Atomikos Forum

Problem with rollback in global transaction

Hi
I am new to using Atomikos, I am having problem that if I try the following from my sample application the DB transaction is not rolled back.
Scenario
1. Write to DB
2. Write to Message queue (explicitly throw error while creating message)

technologies with versions used:
Spring 4.0.0.M1
Atomikos 3.9.0.M1
Derby 10.4.1.3
ActiveMQ 5.8.0

I tried the following spring configuration for handling global transactions.
<?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:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
     http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    <bean id="dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
        init-method="init" destroy-method="close">
        <property name="uniqueResourceName" value="derbyDb" />
        <property name="xaDataSourceClassName" value="org.apache.derby.jdbc.ClientXADataSource" />
        <property name="xaProperties">
            <props>
                <prop key="databaseName">Test</prop>
                <prop key="serverName">localhost</prop>
                <prop key="portNumber">15001</prop>
                <prop key="user">admin</prop>
                <prop key="password">admin</prop>
            </props>
        </property>
    </bean>

    <tx:advice id="txAdvice" transaction-manager="jta.transactionManager">
        <tx:attributes>
            <tx:method name="create" rollback-for="RuntimeException" />
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="createOperation"
            expression="execution(* com.test.spring.transactions.distributed.StudentDaoImpl.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation" />
    </aop:config>

    <bean id="studentDao"
        class="com.test.spring.transactions.distributed.StudentDaoImpl">
        <property name="dataSource" ref="dataSource" />
    </bean>


    <bean id="userTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp"
        init-method="init" destroy-method="shutdownForce">
        <constructor-arg>
            <props>
                <prop key="com.atomikos.icatch.service">
                    com.atomikos.icatch.standalone.UserTransactionServiceFactory
            </prop>
                <prop key="com.atomikos.icatch.automatic_resource_registration">true</prop>
                <prop key="com.atomikos.icatch.console_log_level">DEBUG</prop>
                <prop key="com.atomikos.icatch.serial_jta_transactions">false</prop>
                <prop key="com.atomikos.icatch.output_dir">c:/log</prop>
                <prop key="com.atomikos.icatch.log_base_dir">c:/log/tx</prop>


            </props>
        </constructor-arg>
    </bean>


    <bean id="mqXAconnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
        <property name="brokerURL"
            value="tcp://localhost:61616?jms.redeliveryPolicy.maximumRedeliveries=1">
        </property>
    </bean>

    <bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg value="spring.test.message.distributed" />
    </bean>

    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory">
            <ref local="mqXAconnectionFactory" />
        </property>
        <property name="defaultDestination">
            <ref local="destination" />
        </property>
    </bean>

    <bean id="producer"
        class="com.test.spring.transactions.distributed.MessageProducer">
        <property name="jmsTemplate" ref="jmsTemplate" />
        <property name="studentDao" ref="studentDao" />
    </bean>

    <bean id="userTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
        init-method="init" destroy-method="close" depends-on="userTransactionService">
        <property name="forceShutdown" value="false" />
    </bean>

    <bean id="userTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"
        depends-on="userTransactionService">
        <property name="transactionTimeout" value="300" />
    </bean>

    <bean id="jta.transactionManager"
        class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager" ref="userTransactionManager" />
        <property name="userTransaction" ref="userTransaction" />
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="xa.connectionFactory" class="com.atomikos.jms.AtomikosConnectionFactoryBean">
        <property name="uniqueResourceName" value="amq1" />
        <property name="xaConnectionFactory" ref="mqXAconnectionFactory" />
    </bean>

    <bean id="myListener" class="com.test.spring.jms.MyMessageListener" />

    <bean id="jmsContainer"
        class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="xa.connectionFactory" />
        <property name="destinationName" value="spring.test.message.distributed" />
        <property name="messageListener" ref="myListener" />
        <property name="transactionManager" ref="jta.transactionManager" />
        <property name="sessionTransacted" value="true" />
    </bean>
</beans>

My sample application contains the method with the following code
        studentDao.create(message, 3);
        getJmsTemplate().send(new MessageCreator() {
            @Override
            public Message createMessage(final Session session) throws JMSException {
                final TextMessage msg = session.createTextMessage();

                msg.setText(message);
                System.out.println("Sending msg: " + message);
                throw new RuntimeException();
                //return msg;
            }
        });


The create method in studentDao will use the jdbcTemplate to write to the db.
final String SQL = "insert into Student (name, age) values (?, ?)";
jdbcTemplate.update( SQL, name, age);


If you see the code I explicitly throw exception to fail the message sending. Am I missing something in my configuration that the DB insert is not rolled back?
Oliver Send private email
Sunday, June 30, 2013
 
 
Your transaction AOP config is around the DAO only. That is why it commits independently of the JMS sends...
Guy Pardon Send private email
Thursday, July 11, 2013
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics