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