Pardon me sir, was that an XA transaction that just rolled by?

Last time, we briefly tried local JMS transactions, hopefully on our way to demonstrating a successful XA transaction rollback.  (You know, a successful transaction failure! :)


On a whim, I added an acknowledge="transacted" attribute to my DefaultMessageListenerContainer bean… and now the transaction rolls back when the MessageListener throws a RuntimeException, putting the message back in the queue, whence it is redelivered!  Is this not the moment we have been working for days to witness??!

Maybe!

The working(?) bean file

The complete Spring bean file is:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:amq="http://activemq.org/config/1.0" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jms="http://www.springframework.org/schema/jms" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://activemq.org/config/1.0 http://activemq.apache.org/schema/core/activemq-core-5.0.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

    <jee:jndi-lookup id="queueConnectionFactory" jndi-name="java:activemq/QueueConnectionFactory" />

    <bean id="messageListener" class="com.ontsys.dmn.MessageListener" />

    <tx:jta-transaction-manager />

    <jms:listener-container transaction-manager="transactionManager" connection-factory="queueConnectionFactory"
        acknowledge="transacted">
        <jms:listener destination="myTest.Queue" ref="messageListener" />
    </jms:listener-container>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="messageReceiveOperation" expression="execution(* com.ontsys.dmn.MessageListener.onMessage(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="messageReceiveOperation" />
    </aop:config>
</beans>

JBoss Server Debug-Level Log

Part of the JBoss debug-level server log follows.  I’ve bolded the lines that look rollbacky and/or XA-like.

2008-07-22 14:48:24,915 DEBUG [org.springframework.jms.listener.DefaultMessageListenerContainer] Received message of type [class org.apache.activemq.command.ActiveMQTextMessage] from consumer [ActiveMQMessageConsumer { value=ID:osc8373-4330-1216752471934-0:0:33:1, started=true }] of transactional session [ManagedSessionProxy { ActiveMQSession {id=ID:osc8373-4330-1216752471934-0:0:33,started=true} }]
2008-07-22 14:48:24,915 DEBUG [org.springframework.jms.listener.DefaultMessageListenerContainer] Invoking listener with message of type [class org.apache.activemq.command.ActiveMQTextMessage] and session [ManagedSessionProxy { ActiveMQSession {id=ID:osc8373-4330-1216752471934-0:0:33,started=true} }]
2008-07-22 14:48:24,946 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Using transaction object [org.springframework.transaction.jta.JtaTransactionObject@628e42]
2008-07-22 14:48:24,946 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Participating in existing transaction
2008-07-22 14:48:24,946 DEBUG [org.springframework.transaction.interceptor.TransactionInterceptor] Getting transaction for [javax.jms.MessageListener.onMessage]
2008-07-22 14:48:24,946 DEBUG [org.springframework.transaction.interceptor.TransactionInterceptor] Completing transaction for [javax.jms.MessageListener.onMessage] after exception: java.lang.RuntimeException: Boom: boom
2008-07-22 14:48:24,946 DEBUG [org.springframework.transaction.interceptor.RuleBasedTransactionAttribute] Applying rules to determine whether transaction should rollback on java.lang.RuntimeException: Boom: boom
2008-07-22 14:48:24,946 DEBUG [org.springframework.transaction.interceptor.RuleBasedTransactionAttribute] Winning rollback rule is: null
2008-07-22 14:48:24,946 DEBUG [org.springframework.transaction.interceptor.RuleBasedTransactionAttribute] No relevant rollback rule found: applying default rules
2008-07-22 14:48:24,946 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Participating transaction failed – marking existing transaction as rollback-only
2008-07-22 14:48:24,946 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Setting JTA transaction rollback-only
2008-07-22 14:48:24,946 DEBUG [org.springframework.transaction.support.TransactionSynchronizationManager] Retrieved value [org.springframework.jms.connection.JmsResourceHolder@a98e77] for key [org.apache.activemq.ra.ActiveMQConnectionFactory@335297] bound to thread [org.springframework.jms.listener.DefaultMessageListenerContainer#0-1]
2008-07-22 14:48:24,946 DEBUG [org.springframework.jms.listener.DefaultMessageListenerContainer] Rolling back transaction because of listener exception thrown: java.lang.RuntimeException: Boom: boom
2008-07-22 14:48:24,946 WARN  [org.springframework.jms.listener.DefaultMessageListenerContainer] Execution of JMS message listener failed
java.lang.RuntimeException: Boom: boom

What exactly was it that rolled back?

Did this roll back an XA transaction?  Or did I unwittingly switch over to JMS local transactions by setting acknowledge="transacted"? The server log output certainly seems to confirm that it was an out-and-out XA transaction that we rolled back.  We can further confirm this by adding a JDBC/Hibernate operation to the transaction and see if a rollback really rolls back both the JMS and Hibernate portions.

Thanks to Murali Kosaraju’s JavaWorld article for the idea of setting sessionTransacted on the DMLC, even in an XA situation!

Next time, we’ll try to get the JDBC datasource in place.

Advertisements

, , ,

  1. Leave a comment

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