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

Reply via email to