5 Replies Latest reply on Feb 4, 2013 1:03 PM by tomjenkinson

    EnityManager.close() before or after JTA afterCompletion()?

      Hi,

       

      See as a reference the https://community.jboss.org/message/794633#794633 thread.


      In an application server, that is JavaEE 6 compliant, which of EntityManager.close() and JTA Synchronization.afterCompletion() should be closed first?

       

      Based on the persistence specification:

       

      7.9.1 Container Responsibilities:

      After the JTA transaction has completed (either by transaction commit or rollback), The container closes the entity manager by calling EntityManager.close.

       

      I am using DataNucleus (DN) 3.2 as a Persistence provider, and DN expects the Transaction afterCompletion() to be triggered BEFORE the EntityManager.close().  It seems that the opposite is triggered by JBoss.  So I wonder if both are correct or if one should be called before another based on either JTA or Persistence JSRs?

       

      Based on the thread dump, arjuna calls first:

      at org.datanucleus.api.jpa.JPAEntityManager.close(JPAEntityManager.java:194)

      at org.jboss.as.jpa.transaction.TransactionUtil$SessionSynchronization.afterCompletion(TransactionUtil.java:193)

       

      (EntityManager.close() is called first)

       

      Then JTA after completion:

      at org.datanucleus.TransactionImpl.internalPostCommit(TransactionImpl.java:563)

                  at org.datanucleus.JTATransactionImpl.afterCompletion(JTATransactionImpl.java:429)

                  at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.afterCompletion(SynchronizationImple.java:96)

       

      Thanks

        • 1. Re: EnityManager.close() before or after JTA afterCompletion()?
          tomjenkinson

          Hi Seyvet,


          I wouldn't want to comment on whether afterCompletion is the right place to call close for JPA, the thread you reference is probably the best place to discuss that. We are more concerned with raw transactions rather than resource manager or synchronization implementations in this forum.

           

          This is sort of a transaction manager in a nutshell:

           

          Tx::enlistResource(RM rm)

          Tsr::registerInterposedSynchronization(S s)

          Tx::registerSynchronization(S s)

          Tx::commit()

          foreach Synchronization

             s::beforeCompletion();

          foreach InterposedSynchronization

             s::beforeCompletion();

          foreach ResourceManager

             rm::prepare()

          foreach ResourceManager

             rm::commit()

          foreach InterposedSynchronization

             s::beforeCompletion();

          foreach Synchronization

             s::afterCompletion();

           

          Is there a part of that algorithm that you would like to explore more with me in the context of JPA?

           

          Tom

          • 2. Re: EnityManager.close() before or after JTA afterCompletion()?

            Thanks Tom,

             

            Yes please!

             

            The question is about the following sequence where after the transaction is committed:

            1) The container will first invoke the JPA persistence provider as indicated by this first callback:

            at org.datanucleus.api.jpa.JPAEntityManager.close(JPAEntityManager.java:194)

            at org.jboss.as.jpa.transaction.TransactionUtil$SessionSynchronization.afterCompletion(TransactionUtil.java:193)

            at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.afterCompletion(SynchronizationImple.java:96)

            at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.afterCompletion(TwoPhaseCoordinator.java:402)

             

            2) Which is then followed by a second callback (JTA related this time) from the container:

            at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.afterCompletion(SynchronizationImple.java:96)

                        at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.afterCompletion(TwoPhaseCoordinator.java:402)

                        at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:103)

                        at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162)

                        at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1165)

                        at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:126)

                        at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:75)

             

            The questions:

            - Is this order defined by JBoss?

            - Can this order be modified?

            • 3. Re: EnityManager.close() before or after JTA afterCompletion()?
              tomjenkinson

              Hi Seyvet,

               

              If you look at those two stack traces you can see a common line:

               

              at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.afterCompletion(TwoPhaseCoordinator.java:402)

               

              The only ordering that can be guaranteed is for interposed synchronizations (registered by the TransactionSynchronizationRegistry):

              http://docs.oracle.com/javaee/5/api/javax/transaction/TransactionSynchronizationRegistry.html#registerInterposedSynchronization%28javax.transaction.Synchronization%29

               

              There was a little mistype in my original response which I will now refactor in the original to say:

               

              ...

              foreach ResourceManager

                 rm::commit()

              foreach InterposedSynchronization

                 s::beforeCompletion();

              foreach Synchronization

                 s::afterCompletion();

               

              i.e. When it comes to afterCompletion, interposed synchronizations will be called *first* which is one way (if you only have two synchronizations ) to guarentee order.

              • 4. Re: EnityManager.close() before or after JTA afterCompletion()?

                In DataNucleus, the JTA transaction is registered as an interposed transaction, does that mean the JPA one is also interposed?

                 

                Should not that be specified in some spec?

                • 5. Re: EnityManager.close() before or after JTA afterCompletion()?
                  tomjenkinson

                  Hi,

                   

                  The ordering of interposed vs none-interposed is speced in JTA, in terms of whether JPA should be interposed or not I am not sure, perhaps it is?

                   

                  Tom