Our Craft

Making it better

The mysteriously necessary sessionTransacted=true

Posted by danielmeyer on October 22, 2008

I’ve encountered this before, but just ran into it again: Despite suggestions to the contrary, it is necessary (at least with Spring 2.5.5, ActiveMQ 5.1.0, and JBoss 4.2.2.GA) to set sessionTransacted=true in the DefaultMessageListenerContainer even when it’s set up to connect to an external JTA transaction manager. If I set sessionTransacted=true, then when my messageListener throws a RuntimeException, the message is rolled back onto the queue; if I don’t, it doesn’t.

This has been documented elsewhere regarding Atomikos, but not ActiveMQ. I’ve posted a question to the Spring Remoting and JMS forum. We’ll see what comes of it!

About these ads

13 Responses to “The mysteriously necessary sessionTransacted=true”

  1. Ludovic Orban said

    This is one of the dark corners of the JMS / JTA integration, you can blame it on both specs (and even a bit on the EJB spec which also contains some pieces of the puzzle) that are extremely unclear and vague in this regard.

    The Spring documentation is absolutely correct but needs to be carefully read a few times to make sense.

    Setting sessionTransacted=true is used to configure JMS-transacted (ie: local JMS transactions) DefaultMessageListenerContainer. It is basically used by Spring to feed the 1st parameter of this method:

    http://java.sun.com/j2ee/1.4/docs/api/javax/jms/Connection.html#createSession(boolean,%20int)

    When the JMS resource is configured for XA transaction mode, the application server’s javax.jms.Connection object will ignore this parameter as documented in Spring’s JMSTemplate:

    http://opensource.objectsbydesign.com/spring-1.1.4/org/springframework/jms/core/JmsTemplate.html#setSessionTransacted(boolean)

    This is logical because the Session returned by the application server will use an underlying XASession object to perform the work and creating this XASession object from an XAConnection object takes no parameter:

    http://java.sun.com/j2ee/1.4/docs/api/javax/jms/XAConnection.html#createXASession()

    Again this makes sense as to guarantee transactional semantics you MUST have transactions and auto-acknowledge.

    It took me some time to digest all that but the result is that with BTM, no matter what you set in sessionTransacted you will get transactional semantics when using the session inside a JTA transaction.

  2. danielmeyer said

    Ludovic,
    It still seems to me that the Spring manual leaves out any hint of needing to set sessionTransacted=true when using a JtaTransactionManager. Even a one-sentence addition would help — maybe something like “Some JMS implementations require that sessionTransacted be set to true even when connecting to a JTA transaction manager, to achieve transactional semantics.”

  3. Ludovic Orban said

    That would be wrong for at least these two reasons:

    First, this is not a JMS implementation problem but a JMS XA pool problem.

    Second, any JMS XA pool that requires Spring’s sessionTransacted to be set to any value is not EJB / JTA spec compliant.

    Do you think they should document non spec compliant behaviors ?

  4. danielmeyer said

    “any JMS XA pool that requires Spring’s sessionTransacted to be set to any value is not EJB / JTA spec compliant.”

    So is it ActiveMQ that is requiring sessionTransacted to be set to true when it shouldn’t need to be?

    (Thank you for your patience with me as I try to understand)

  5. Ludovic Orban said

    I know this is really confusing but no, the problem is not in ActiveMQ.

    A brief background info:

    – The JMS XAConnectionFactory implementation is the responsibility of the JMS implementation under the JMS spec.

    – The TransactionManager and UserTransaction implementations are the responsibility of the transaction manager under the JTA spec.

    – The JMS XA pool (that wraps XAConnectionFactory as ConnectionFactory) is the responsibility of the application server under the EJB spec.

    The problem of Spring’s sessionTransacted falls under the JMS XA pool’s responsibility: the pool should ensure this value is meaningless in the context of a JTA transaction.

    In a classic application server, you do not have to be concerned about this as it implements all 3 specs.

    With standalone transaction managers, this can cause headaches as to be of any use, such transaction manager also has to provide some XA pooling mechanism or else, you would have access to the JTA API but no single database or JMS server could participate in JTA transactions.

  6. Guy Pardon said

    Hi,

    First: in the XASession javadoc it says that isTransacted() is always true for these sessions. So this supports the need for sessionTransacted=true.

    Second: if you create a session with sessionTransacted=false then you should NOT get a transacted session, since you might be doing explicit acknowledgment in your code. This contradicts transacted sessions…

    In other words, you risk breaking the client-side coding contract (and semantics) of explicit acknowledgment if you return an XA session merely because of a JTA transaction being present.

    Third: Transacted session in JMS are characterized by the acknowledgment coinciding with transaction commit. See http://www.atomikos.com/Publications/ReliableJmsWithTransactions for more information. This is the case for local as well as JTA transactions. Again, this supports sessionTransacted=true.

    Fourth: returning XA (or non-XA) sessions merely based on JTA transaction context (for the calling thread) is very dangerous as it might lead to unexpected behavior (suppose the JTA transaction times out etc…).

    Of course, this is just my interpretation but I think it is consistent in all its aspects (which is more than you can say from the combination of all specs involved:-)

    Guy
    BTW I work for Atomikos :-)

  7. danielmeyer said

    Guy,
    What do you make of Denis’s reply at the Spring Forum (starting with his quote of me, “I still don’t understand why the sessionTransacted setting should make any difference…”)

    I am coming to see, though, that differences of opinion are likely to not be simply resolved as I had originally hoped:

    * The Spring guys probably think it’s clear that sessionTransacted should be a don’t-care value when you’re getting an XASession, so they don’t document having to set sessionTransacted=true when using a JtaTransactionManager;
    * The JMS broker guys (Atomikos, ActiveMQ, etc.) think it’s clear that sessionTranacted *should* matter, and program accordingly;
    * Poor users like me (sad violin music in background) have to learn for ourselves what has to be done. : )

  8. Guy Pardon said

    Daniel,

    Let me ask with Spring – not sure if they have time to answer though…

    Guy

  9. According to traditional J2EE docs such as WebLogic’s, the sessionTransacted parameter (corresponding to the standard JMS createSession method) has to be *false* in order to get a JTA-enabled session:

    http://edocs.bea.com/wls/docs92/jms/trans.html#wp1025537

    The preceding section on native JMS transaction states that: “JTA user transactions are ignored by JMS transacted sessions.”

    In other words, JTA participation on WebLogic only works with sessionTransacted=false. If it’s set to true, you always get a native JMS-transacted Session that happens to ignore JTA transaction completely…

    This is why we use sessionTransacted=false as default in Spring. Point taken that we should add a warning to our JMS section in the reference docs: Always check with your JMS provider / XA provider.

    Juergen

  10. danielmeyer said

    Thanks, Juergen!!

  11. Neal Ravindran said

    The usage of sessionTransacted=”true” vs setting a jmsTransactionManager property for DefaultMessageListenerContainer(DMLC)

    We use JBoss 4.2 server. In dev env, we use a local JBoss Queue and there are no redeliveries. In the test env, we use a remote weblogic queue.

    We have a MDP wired using spring into a DMLC. The message falls into queue, onMessage processes it and dumps to a db. We do not use XA since when we got the app, HibernateTransactionManager took care of db transactions. The onMessage has a try/catch block wherein first we try the db insert and if it fails we throw a JMSException in the catch and it works akin to a global transaction.

    What we noticed is that when sessionTransacted=true it works well on dev env(with a local jboss queue), but in the test env(with a remote weblogic queues, the JMS messages were redelivered. But when we took out sessionTransacted=”true” and set spring JmsTransactionManager instead, the redeliveries stopped in the test env(our problem was fixed)

    The spring doc says that one can use either sessionTransacted=”true” or set an external JmsTransactionManager. So why did only the setting of an external JmsTransactionManager work in this case?

  12. Neal,
    You seem to be speaking of the redeliveries as if they are a problem, and you were glad when the redeliveries stopped. Am I understanding correctly?

    But if your message processing encounters an exception and the transaction is rolled back, you would want the message to be redelivered, right? (Unless you just want to lose the message in this case, which is certainly not the behavior I need!)

    The setup you describe is Hibernate local transactions plus JMS local transactions (managed by the external JmsTransactionManager). What XA gives you that your setup doesn’t have is coordinated commit/rollback of your db and JMS transactions. In your setup, a db transaction could roll back after the JMS transaction had committed or vice versa, leaving the system in an inconsistent state.

    This is not insurmountable; a page on ActiveMQ’s website sketches an alternative to XA where you have your application logic detect duplicate messages in this case.

    Hope this helps. (I wrote up a timely response several days ago but accidentally closed my browser without sending, and was so deflated by the waste of time that it took me until today to respond again. ;)

  13. Guy Pardon said

    An additional note on this issue: for our 3.6 release of TransactionsEssentials we will (by default) ignore the transacted flag, always returning an XA session. This release is expected in August 2009.

    Best
    Guy

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.