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
>
>

Reply via email to