8 Replies Latest reply on Jul 10, 2007 4:45 AM by marklittle

    Callback on transaction end

    zetzioni

      Hi,

      Is there a way to tell when a transaction (in CMT) is completed, either commit or rollback?

      The problem I'm trying to solve is this:

      As part of a method foo() that either starts a new transaction or joins an existing one I have to lock some resource. In order to avoid race condition I must release the resource only when commit or rollback is made. Since it is not guaranteed that the commit/rollback will happen at the end of the method, I wonder if there's some callback indicating that the commit/rollback of the current transaction has taken place.

      Thanks.

        • 1. Re: Callback on transaction end
          jhalliday

          A Synchronization's afterCompletion method would be a good place to put your lock release code, assuming that the locks are not persistent. However, registering Synchronizations requires access to the TransactionManager, which is not usually allowed for application code.

          The new TransactionSynchronizationRegistry would be ideal, but that won't be available (in a JEE compliant way at least) until JBossAS 5.0. How would you feel about a non-JEE compliant, vendor specific solution in the meanwhile?

          • 2. Re: Callback on transaction end
            zetzioni

             

            "jhalliday" wrote:
            A Synchronization's afterCompletion method would be a good place to put your lock release code, assuming that the locks are not persistent. However, registering Synchronizations requires access to the TransactionManager, which is not usually allowed for application code.

            The new TransactionSynchronizationRegistry would be ideal, but that won't be available (in a JEE compliant way at least) until JBossAS 5.0. How would you feel about a non-JEE compliant, vendor specific solution in the meanwhile?


            Well, I'd prefer not to use proprietary APIs unless forced to. As well we're using JBoss 4.x in the meantime. What I'm wondering is if it's a problem whose root is in something I'm doing wrong. It seems like a general issue when working with CMT and needing to lock some resource, and release that lock when commit/rollback is done.

            How is the transaction manager accessed? how do you register synchronization? any example code would be greatly appreciated.

            Thanks.

            • 3. Re: Callback on transaction end
              marklittle

              Your locks should be released by transaction participants. Register a participant with the transaction (an XAResource). Then you'll know when the transaction has completed and can release your locks. That's the way you should do it to get two-phase locking: necessary to ensure you don't end up in a cascade rollback situation. Without boring you further ;-) you're supposed to make it appear as though any locks held during the transaction are released instantaneously, so you'd do that within a two-phase aware participant during the commit or rollback.

              As Jonathan points out, you could use Synchronizations, but afterCompletion isn't guaranteed to be called. It's a convenience method.

              • 4. Re: Callback on transaction end
                marklittle

                Hit return too soon:

                Oh and yes I know: these APIs aren't normally available to you via CMT ;-)

                Vendor specific extensions are probably your best route at the moment.

                • 5. Re: Callback on transaction end
                  zetzioni

                   

                  "mark.little@jboss.com" wrote:
                  Hit return too soon:

                  Oh and yes I know: these APIs aren't normally available to you via CMT ;-)

                  Vendor specific extensions are probably your best route at the moment.


                  Thanks mark. So let me verify I got you correctly.

                  Do you mean that I need to make a XAResource (the bean with method foo?) and then enlistResource with it on the transaction object, and then in the implementation of end(), release the lock? - in case all of this is correct, I guess this is also not portable as you suggest, right?

                  Thanks.

                  • 6. Re: Callback on transaction end
                    marklittle

                    If you retain transactional locks then you should not release them until the transaction commits or rolls back. If serializability is enabled on your backend db, it's doing this for you with locks you may have implicitly grabbed. What you're doing is obtaining application level locks, but the requirement is still the same: they shouldn't be released until the transaction terminates.

                    If you had access to the Transaction object in a portable manner and could enlist an XAResource to manage your locks, then that's how it should be implemented. But from what you've said about your scenario, that's not possible. I suspect you'll have to take the non-portable hit. But as long as you structure your application so the non-portable code is in a well defined place, it should be easy to move to another deployment environment once you write the non-portable code for that environment.

                    • 7. Re: Callback on transaction end
                      mr_dronski

                      Not trying to interrupt a party, but a standard Stateful Session Bean implementing a SessionSynchronization interface would provide these callbacks in a portable fashion. The use of SFSB in every single application, is of course, questionable...

                      • 8. Re: Callback on transaction end
                        marklittle

                         

                        "mr_dronski" wrote:
                        Not trying to interrupt a party, but a standard Stateful Session Bean implementing a SessionSynchronization interface would provide these callbacks in a portable fashion. The use of SFSB in every single application, is of course, questionable...


                        You're right, but if it's implemented using an underlying Synchronization, then you've no guarantee for afterCompletion to be called in the event of failures. Not a problem if the TM is co-located with the AS and you assume crash failures, but if the TM is remote and it crashes, then you'll be left in limbo with no recovery on Synchronizations from the TM even when it comes back.