8 Replies Latest reply on Jan 22, 2009 11:06 AM by marklittle

    JTA/JTS thread disassociation semantics

    jhalliday

      With the local JTA impl, Transaction.[commit()|rollback()] don't do Thread disassociation, whilst TransactionManager.commit()|rollback()] do. Thus

      transactionmanager.begin();
      transactionmanager.getTransaction().rollback();
      transactionmanager.getStatus();

      results in STATUS_ROLLEDBACK. Which is all well and good.

      Now substitute the JTS implementation and run the same code again.

      Any guesses?

      yup, that right: STATUS_NO_TRANSACTION.

      This is compliant with the JTA spec, which mandates thread disassociation for the TransactionManager but says nothing about Transaction.

      On the other hand its got the potential to break things. Indeed it does break the JCA, which has transaction context checking on the connections which is insufficiently robust to cope with this.

      So, do we change the JTS or just document it and move on?

        • 1. Re: JTA/JTS thread disassociation semantics
          marklittle

          This is moot now, correct :-) ?

          • 2. Re: JTA/JTS thread disassociation semantics
            jhalliday

            OK, JBTM-474 seems to have helped somewhat. There is still an issue with some of the JCA tests[1] that use the following cleanup code:

            if (!TxUtils.isCompleted(tm))
            {
            tm.rollback();
            fail("Tx was still active");
            }

            rollback is called, which is correct - it's needed to ensure thread disassociation. Note that the test is broken even for the JTA case, since there may be a complete tx associated to the thread and the rollback call is needed to disassociate it even if it's already rolled back. But in the JTS case since it can't determine the tx rolled back, rollback throws an exception rather than silently working as the JTA version does.

            The issue here is that a timedout JTS tx is removed at the point it times out so thereafter its status cannot be determined. For some use cases (where the client and server are collocated) we could cache the outcome at the point the tx is removed, allowing getStatus and rollback|commit to behave more similarly to the JTA version.

            But that won't work in distributed cases, since the tx is remote which means we either need it to hang around as long as a client has a handle on it (i.e. it's a distributed gc problem) or we need to notify all the clients of the outcome when it terminates (i.e. communication overhead). Neither of these appeal.

            Thus the JCA test is going to have to change anyhow to cope with the distributed case.

            It seems to me that what the test is really in interested in is: did the tx timeout as expected. It could either register a sync and use that to set a status flag, or rely on isActive() rather than !isCompleted. Either way it needs an exception handler around tm.rollback, since that call is going to throw an exception.

            [1] org.jboss.test.jca.test.TxConnectionManagerUnitTestCase
            methods testSynchronizationAfterCompletionTxTimeout
            testGetManagedConnectionTimeoutTrackByTx
            testGetManagedConnectionTimeout

            • 3. Re: JTA/JTS thread disassociation semantics
              marklittle

              Yes, we can definitely cache the last known status in some cases, but it's not a complete solution as you outline. I agree that the test should be changed to cope with the uncertainties inherent when you add distribution in to this.

              • 4. Re: JTA/JTS thread disassociation semantics
                marklittle

                 

                "jhalliday" wrote:

                But that won't work in distributed cases, since the tx is remote which means we either need it to hang around as long as a client has a handle on it (i.e. it's a distributed gc problem) or we need to notify all the clients of the outcome when it terminates (i.e. communication overhead). Neither of these appeal.


                As long as the ORB is a good CORBA citizen it should throw OBJECT_NOT_EXIST and (now) we catch that are translate it to rolled back. So hopefully that'll close some of the holes here too. But the test is still suspect :-)

                • 5. Re: JTA/JTS thread disassociation semantics
                  jhalliday

                  So in the case of a commit from another thread the object hangs around rather than getting thrown away? Otherwise the translation is suspect...

                  • 6. Re: JTA/JTS thread disassociation semantics
                    marklittle

                    No, if a compliant ORB is supposed to throw OBJECT_NOT_EXIST if there's a call on a reference/IOR to a non-persistent instance that it can no longer find. This is different to, say, COMM_FAILURE or one of the other low-level SystemExceptions. In the case of a timeout the transaction will be garbage collected and remove itself from the POA, which will mean any outstanding requests from remote clients should (assuming the ORB works) get back OBJECT_NOT_EXIST.

                    BTW, if this is an answer to a different question, let me know ;-)

                    • 7. Re: JTA/JTS thread disassociation semantics
                      jhalliday

                      I'm not arguing with the ORB's behavour, I'm arguing about the way the transaction service sat on top of the ORB translates that. If a client gets an OBJECT_NOT_EXIST it only knows the tx went away, not what state the tx was in. Assuming rollback is unreasonable - it may just as easily have committed via another thread or a different JVM.

                      • 8. Re: JTA/JTS thread disassociation semantics
                        marklittle

                        Yes well welcome to the world of presumed abort and checked transaction semantics. Although the OTS doesn't mandate them or which implementation you use, it assumes they're in place. (In fact we allow the terminator to be nulled-out to prevent this situation.) So realistically the status depends on the checking that's in place at runtime.