6 Replies Latest reply on Jan 19, 2005 11:21 AM by adrian.brock

    Distributed transaction and Message Driven Bean

    wengatz_n

      Hi,


      we have been playing around with Message Bean to investigate how a distributed transaction works in
      an asynchronous way. But we could not make that working.


      Basically we have the following example:

      1) BankFacade - a stateless session Bean

      2) OracleAccountMDB - a message driven bean which internally invokes a OracleAccountEntityBean

      3) MySqlAccountMDB - similar to the above but invokes MySqlAccountEntityBean

      4) OracleAccountEntityBean and MySqlAccountEntityBean manages a bank account table in oracle and mysql respectively



      In BankFacade session Bean, there is a method call transfer which transfer 100 Euro from account in MySql to that in Oracle.
      Both MDBs are configured to use Container Managed transactions.



      Test Case:

      1) Configure BankFacade to use Bean Managed Transaction,

      2) In transfer method, explicitly get a UserTransaction and start a new transaction,

      3) Send messages to tell OracleAccountMDB to deposit money and MySqlAccountMDB to withdraw money;

      4) Once it?s done, call Rollback to rollback the whole transaction OR (other scenario) let one of the Entity Beans throw an exception.

      The result is the transaction is Committed instead.


      Is there a way to propagate the transaction from the Session Bean BankFacade to the MessageDrivenBeans?



      Thanks and best regards

      Nicole

        • 1. Re: Distributed transaction and Message Driven Bean

          No. And it is deliberatly designed/speced that way.
          Otherwise it wouldn't be asynchronous.
          A sender and receiver's tranasctions are quite independent and may be separated
          both spatially and temporily.

          • 2. Re: Distributed transaction and Message Driven Bean

            Besides MySQL doesn't even support XA.

            • 3. Re: Distributed transaction and Message Driven Bean
              zhangpeng_ca

              Hi Adrian,

              Thanks for you information. It is understood that: Transaction propagation context will not be transfered through messages like Session Bean and Stateless Bean do;

              But we have a scneario that to make two asynchorously responded services in one transaction. That's the reason we do the above mentioned test.

              My impression is that in theory, as long as we have a means to propagte the transaction context and associate transaction context with the service thread, it should be working no matter whether we are using synchronus call or asynchorous call. Does it make sense to you?

              Following that logic, I was trying to implement the following logic, but it still didn't work:
              1) On client side,
              UserTransaction trans = (UserTransaction)
              initialContext.lookup("UserTransaction")
              .narrow(o, UserTransaction.class);
              trans.begin();

              // By converting to JBoss clientUserTransaction,
              // I could get TPC (TransactionPropagationContext)
              ClientUserTransaction jbossTransImpl =
              (ClientUserTransaction)trans;
              Object tpc = jbossTransImpl.getTransactionPropagationContext();

              // Send this tpc via JMS message to a MessageDrivenBean
              ...

              trans.rollback();

              2) On MessageDrivenBean side in onMessage method
              // Unpack message and get tpc object

              // Use TPC Importer to import tpc into a transaction
              TransactionPropagationContextImporter
              tpcImporter = (TransactionPropagationContextImporter)
              initialContext.lookup("java:/TransactionPropagationContextImporter");
              Transaction trans = tpcImporter.importTransactionPropagationContext(tpc);

              // Use JBoss Transaction Manager to associate the transaction to the current Thread
              TransactionManager
              tpcImporter = (TransactionManager)
              initialContext.lookup("java:/TransactionManager");
              TxManager jbossTx = (TxManager)tx;
              jbossTx.associateThread(trans);

              // Call another EntityBean, hopefully the TransactionContext propagtion could be handled by JBoss container


              Do you see it should be working?

              Thanks

              Peng

              • 4. Re: Distributed transaction and Message Driven Bean

                Your question has little to do with JMS (other than you are sending a TPC in a JMS message).

                What you are doing might be made to work, but there are many other considerations
                you haven't taken into account (at least from the information on your post).
                e.g.
                1) A JTA transaction cannot be actively associated with two threads at the same time
                there are basic assumptions where the tx is assumed to be per
                thread when ensuring thread safety
                2) You need a mechanism for the commit to wait for the asynchronous stuff to complete,
                otherwise all bets are off
                3) You need to tidyup thread association (suspend)
                4) If you want to see how to do things properly look at the JRMPInvoker and
                TxInterceptorCMT (import/suspend/resume, etc)
                5) It is not spec compliant. You are using methods that are either non spec
                or aren't intended for use by applications including javax.transaction.TransactionManager

                • 5. Re: Distributed transaction and Message Driven Bean
                  zhangpeng_ca

                  Yes, I agree with you that my question has little to do with JMS. And I was just trying to use it as an example to find out what need to be done if I want a distributed transaction span over two asynchronously invoked services/components.

                  The most important point you made (and thanks for bringing it up) is that a JTA transaction cannot be actively associated with two threads at the same time. And suspend and resume should be used to tide up the participants to make sure only one particant is actively involved in a JTA transaction.

                  I would like to elaborate why I'm looking at this if you don'y mind. We currently have a project. And for some other reasons, we decided to not use EJB and all our services should be accessed asychronously through messages. But there are some cases that we need two service invocations involved in one global atomic transaction. We don't want to build our transaction service our own and are trying to investigate if we could use a JTA based transaction service already included in an application server like JBoss.

                  I feel that the point - a JTA transaction cannot be actively associated with two threads at the same time - is too strong. Is it part of a JTA spec or just because of implementation limitation?

                  And it will be very difficult to tide up the association of a JTA transaction if the involved services are called asynchronously.

                  Do you see it the same way? And do you think JTA is an option to achieve the requirements of our project? Or should we should look at WS-Transaction?

                  Yes, another concern I have (as you've pointed out) is spec-compliance. My impression is that JTA doesn't specify how transaction context is propagated and associated with a thread. So this could be another factor to determine if we could use JTA.

                  Many thanks!

                  Peng

                  • 6. Re: Distributed transaction and Message Driven Bean

                    Can I refer you to the specifications. You will need to read them if you are
                    attempting to bypass the spec defined assumptions/behaviours.

                    You will find lots to read.... :-)

                    I will also repeat, your question is also off topic for the JMS forum.

                    The basics are:
                    JTA - java mapping of XA/Open describes one transaction manager model
                    JTS - java mapping of OTS another transaction manager model
                    J2EE - Overview of J2EE platform
                    EJB - EJB programming model (read the part about transaction diamonds)

                    To answer part of your question very quickly, but more accuratly than my
                    original post:

                    JTA can either be implemented directly or it can be a mapping on top of another
                    TM implemetnation (e.g. JTS/OTS).

                    OTS allows multiple active threads/transaction but also defines separate
                    behaviour for a reconciliation stage of those threads before transaction commit.

                    The JTA spec also allows this behaviour, but it also allows the opposite,
                    i.e. only the originator thread can do work/commit the transaciton.

                    The JTA spec does not define a reconcilation (leaving it to the TM implementation
                    which is usually OTS underneath - but not in JBoss's case).
                    Well actually it does implicitly in that it assumes a single thread of control
                    (negating the need for a reconciliation).

                    The EJB spec does not allow this behaviour (diamonds mentioned above)
                    but recognises that the AS cannot detect every occurance of this pattern.