4 Replies Latest reply on Apr 9, 2004 3:52 AM by stephanenicoll

    MDB and container managed transactions

      I have been trying to make an MDB get a message and send it to another queue in the context of a transaction. It seems that I got stuck on the fact that JBoss does not run my MDB in the context of a transaction.

      from ejb-jar.xml

      <ejb-jar >
       ...
       <enterprise-beans>
      
       <message-driven >
       <description>[CDATA[]]</description>
      
       <ejb-name>TrxMDB</ejb-name>
      
       <ejb-class>mypackage.foo.TrxMDB</ejb-class>
      
       <transaction-type>Container</transaction-type>
       <message-driven-destination>
       <destination-type>javax.jms.Queue</destination-type>
       </message-driven-destination>
      
       </message-driven>
       </enterprise-beans>
       <assembly-descriptor >
       <container-transaction>
       <method>
       <ejb-name>TrxMDB</ejb-name>
       <method-name>*</method-name>
       </method>
       <trans-attribute>Required</trans-attribute>
       </container-transaction>
       </assembly-descriptor>
      <ejb-jar >
      


      So in the MDB my test for running inside a transaction fails:

      public void onMessage(Message message)
      {
      // ctx is a member variable that stores the message driven context
      boolean res = ctx.getRollbackOnly());

      // ...
      }

      This will throw an exception informing me that my function call is illegal since I am not running inside a transaction.

      I am really puzzled here. Why am I not running inside a transaction when my deployment descriptor specified otherwise?

      Thanks,
      Florian

        • 1. Re: MDB and container managed transactions

          Your config looks correct to me.

          Which version of JBoss are you using?
          There was a bug in earlier versions of JBoss where it looked for
          onMessage() instead of onMessage(Message) in the config, but that
          shouldn't affect you since you are using a generic.

          Add TRACE logging for org.jboss.ejb.plugins and post the results.
          You should see the attribute JBoss thinks it is configured with.

          I have almost exactly the same config in one of my tests that definitly works:

          <?xml version="1.0" encoding="UTF-8"?>
          
          <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">
          
          
          
          <ejb-jar >
          
           <enterprise-beans>
          
           <message-driven >
          
           <ejb-name>test/mdb</ejb-name>
          
           <ejb-class>test.mdb.TestMDBBean</ejb-class>
          
           <transaction-type>Container</transaction-type>
          
           <message-driven-destination>
          
           <destination-type>javax.jms.Queue</destination-type>
          
           <subscription-durability>NonDurable</subscription-durability>
          
           </message-driven-destination>
           <resource-ref>
           <res-ref-name>standalone/test</res-ref-name>
           <res-type>javax.sql.DataSource</res-type>
           <res-auth>Container</res-auth>
           <res-sharing-scope>Shareable</res-sharing-scope>
           </resource-ref>
          
           </message-driven>
          
           <message-driven >
          
           <ejb-name>test/dlq</ejb-name>
          
           <ejb-class>test.mdb.TestMDBBean</ejb-class>
          
           <transaction-type>Container</transaction-type>
          
           <message-driven-destination>
          
           <destination-type>javax.jms.Queue</destination-type>
          
           <subscription-durability>NonDurable</subscription-durability>
          
           </message-driven-destination>
          
           </message-driven>
          
           </enterprise-beans>
          
           <assembly-descriptor >
          
           <container-transaction>
          
           <method>
          
           <ejb-name>test/mdb</ejb-name>
          
           <method-name>*</method-name>
          
           </method>
          
           <trans-attribute>Required</trans-attribute>
          
           </container-transaction>
          
           <container-transaction>
          
           <method>
          
           <ejb-name>test/dlq</ejb-name>
          
           <method-name>*</method-name>
          
           </method>
          
           <trans-attribute>Required</trans-attribute>
          
           </container-transaction>
          
           </assembly-descriptor>
          
          
          
          </ejb-jar>
          
          


          Regards,
          Adrian

          • 2. Re: MDB and container managed transactions

            Thanks!

            I double checked everything and it looks like it is finally working. I really do not have a good explanation on how it all started working. Now I have a new problem. I am using this code in the MDB that now it runs inside a transation:

            InitialContext ctx = JndiContextFactory.getLocalContext(); // this is a helper JNDI class

            XAQueueConnectionFactory queueConnectionFactory = (XAQueueConnectionFactory)ctx.lookup("XAConnectionFactory");

            XAQueueConnection queueConnection = queueConnectionFactory.createXAQueueConnection();
            XAQueueSession queueSession = queueConnection.createXAQueueSession();

            Queue queue = (Queue) ctx.lookup("queue/queueName");
            QueueSender queueSender = queueSession.getQueueSession().createSender(queue);

            queueSender.send(message);

            queueSender.close();
            queueSession.close();
            queueConnection.close();


            The MDB gets executed but I never see the message in the new queue that it is sent to. Basically I even checked the number or commited transactions in the system and it looks like JBoss commits my transaction but never writes the message to the destination queue. Any help would be appreciated.

            Thanks,
            Florian

            • 3. Re: MDB and container managed transactions

              use java:/JmxXA as connection factory. Do not create a JMS transacted session, JTA will take care of everything.

              Regards,

              Stephane

              • 4. Re: MDB and container managed transactions

                java:/JmsXA sorry. The following code should work:

                Context jndi = new InitialContext();
                queueConnectionFactory = (QueueConnectionFactory) jndi.lookup("java:/JmsXA");
                connection = queueConnectionFactory.createQueueConnection();
                session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
                sender= session.createSender(queue);
                sender.send ....
                close sender
                close session
                close connection

                Regards,

                Stephane