Thanks Christian I think I understand. So before each transactional method (not only persist) you create an EntityManager and then you close it. I'm not sure that you can simplify the JTAEntityManagerHandler class. I think that the only change that we can do is to simplify the pool management removing the ThreadLocal and the using a simple resourcepool. If you want I can try to prepare an example on my trunk.
Giuseppe 2014-11-06 20:20 GMT+01:00 Christian Schneider <ch...@die-schneider.net>: > When the bean is created we would initialize the variable with: > localEm = new ThreadLocal<EntityManager>(); > > We already have an interceptor that runs around transactional methods. > > Before the method call we could do: > EntityManager em = emf.createEntityManager(); > localEm.set(em); > > and after: > EnityManager em = localEm.get(); > em.close(); > localEm.remove(); > > This is of course largely simplified as it does not do error handling, > transaction handling, ... > but I think it would be easy to adjust that. > > Probably we also need to keep the EntityManager and Transaction alive if > there are cascaded transactional calls. > > Honestly I am not fully sure how much better my solution would be compared > to a simple wrapper that does the same internally. > Basically my main concern with the current wrapper is that it does a lot > more than just map each call to the EntityManager to the thread local one. > I wonder if it could be simplified a lot. > > I am also not sure if we really need jpa-container-context or if we could > simply do the work inside the jpa-blueprint module. > > Christian > > Am 06.11.2014 14:07, schrieb Giuseppe Gerla: > > Thanks Christian >> now it's clear the problem and why we cannot use the EMF solution.... >> So let me come back on your second solution. I have some doubt about the >> EntityManager creation. >> Your code posted is only a part of solution. Can you complete it adding >> the initialValue of ThreadLocal implementation? >> >> Regards >> Giuseppe >> >> >> >> >> >> 2014-11-06 13:39 GMT+01:00 Christian Schneider <ch...@die-schneider.net>: >> >> 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 >>> >>> >>> > > -- > Christian Schneider > http://www.liquid-reality.de > > Open Source Architect > Talend Application Integration Division http://www.talend.com > >