Of course using the EntityManagerFactory is a possible and working way.
The problem is that it creates a lot of boilerplate code.
// This is how persist looks in JEE container managed persistence
public void updateTask(Task task) {
em.persist(task);
}
// This is halfway correct handling of transactions and em
lifecycle for plain java
public void updateTaskEmf(Task task) {
userTransaction.begin();
EntityManager em = emf.createEntityManager();
try {
em.persist(task);
userTransaction.commit();
} catch (RuntimeException e) {
userTransaction.rollback();
throw e;
} finally {
em.close();
}
}
As you see you need a lot of code around your business functionality to
handle EntityManager lifecycle and transactions. It becomes even more
complex if you
assume cascaded transactions where you have one transacted method that
calls other transacted methods. There you also want the EntityManager to
life throughout the cascaded transaction so you can do different changes
to persistent entities in the same em session before you finally commit.
So this is the reason why JEE does container managed persistence and
also the reason why we wrap the EntityManager in aries.
I proposed ThreadLocal to make it more obvious that EntityManager is not
thread safe and each thread will use its own instance. We do a similar
thing inside the wrapped EntityManager that jpa-container-context
creates but I think it is not good to hide that fact too much.
This is how we currently wrap the EntityManager:
https://github.com/apache/aries/blob/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/impl/JTAEntityManagerHandler.java
As you see there is a lot of special processing for the different calls
to EntityManager. Some calls we even swallow. My hope is that with a
plain EntityManager inside a ThreadLocal most of that complexity can be
removed. After all it is pretty difficult to prove that our current
wrapping solution works correctly in all imaginable cases.
The wrapping is also especially difficult as we handle JPA 2.0 and 2.1
at the same time as we have to wrap two different versions of the
EnitityManager interface.
Christian
On 06.11.2014 12:36, Giuseppe Gerla wrote:
Hi Christian
I am not an expert on JTA, so for me it is not fully clear the problem
you're facing.
From my experience I can say, however, that the use of ThreadLocal is not
recommended.
From my point of view, it would be better to use something like this:
@Singleton
@Transactional
public class TaskServiceImpl implements TaskService {
EntityManagerFactory emf;
public void updateTask(Task task) {
emf.createEntityManager().persist(task);
}
}
Regards
Giuseppe
--
Christian Schneider
http://www.liquid-reality.de
Open Source Architect
http://www.talend.com