6 Replies Latest reply on Nov 25, 2008 9:12 AM by wolfc

    UserTransactedStartedListener is not implemented in EJB3

      This relates to JBCTS-599 but I can explain it without reference to that.

      There is a little known feature in JavaEE called lazy transaction enlistment.
      It basically works with the UserTransaction where you retrieve a connection
      before starting the transaction and then ut.begin() enlists the connection.

      // BMT EJB(3) method
      public void doSomething()
      {
       DataSource ds = ...
       Connection c = ds.getConnection(); // Not enlisted in transaction, there isn't one
       UserTransaction ut = ...
       ut.begin(); // the connection is enlisted in the transaction
      }
      


      It even works across multiple transactions

      public void doSomething()
      {
       DataSource ds = ...
       Connection c = ds.getConnection(); // Not enlisted in transaction, there isn't one
       UserTransaction ut = ...
       ut.begin(); // the connection is enlisted in the transaction
       ut.commit(); // connections is unenlisted
       ut.begin(); connection is enlisted in the new/different transaction
      }
      


      The problem is that EJB3 is not firing the transaction started events
      from its user transaction.

      Compare EJB2/EJB3:
      org.jboss.ejb.EnterpriseContext/org.jboss.ejb3.tx.UserTransactionImpl

      
       public void begin()
       throws NotSupportedException, SystemException
       {
       TransactionManager tm = con.getTransactionManager();
      
       int oldTimeout = -1;
       if (tm instanceof TransactionTimeoutConfiguration)
       oldTimeout = ((TransactionTimeoutConfiguration) tm).getTransactionTimeout();
      
       // Set the timeout value
       tm.setTransactionTimeout(timeout);
      
       try
       {
       // Start the transaction
       tm.begin();
      
       // HERE!!!!!!!!!!!!! notify checked out connections
       if (tsl != null)
       tsl.userTransactionStarted();
      
       Transaction tx = tm.getTransaction();
       if (trace)
       log.trace("UserTx begin: " + tx);
      


      In fact, if you compare the two classes you'll see that the EJB3
      user transaction is incomplete in other ways (such as resetting
      the transaction timeout after the begin).

        • 1. Re: UserTransactedStartedListener is not implemented in EJB3

          I think the way this does is pretty bad.
          It requires each UserTransaction to implement a static method
          to inject the transaction started listener

           //Registration for CachedConnectionManager so our UserTx can notify
           //on tx started.
           private static ServerVMClientUserTransaction.UserTransactionStartedListener tsl;
          
           /**
           * The <code>setUserTransactionStartedListener</code> method is called by
           * CachedConnectionManager on start and stop. The tsl is notified on
           * UserTransaction.begin so it (the CachedConnectionManager) can enroll
           * connections that are already checked out.
           *
           * @param newTsl a <code>ServerVMClientUserTransaction.UserTransactionStartedListener</code> value
           */
           public static void setUserTransactionStartedListener(ServerVMClientUserTransaction.UserTransactionStartedListener newTsl)
           {
           tsl = newTsl;
           }
          


          Then the cached connection manager (CCM) needs to know about all listeners:
          
           protected void startService()
           throws Exception
           {
           tm = (TransactionManager) getServer().getAttribute(transactionManagerServiceName,
           "TransactionManager");
           TransactionSynchronizer.setTransactionManager(tm);
           ServerVMClientUserTransaction.getSingleton().registerTxStartedListener(this);
           EnterpriseContext.setUserTransactionStartedListener(this);
           }
          


          It would be much better if the CCM had a single place to register the listener
          and then each UserTransaction notified that single place of transaction start.

          • 2. Re: UserTransactedStartedListener is not implemented in EJB3

            NOTE: The embedded UserTransactions has the same problem.

            • 3. Re: UserTransactedStartedListener is not implemented in EJB3
              wolfc

              http://jira.jboss.com/jira/browse/EJBTHREE-1028

              I'll ignore the embedded user transaction for the moment. It will either be removed or deprecated.

              • 4. Re: UserTransactedStartedListener is not implemented in EJB3
                wolfc

                Why is EJB2UserTransactionProvider not part of the transaction-spi?

                Shouldn't the EJB2UserTransactionProvider bean define a dependency on the UserTransactionRegistry?

                • 5. Re: UserTransactedStartedListener is not implemented in EJB3

                   

                  "wolfc" wrote:
                  Why is EJB2UserTransactionProvider not part of the transaction-spi?

                  Shouldn't the EJB2UserTransactionProvider bean define a dependency on the UserTransactionRegistry?


                  No its an incallback.

                   <bean name="UserTransactionRegistry" class="org.jboss.tm.usertx.UserTransactionRegistry">
                  
                  THIS REGISTERS ALL USER TRANSACTION PROVIDERS
                  
                   <!-- Register providers -->
                   <incallback method="addProvider"/>
                   <uncallback method="removeProvider"/>
                  
                  THIS REGISTERS THE LISTENERS (Currently only the CCM)
                  
                   <!-- Register listeners -->
                   <incallback method="addListener"/>
                   <uncallback method="removeListener"/>
                   </bean>
                  


                  That way you can remove the ejb and jca configs without having to redo
                  the other configurations.

                  • 6. Re: UserTransactedStartedListener is not implemented in EJB3
                    wolfc

                    So the moment UserTransactionRegistry comes online all already installed providers are also added?