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

2014-11-06 11:03 GMT+01:00 Christian Schneider <ch...@die-schneider.net>:

> Currently in jpa-container-context we wrap the EntityManager to ensure we
> provide it in a thread safe way.
>
> This is to emulate a usage pattern like in JEE where a pool of EntityBeans
> are kept and the container guarantees that no two threads access the same
> bean at the same time. I think this approach is difficult to get right and
> also quite complicated to implement. It is also conceptually bad as the
> EntityManager interface never was designed to be used in a thread safe way.
>
> So I wonder if we could use a different approach on the client side to
> make this easier.
>
> 1. So one approach would be to use Java 8 lambdas to make the
> entitymanager usage thread safe and transactional. It could look like this:
> public void update(Task task ) {
>     peristenceManager.transactional(Required, em -> em.persist(task));
> }
>
> persistenceManager would be initialized once with the EntityManagerFactory
> and the TransactionManager.
>
> The advantage of this approach is that we do not need any wrapping at all.
> We can simply create the EntityManager at the start of the "transactional"
> method and close it in the end. We can also do the transaction handling
> there. We also need no interceptors. So we do not need to proxy the bean
> class.
>
> The downside is that it is a little bit more verbose than annotation based
> transactions and that it requires Java 8.
>
> 2. Another approach would be to store the EntityManager visibly in a
> ThreadLocal in the client code:
>
> @Singleton
> @Transactional
> public class TaskServiceImpl implements TaskService {
>     ThreadLocal<EntityManager> localEm;
>
>     public void updateTask(Task task) {
>         emLocal.get().persist(task);
>     }
> }
>
> The advantage here is that it does not need Java 8 and is a bit less
> verbose than 1. Compared to our current solution the advantage would be
> that we need no special
> wrapping of the EntityManager. Before the call to updateTask we use an
> interceptor to make sure the transaction is set up correctly and we create
> the EntityManager for the thread. After the call we close the EntityManager
> and handle the eventual commit or rollback.
>
> The downside here is that it still needs an interceptor for transaction
> handling and to make sure localEm contains a valid EntityManager for the
> current Thread.
>
> Solution 2 could also be introduced without creating additional blueprint
> elements. We could simply detect that we inject into a ThreadLocal and act
> accordingly.
>
> So WDYT?
>
> Christian
>
>
> --
> Christian Schneider
> http://www.liquid-reality.de
>
> Open Source Architect
> http://www.talend.com
>
>

Reply via email to