3 Replies Latest reply on Aug 6, 2019 4:31 PM by nimo stephan

    @ApplicationScoped with container managed EntityManager

    nimo stephan Master

      I have an @ApplicationScoped bean injecting a container managed EntityManager:

       

      @ApplicationScoped
      public class EntityFacade{
      
      // inject container managed entityManager
      @PersistenceContext
      private EntityManager em;
      
      public void persist(User u){
      em.persist(u);
      }
      
      ...
      
      }

       

      If other beans are injecting this EntityFacade simultanously with

       

      @Inject EntityFacade entityFacade

       

      will Wildfly provide different entityManagers for each different thread or will it be the same entityManager for each simultanously running thread?

       

      Do I get a thread safe entityManager with the solution above?

       

      Normally, such EntityFacade should be annotated with @Stateless, but why? I cannot see any benefit in using @Stateless instead of @ApplicationScoped (@Stateless uses different intances from the pool->more memory, etc, while @ApplicationScoped can be accessed concurrently).

        • 1. Re: @ApplicationScoped with container managed EntityManager
          nimo stephan Master

          There is another thread asking the same Application Scoped POJO vs Stateless Session Bean, however, the thread is over 10 years old and nobody answered it;/

           

          But I found this:

           

          Concurrency issue: Aren't application scoped components threadsafe?

           

          with the relevant statement from swd847 :

           

          >Your bean should be in the STATELESS pseudo scope, not in the application scope.

          Client 1 accesses bean, entityManager is injected
          Client 1 starts doing entityManager stuff
          Client 2 access bean, client 1s entitymanager is replaced by client 2's entitymanager
          Client 2 does entityManager stuff, and so does client 1, both using the same EntityManager.

           

          Depending on the actual ordering of these requests, the hibernate error message will be different each time.

           

          However, I am wondering if this statement from swd847 is still valid.

           

          Wildfly uses a EntityManager-Proxy which is resolved to a thread-safe EntityManager-Delegate. So the delegate is bound to only one thread and does not change through other threads accessing the same bean. And I dont get any hibernate errors when the entityManager from my @ApplicationScoped-Bean is used simultanously by running threads. However, I am unsure.

           

          Can anyone confirm my assumption?

          • 2. Re: @ApplicationScoped with container managed EntityManager
            Scott Marlow Master

            If you update your standalone.xml to enable TRACE logging for org.jboss.as.jpa, the trace output will tell you when a new EntityManager is being created (including the thread name that it is created on).  The purpose of the org.jboss.as.jpa TRACE output, is for showing you what is going on internally for container managed EntityManager. 

             

            I'll try to answer what should happen, using the same terminology as Stuart Douglas used that you quoted above:

             

            With just Client 1 accessing the bean, the EntityManager-Proxy is invoked.  When the EntityManager-Proxy instance is called within a JTA transaction TX-1 for the first time,  a new underlying (Hibernate) EntityManager instance is created and associated with the TX-1 transaction (via TransactionSynchronizationRegistry).  For the remaining calls from Client 1 with transaction TX-1, that same underlying (Hibernate) EntityManager instance is reused.  After the TX-1 transaction is (completely) ended (whether rollback or commit), the underlying (Hibernate) EntityManager is closed.

             

            With Client 2 accessing the bean, Client 2 will have its own TX-2 transaction and each call to the EntityManager-Proxy instance, will use a different underlying (Hibernate) EntityManager instance.  Again, the underlying (Hibernate) EntityManager instance is cached to the TX-2 transaction via TransactionSynchronizationRegistry.

             

            The org.jboss.as.jpa TRACE output will give you concrete confirmation that what is described above, is what happens for your application.  The TRACE output will clearly indicate whether the underlying (Hibernate) EntityManager is found in the active JTA transaction or if a new underlying (Hibernate) EntityManager is created for the invocation.

             

            If your bean is not using JTA transactions for some calls to the EntityManager-Proxy, a new underlying (Hibernate) EntityManager instance is created for each of your calls to the EntityManager-Proxy, so that should also be thread safe.

             

            In case you like to see some source code, the EntityManager-Proxy source is here (class name is TransactionScopedEntityManager, not actually EntityManager-Proxy).

             

            Scott

            • 3. Re: @ApplicationScoped with container managed EntityManager
              nimo stephan Master

              Thanks. So I am right with my assumption.

               

              To sum up:

               

              1. There is only one EntityManager-Proxy instance which resolves to different entityManager-Delegates for each calling thread.

              2. With JEE managed EntityManager, we can use this:

               

              @ApplicationScoped 
              public class EntityFacade{ 
               
              // inject container managed entityManager  (THIS IS THREAD-SAFE!)
              @PersistenceContext 
              private EntityManager em; 
               
              public void persist(User u){ 
              em.persist(u); 
              }