10 Replies Latest reply on Nov 19, 2003 12:36 PM by bcdecamp

    JMS transaction session not commited

    jeffbannister

      Hi,

      I am getting a little confused about using a transacted JMS session from a SLSB. I currently have an application that after performs some updates to a database post a message onto a P2P queue.

      I would like this message not to be sent i.e. consumed until the transaction that performed the database updates commits. I believe I need to write the message within a transacted session.

      However probably due to my lack of knowlege with JBoss/JMS I have been uable to get a message successfully written to the queue within a transacted session.

      i.e.
      I have a SLSB that creates a transaction session as follows...

      session = connection.createQueueSession(true,0)

      the method which begins the work on the SLSB has transaction attribute of 'Required'. What happens is that the JMS session never appears to get commited and the message is therefore not written to the queue.

      I am confused about which JMS connection factory I am supposed to use for this scenario
      e.g. java:/ConnecitonFactory, java:/XAConnectionFactory,java:/JmsXA.

      Can anyone whose got a transacted session to work point me in the right direction.

      thanks,

      Jeff.


        • 1. Re: JMS transaction session not commited

          You are misusing transactions. JMS transactional session are used if you are working only with JMS. When your transaction is more global (e.g. involve changes on your database), you need to use a JTA transaction.

          Actually you have to create a NON JMS transactional session (that is pass false to the createQeueSession method). That way, your jms session will enrole itself into the JTA tx initiated by your SLSB.

          To achieve your goal, use the java:/JmsXA connection factory

          Regards,

          Stephane

          • 2. Re: JMS transaction session not commited
            jeffbannister

            Hi Dark Lord,

            thanks for the quick reply....

            I would like to clarify your point....

            If I post the message in a non-transacted JMS session using the connection factory 'java:/JmsXA' , then the MDB consumer of the message will not be able to read it until the JTA transaction my SLSB is within commits?

            thanks,

            Jeff.

            • 3. Re: JMS transaction session not commited

              exactly.

              Regards,

              Stephane

              • 4. Re: JMS transaction session not commited
                jeffbannister

                Hi Dark_Lord,

                I think I have the theory part in place, thankyou.
                However I am unable to put it into practice...

                My SLSB code is directly looking up the resource factory at 'java:/JmsXA'. When the code attempts to place a message onto the queue I get the following error 'Invalid transaction Id error'....

                I have see many posts on this but no clear answers. Should I have been using a 'resource-ref' in the deployment descriptor for the SLSB to access this factory or is this not relevant?

                STACK TRACE BEGIN[###################
                javax.jms.JMSException: Invalid transaction id.
                at org.jboss.mq.SpyXAResourceManager.addMessage(SpyXAResourceManager.java:95)
                at org.jboss.mq.SpySession.sendMessage(SpySession.java:716)
                at org.jboss.mq.SpyQueueSender.internalSend(SpyQueueSender.java:118)
                at org.jboss.mq.SpyQueueSender.send(SpyQueueSender.java:68)
                at com.beetleweed.bulkmail.ejbs.QueueManager.addObject(QueueManager.java:100)
                at com.beetleweed.bulkmail.ejbs.BatchProcessorBean.onMessage(BatchProcessorBean.java:139)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                at java.lang.reflect.Method.invoke(Method.java:324)
                at org.jboss.ejb.MessageDrivenContainer$ContainerInterceptor.invoke(MessageDrivenContainer.java:460)
                at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:186)
                at org.jboss.ejb.plugins.MessageDrivenInstanceInterceptor.invoke(MessageDrivenInstanceInterceptor.java:62)
                at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:84)
                at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:216)
                at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:104)
                at org.jboss.ejb.plugins.RunAsSecurityInterceptor.invoke(RunAsSecurityInterceptor.java:90)
                at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:191)
                at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
                at org.jboss.ejb.MessageDrivenContainer.internalInvoke(MessageDrivenContainer.java:374)
                at org.jboss.ejb.Container.invoke(Container.java:700)
                at org.jboss.ejb.plugins.jms.JMSContainerInvoker.invoke(JMSContainerInvoker.java:827)
                at org.jboss.ejb.plugins.jms.JMSContainerInvoker$MessageListenerImpl.onMessage(JMSContainerInvoker.java:1115)
                at org.jboss.jms.asf.StdServerSession.onMessage(StdServerSession.java:256)
                at org.jboss.mq.SpyMessageConsumer.sessionConsumerProcessMessage(SpyMessageConsumer.java:633)
                at org.jboss.mq.SpyMessageConsumer.addMessage(SpyMessageConsumer.java:433)
                at org.jboss.mq.SpySession.run(SpySession.java:298)
                at org.jboss.jms.asf.StdServerSession.run(StdServerSession.java:180)
                at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:727)
                at java.lang.Thread.run(Thread.java:536)

                STACK TRACE END#####################]

                • 5. Re: JMS transaction session not commited

                  Post your code.

                  Regards,

                  Stephane

                  • 6. Re: JMS transaction session not commited

                    This was fixed in 3.2.2
                    I think using <track-connection-by-tx> in jms-ds.xml
                    for JmsXA should also workaround the problem.

                    Regards,
                    Adrian

                    • 7. Re: JMS transaction session not commited
                      jeffbannister

                      Hi Adrian,

                      Thanks for the reply.

                      FYI I still get the problem with v3.2.2RC4.

                      I will now try the workaround.

                      regards,

                      Jeff.

                      • 8. Re: JMS transaction session not commited
                        jeffbannister

                        Hi Adrian,

                        FYI I have attempted the workaround with no joy, not sure I've done this right but my jms-ds.xml now contains the following.....

                        <!-- JMS XA Resource adapter, use this to get transacted JMS in beans -->

                        <tx-connection-factory>

                        <jndi-name>JmsXA</jndi-name>

                        <xa-transaction/>

                        <!-- Added workaround-->
                        <track-connection-by-tx/>

                        <adapter-display-name>JMS Adapter</adapter-display-name>

                        <config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property>

                        <security-domain-and-application>JmsXARealm</security-domain-and-application>

                        </tx-connection-factory>

                        I notice that the default session type is for a topic, I am actually trying to post to a queue.

                        regards,

                        Jeff.

                        • 9. Re: JMS transaction session not commited
                          jeffbannister

                          Hi Adrian/Dark_Lord,

                          I now have a resolution to my problem. These were the things I was doing wrong....

                          1) I wasn't using a XA resource factory when posting messages to a queue. I changed the jndi name I was using to 'java:/JmsXA'.

                          2) One of my MDB's was attempting to consume a message with transaction attribute of 'NotSupported'. It was this that caused the 'Invalid Transaction Id' message. Changing to 'Required' fixed the problem.

                          3) I was attempting to create a transacted JMS session which I now know is not appropriate when in the context of a JTA managed transaction.

                          Now with all the changes in place the message I write after performing some database work is committed with the SLSB transaction. This avoids a race condition that was occuring so job done :-)

                          Thanks one again to those that offered suggestions.

                          regards,

                          Jeff.

                          • 10. Re: JMS transaction session not commited
                            bcdecamp

                            Jeff/Adrian/Stephane,

                            Thanks for the helpful discussion on this topic. A point of clarification though:

                            Section 17.3.5 of the EJB 2.0 spec says,
                            "Because the container manages the transactional enlistment of JMS sessions on behalf of a bean, the
                            parameters of the createQueueSession(boolean transacted, int acknowledgeMode)
                            and createTopicSession(boolean transacted, int acknowledgeMode) methods are
                            ignored. It is recommended that the Bean Provider specify that a session is transacted, but provide 0 for
                            the value of the acknowledgment mode."

                            Jeff, this means you were right when you used the code:
                            session = connection.createQueueSession(true, 0);

                            I tested both true and false values for the transaction parameter and the JmsXA connection does, in fact, ignore the values of createQueueSession() consistent with the spec. The (true, 0) parameters are only there for style points.

                            Thanks,
                            Brian