4 Replies Latest reply on Nov 25, 2002 7:19 AM by frito

    MDB with Oracle and XA transactions: invalid transaction id

    frito

      I have set up a MDB (PersistenceManager is JDBC2 with Oracle DB) with CMT. I am doing the following work:
      - MDB receives Message from Queue A
      - the instance of my MDB will do some work in the onMessage method (could be transactional, too)
      - the MDB sends a message to queue B
      The queues and the Connection Factory are managed ressources (ejb-jar.xml of the MDB).

      Since no RuntimeException is thrown in the onMessage() method and setRollbackOnly() was not invoked, the received message should be acknowledged, my work should be commited and the message should be sent when the TransactionManager commits the XA transaction covering these actions.

      Well, it works when I start JBoss and send a test message from my standalone client which sends a message to queue A
      and receives the answering message from queue B. But it only works once.
      When I restart my test client, there is a JMS Exception telling me: invalid transaction id. This appears when the MDB tries to send the message to queue B. In fact, the transaction seems to be null then.

      These are my questions:
      1. Could this be a faulty configuration? But why is it working for the first time then?
      2. I set the trans-attribute for container-transaction to required for 'onMessage' (and even tried *). Do I have to set
      the trans-attribute for the managed ressource as well (QueueSender in my case?!?), and if so, how should I do this?
      3. Why is the message sent and the received message acknowledged when the JMSException was thrown? Mustn't everything
      roll back or is the missing transaction id the clue for this?
      Any other hints beside these questions? ;-)

      I am using JBoss 3.0.3 with Tomcat 4.1.12 on W2K with SUN JDK 1.4.1 (and even tried with JRockit).

      Greetings,
      Frito

        • 2. Re: MDB with Oracle and XA transactions: invalid transaction
          frito

          Hi Adrian,

          thanks for your reply. I am glad someone cares for my problems :-)
          But the link you gave me didn't really enlight me at all, even after reading it more than once. Perhaps it is too early in the morning ;-)

          I think I just did everything mentioned in the forum thread you told me:

          this is my ejb-jar.xml for the MDB receiving from QueueA and sending into QueueB:
          [pre]

          <?xml version="1.0" encoding="UTF-8"?>
          <ejb-jar>
           <display-name>test/Test1</display-name>
           <enterprise-beans>
           <message-driven>
           <ejb-name>test/Test1</ejb-name>
           <ejb-class>gen.test.Test1MDB</ejb-class>
           <message-selector>filter = 'test/Test1'</message-selector>
           <transaction-type>Container</transaction-type>
           <resource-ref>
           <res-ref-name>managedQueueConnectionFactory</res-ref-name>
           <res-type>javax.jms.QueueConnectionFactory</res-type>
           <res-auth>Container</res-auth>
           </resource-ref>
           <resource-ref>
           <res-ref-name>managedQueueA</res-ref-name>
           <res-type>javax.jms.Queue</res-type>
           <res-auth>Container</res-auth>
           </resource-ref>
           <acknowledge-mode>Auto-acknowledge</acknowledge-mode>
           <message-driven-destination>
           <destination-type>javax.jms.Queue</destination-type>
           </message-driven-destination>
           </message-driven>
           </enterprise-beans>
           <assembly-descriptor>
           <security-role>
           <role-name>everyone</role-name>
           </security-role>
           <container-transaction>
           <method>
           <ejb-name>test/Test1</ejb-name>
           <method-name>onMessage</method-name>
           </method>
           <trans-attribute>Required</trans-attribute>
           </container-transaction>
           </assembly-descriptor>
          </ejb-jar>
          
          [/pre]

          my jboss.xml:
          [pre]
          <?xml version="1.0" encoding="UTF-8"?>
          <jboss>
           <resource-managers>
           <resource-manager>
           <res-name>managedQueueConnectionFactory</res-name>
           <res-jndi-name>java:JmsXA</res-jndi-name>
           </resource-manager>
           <resource-manager>
           <res-name>managedQueueA</res-name>
           <res-jndi-name>queue/QueueA</res-jndi-name>
           </resource-manager>
           <resource-manager>
           <res-name>managedQueueB</res-name>
           <res-jndi-name>queue/QueueB</res-jndi-name>
           </resource-manager>
           </resource-managers>
           <enterprise-beans>
           <message-driven>
           <ejb-name>test/Test1</ejb-name>
           <configuration-name>Test Message Driven Bean</configuration-name>
           <destination-jndi-name>queue/QueueA</destination-jndi-name>
           </message-driven>
           </enterprise-beans>
          </jboss>
          
          [/pre]

          The code in my MDB to get the Queue for sending:
          [pre]
          QueueConnectionFactory queueConnectionFactory =
           (QueueConnectionFactory)jndiContext.lookup("java:comp/env/managedQueueConnectionFactory");
          Queue queue = (Queue)jndiContext.lookup("java:comp/env/managedQueueB");
          QueueConnection queueConnection = queueConnectionFactory.createQueueConnection();
          QueueSession queueSession = queueConnection.createQueueSession(true, 0);
          QueueSender queueSender = queueSession.createSender(queue);
          [/pre]


          The code in my standalone client to get the Queues (sending in QueueA and receiving from QueueB:
          [pre]
          QueueConnectionFactory queueConnectionFactory =
           (QueueConnectionFactory) jndiContext.lookup("XAConnectionFactory");
          Queue sendQueue = (Queue) jndiContext.lookup("queue/QueueA");
          Queue receiveQueue = (Queue) jndiContext.lookup("queue/QueueB");
          QueueConnection queueConnection = queueConnectionFactory.createQueueConnection();
          QueueSession queueSession = queueConnection.createQueueSession(true, 0);
          QueueSender sender = queueSession.createSender(sendQueue);
          QueueReceiver receiver = queueSession.createReceiver(receiveQueue, messageSelector);
          [/pre]


          Did I miss something?

          Greetings again,

          Frito

          • 3. Re: MDB with Oracle and XA transactions: invalid transaction

            Perhaps I didn't your question?

            Can you explain where you get the error and give
            a full stack trace and code snippet where the
            error is thrown.
            e.g. You are using transactional sessions,
            where is the commit?

            Regards,
            Adrian

            • 4. Re: MDB with Oracle and XA transactions: invalid transaction
              frito

              Hello Adrian,

              I found the problem while writing a minimal test client I wanted to attach my next posting:
              I made a new instance of my QueueSession in ejbCreate(). Instead I should do this in onMessage(), since the transaction attribute "Required" is only set for the onMessage() method.
              The EJB spec (15.4.9) sais, that ejbCreate() is called with an unspecified transaction context. Therefore I suppose it is not a bug when a resource (the QueueSession in my case) takes part at the transaction (the first one after newInstance()). Right? If not, I would report this as a bug.

              Thank you once again a regards,

              Frito