9 Replies Latest reply on Apr 7, 2008 11:34 AM by koh

    Listener for CMT commit/rollback

    koh

      I have a requirement where I need to know when a container managed transaction (or bean managed) commits the transaction. I was hoping there would be some kind of Interceptor of Listener system that I could hook into on the TransactionManager but there is nothing obvious that provides this. I've tried to use AOP but the jars in the lib folder do not appear to permit instrumentation.

      Any help is highly appreciated.

        • 1. Re: Listener for CMT commit/rollback
          alrubinger

          You can register your own Synchronization implementation with the current Tx and listen in on "afterCompletion", looking for a status of "success":

          http://java.sun.com/javaee/5/docs/api/javax/ejb/SessionSynchronization.html

          S,
          ALR

          • 2. Re: Listener for CMT commit/rollback
            koh

            Thanks for the reply.

            I have read this only applies to stateful session beans.
            I am using stateless.

            Do you know of anywhere I may obtain an example ?

            • 3. Re: Listener for CMT commit/rollback
              alrubinger

              You may also:

              * Look up the TransactionManager from JNDI (or inject it using @Resource) and register with the Thread's Tx by calling tm.getTransaction().registerSynchronization(). You might want to further abstract this using an Interceptor (AOP) if you want to apply this across many EJBs.

              * If hooking in from an Entity Bean, listen in on an event (ie. PostUpdate) and call event.getSession().getTransaction().registerSynchronization()

              S,
              ALR

              • 4. Re: Listener for CMT commit/rollback
                koh

                Thanks for that, the event triggered OK.

                However, during this event I am attempting to create a manual UserTransaction. Unfortunately the begin() method this is throwing an NotSupportedException, due the fact that even thought the transaction status is COMMITTED the UserTransaction thinks not.

                Not sure how to tackle this one, any ideas ?

                • 5. Re: Listener for CMT commit/rollback
                  alrubinger

                  See, now you're trying to combine BMT and CMT within the same Thread, and in a CMT-enabled context. That's a no-no. :)

                  Haven't tested this technique post-commit, but try marking the method you'd like to call after commit succeeds with @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW). From EJB3 Core Spec:

                  "13.6.2.4" wrote:
                  If a client calls with a transaction context, the container suspends the association of the transaction context with the current thread before starting the new transaction and invoking the business method. The container resumes the suspended transaction association after the business method and the new transaction have been completed.


                  ...or you can perform an asynchronous invocation as outlined in http://docs.jboss.org/ejb3/app-server/reference/build/reference/en/html/jboss_extensions.html or delegate the invocation to JMS for execution by an MDB listener.

                  S,
                  ALR

                  • 6. Re: Listener for CMT commit/rollback
                    koh

                    Makes sense.

                    Your help has been much appreciated.

                    • 7. Re: Listener for CMT commit/rollback
                      alrubinger

                      Great; post back with results when you've got 'em?

                      S,
                      ALR

                      • 8. Re: Listener for CMT commit/rollback
                        koh

                        I've changed the code to use CMT with a TransactionAttributeType.REQUIRES_NEW and it works perfectly.

                        Thanks for you help.

                        • 9. Re: Listener for CMT commit/rollback
                          koh

                          Unfortunately, this solution isn't as straight forward as it may seem.

                          The problem seems to be, when a transaction is COMMITTED, my notification routine may contain code that calls stateless session bean methods.
                          This causes problems (at this stage) due to the container thinking the transaction is still alive and the transaction knowing its now inactive. Thus the container doesn't attempt to start a new transaction.
                          The REQUIRES_NEW gets around this to a certain degree, but I know have the problem if 2 REQUIRES_NEW being attempted.

                          Does anyone know of any callbacks that can be used which will tell me when the container is done as opposed to just the transaction.

                          Any help would be appreciated.