Cannot rollback() inside an XASession

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Cannot rollback() inside an XASession

stevenmaring
I'm trying to use ActiveMQ with XA and a Spring configuration.  I'm now at the point where DefaultMessageListenerContainer seems to be confusing local and global transactions ...

12:37:58,173  WARN PooledSession:112 - Caught exception trying rollback() when putting session back into the pool: javax.jms.TransactionInProgressException: Cannot rollback() inside an XASession
javax.jms.TransactionInProgressException: Cannot rollback() inside an XASession
        at org.apache.activemq.ActiveMQXASession.rollback(ActiveMQXASession.java:76)
        at org.jencks.amqpool.PooledSession.close(PooledSession.java:109)
        at org.jencks.amqpool.XaConnectionPool$Synchronization.afterCompletion(XaConnectionPool.java:89)
        at bitronix.tm.BitronixTransaction.fireAfterCompletionEvent(BitronixTransaction.java:382)
        at bitronix.tm.BitronixTransaction.rollback(BitronixTransaction.java:220)
        at bitronix.tm.BitronixTransactionManager.rollback(BitronixTransactionManager.java:105)
        at org.springframework.transaction.jta.JtaTransactionManager.doRollback(JtaTransactionManager.java:1054)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:800)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:777)
        at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.rollbackOnException(AbstractPollingMessageListenerContainer.java:385)
        at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:243)
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:944)
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:875)
        at java.lang.Thread.run(Thread.java:595)


Honestly, I'm not even sure why it is trying to do transactions at this point because there is nothing in the queues.

here is my Spring config:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:amq="http://activemq.apache.org/schema/core"
       xmlns:jms="http://www.springframework.org/schema/jms"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://cxf.apache.org/jaxws
       http://cxf.apache.org/schemas/jaxws.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
       http://activemq.apache.org/schema/core
       http://activemq.apache.org/schema/core/activemq-core-5.2.0.xsd
       http://www.springframework.org/schema/jms
       http://www.springframework.org/schema/jms/spring-jms-2.5.xsd">

        <import resource="classpath:META-INF/cxf/cxf.xml" />
        <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
        <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> 
       

        <jaxws:endpoint
                id="voiceRequest"
                implementor="com.ess.tts.voicerequest.VoiceRequestImpl"
                address="/voiceRequest"
        />
       

  <amq:broker useJmx="false">
  <amq:persistenceAdapter>
    <amq:journaledJDBC dataDirectory="amq"/>
    </amq:persistenceAdapter>
    <amq:transportConnectors>
      <amq:transportConnector uri="tcp://localhost:0" />
    </amq:transportConnectors>
  </amq:broker>
 
    <amq:systemUsage>
        <amq:memoryUsage>
            <amq:memoryUsage limit="20 mb"/>
        </amq:memoryUsage>
        <amq:storeUsage>
            <amq:storeUsage limit="1 gb"/>
        </amq:storeUsage>
        <amq:tempUsage>
            <amq:tempUsage limit="100 mb"/>
        </amq:tempUsage>
    </amq:systemUsage>


  <amq:queue id="amqRequestQueue"  physicalName="amqRequestQueue"/>
  <amq:queue id="amqResponseQueue"  physicalName="amqResponseQueue"/>

   
    <bean id="jmsConnectionFactory"
                class="org.jencks.amqpool.XaPooledConnectionFactory">
                <property name="connectionFactory" ref="jmsFactory" />
                <property name="transactionManager" ref="bitronixTransactionManager" />
        </bean>
   
    <bean id="jmsFactory"
                class="org.apache.activemq.spring.ActiveMQXAConnectionFactory">
                <property name="brokerURL" value="vm://localhost" />
                <property name="prefetchPolicy">
                        <bean class="org.apache.activemq.ActiveMQPrefetchPolicy">
                                <property name="queuePrefetch" value="1" />
                        </bean>
                </property>
                <property name="redeliveryPolicy">
                        <bean class="org.apache.activemq.RedeliveryPolicy">
                                <property name="initialRedeliveryDelay" value="60000" />
                                <property name="backOffMultiplier" value="2" />
                                <property name="useExponentialBackOff" value="true" />
                                <property name="maximumRedeliveries" value="3" />
                        </bean>
                </property>
        </bean>


 
  <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
  <property name="connectionFactory" ref="jmsConnectionFactory"/>
  </bean>
 
  <bean id="voiceRequestImpl" class="com.ess.tts.voicerequest.VoiceRequestImpl">
  <property name="jmsTemplate" ref="jmsTemplate"/>
  <property name="requestQueue" ref="amqRequestQueue"/>
  </bean>
 
  <bean id="voiceRequestConsumer" class="com.ess.tts.voicerequest.queue.VoiceRequestConsumer">
  <property name="jmsTemplate" ref="jmsTemplate"/>
  <property name="responseQueue" ref="amqResponseQueue"/>
  </bean>
 

  <bean id="btmConfig"
  factory-method="getConfiguration"
  class="bitronix.tm.TransactionManagerServices">
                <property name="serverId" value="spring-btm" />
        </bean>

        <bean id="bitronixTransactionManager"
                factory-method="getTransactionManager"
                class="bitronix.tm.TransactionManagerServices"
                depends-on="btmConfig"
                destroy-method="shutdown" />
       
  <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
                <property name="transactionManager" ref="bitronixTransactionManager" />
                <property name="userTransaction" ref="bitronixTransactionManager" />
        </bean>
       
        <aop:aspectj-autoproxy/>
       
        <tx:advice id="txAdvice" transaction-manager="transactionManager"> 
                <tx:attributes> 
                        <tx:method name="*" propagation="REQUIRED" /> 
                </tx:attributes> 
        </tx:advice> 

        <aop:config> 
                <aop:pointcut
                        id="voiceRequestSender"
                        expression="execution(String com.ess.tts.voicerequest.VoiceRequestImpl.submitVoiceRequest(..))" />
                <aop:pointcut
                        id="messageReceptionOperations"
                        expression="execution(void com.ess.tts..*.onMessage(..)) and target(javax.jms.MessageListener)" />
                <aop:advisor advice-ref="txAdvice" pointcut-ref="voiceRequestSender" />
                <aop:advisor advice-ref="txAdvice" pointcut-ref="messageReceptionOperations" />
        </aop:config>

        <bean id="voiceResponseConsumer" class="com.ess.tts.voiceresponse.queue.VoiceResponseConsumer" />

        <jms:listener-container
                concurrency="1-5"
                destination-type="queue"
                prefetch="1"
                transaction-manager="transactionManager"
                connection-factory="jmsConnectionFactory">
                <jms:listener
                        destination="amqRequestQueue"
                        ref="voiceRequestConsumer"/>
                <jms:listener
                        destination="amqResponseQueue"
                        ref="voiceResponseConsumer"/>
        </jms:listener-container>
</beans>


Thanks,
Steve Maring
Reply | Threaded
Open this post in threaded view
|

Re: Cannot rollback() inside an XASession

Ludovic Orban
Administrator
You have to configure a bitronix.tm.resource.jms.PoolingConnectionFactory instead of the org.jencks.amqpool.XaPooledConnectionFactory and org.apache.activemq.spring.ActiveMQXAConnectionFactory:

        <bean id="jmsConnectionFactory" class="bitronix.tm.resource.jms.PoolingConnectionFactory" init-method="init" destroy-method="close">
                <property name="className" value="org.apache.activemq.ActiveMQXAConnectionFactory" />
                <property name="uniqueName" value="amq1" />
                <property name="maxPoolSize" value="5" />
               
                <property name="driverProperties">
                        <props>
                                <prop key="brokerURL">vm://localhost</prop>
                        </props>
                </property>
        </bean>

See http://docs.codehaus.org/display/BTM/JmsConfiguration for more details.

The <jms:listener-container> actually polls the JMS server to determine if messages are to be delivered, this explains why transactions are started and rolled back (because as you said the queue is empty).
Reply | Threaded
Open this post in threaded view
|

Re: Cannot rollback() inside an XASession

stevenmaring
I had been using the Bitronix connection pooling earlier, but I ran into a brick wall trying to figure out how to configure org.apache.activemq.ActiveMQPrefetchPolicy and org.apache.activemq.RedeliveryPolicy via the driverProperties.

Any thoughts on that one?



Ludovic Orban wrote
You have to configure a bitronix.tm.resource.jms.PoolingConnectionFactory instead of the org.jencks.amqpool.XaPooledConnectionFactory and org.apache.activemq.spring.ActiveMQXAConnectionFactory:

        <bean id="jmsConnectionFactory" class="bitronix.tm.resource.jms.PoolingConnectionFactory" init-method="init" destroy-method="close">
                <property name="className" value="org.apache.activemq.ActiveMQXAConnectionFactory" />
                <property name="uniqueName" value="amq1" />
                <property name="maxPoolSize" value="5" />
               
                <property name="driverProperties">
                        <props>
                                <prop key="brokerURL">vm://localhost</prop>
                        </props>
                </property>
        </bean>

See http://docs.codehaus.org/display/BTM/JmsConfiguration for more details.

The <jms:listener-container> actually polls the JMS server to determine if messages are to be delivered, this explains why transactions are started and rolled back (because as you said the queue is empty).
Reply | Threaded
Open this post in threaded view
|

Re: Cannot rollback() inside an XASession

Ludovic Orban
Administrator
You mean like this ?

        <bean id="jmsConnectionFactory" class="bitronix.tm.resource.jms.PoolingConnectionFactory" init-method="init" destroy-method="close">
                <property name="className" value="org.apache.activemq.ActiveMQXAConnectionFactory" />
                <property name="uniqueName" value="amq1" />
                <property name="maxPoolSize" value="5" />
               
                <property name="driverProperties">
                        <props>
                                <prop key="brokerURL">tcp://localhost:61616</prop>
                                <prop key="redeliveryPolicy.initialRedeliveryDelay">60000</prop>
                                <prop key="redeliveryPolicy.backOffMultiplier">2</prop>
                                <prop key="redeliveryPolicy.useExponentialBackOff">true</prop>
                                <prop key="redeliveryPolicy.maximumRedeliveries">3</prop>
                                <prop key="prefetchPolicy.queuePrefetch">1</prop>
                        </props>
                </property>
        </bean>
Reply | Threaded
Open this post in threaded view
|

Re: Cannot rollback() inside an XASession

stevenmaring
FANTASTIC!  I didn't know you could do that.

Many thanks for the help Ludovic!

Now if I can just figure out how to write this pointcut expression to wrap a transaction around my JmsTemplate sender I will be all set.

-Steve Maring
 

Ludovic Orban wrote
You mean like this ?

        <bean id="jmsConnectionFactory" class="bitronix.tm.resource.jms.PoolingConnectionFactory" init-method="init" destroy-method="close">
                <property name="className" value="org.apache.activemq.ActiveMQXAConnectionFactory" />
                <property name="uniqueName" value="amq1" />
                <property name="maxPoolSize" value="5" />
               
                <property name="driverProperties">
                        <props>
                                <prop key="brokerURL">tcp://localhost:61616</prop>
                                <prop key="redeliveryPolicy.initialRedeliveryDelay">60000</prop>
                                <prop key="redeliveryPolicy.backOffMultiplier">2</prop>
                                <prop key="redeliveryPolicy.useExponentialBackOff">true</prop>
                                <prop key="redeliveryPolicy.maximumRedeliveries">3</prop>
                                <prop key="prefetchPolicy.queuePrefetch">1</prop>
                        </props>
                </property>
        </bean>
Reply | Threaded
Open this post in threaded view
|

Re: Cannot rollback() inside an XASession

Dennis Brakhane-2
On Tue, Jun 16, 2009 at 9:07 PM, stevenmaring<[hidden email]> wrote:
>
> FANTASTIC!  I didn't know you could do that.
>
> Many thanks for the help Ludovic!
>
> Now if I can just figure out how to write this pointcut expression to wrap a
> transaction around my JmsTemplate sender I will be all set.

The spring folks will probably be able to help you with this one.

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Cannot rollback() inside an XASession

stevenmaring
In reply to this post by stevenmaring
The only bump is ...

<prop key="redeliveryPolicy.initialRedeliveryDelay">5000</prop>
or
<prop key="redeliveryPolicy.initialRedeliveryDelay">5000L</prop>

causes ...

Caused by: bitronix.tm.resource.ResourceConfigurationException: cannot create JMS connection factory named amq1
        at bitronix.tm.resource.jms.PoolingConnectionFactory.init(PoolingConnectionFactory.java:50)
        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:585)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractA
utowireCapableBeanFactory.java:1413)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowi
reCapableBeanFactory.java:1374)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireC
apableBeanFactory.java:1334)
        ... 39 more
Caused by: bitronix.tm.utils.PropertyException: cannot convert values of type 'java.lang.String' into type 'long'
        at bitronix.tm.utils.PropertyUtils.transform(PropertyUtils.java:229)
        at bitronix.tm.utils.PropertyUtils.setDirectProperty(PropertyUtils.java:189)
        at bitronix.tm.utils.PropertyUtils.setProperty(PropertyUtils.java:51)
        at bitronix.tm.resource.common.XAPool.createXAFactory(XAPool.java:223)
        at bitronix.tm.resource.common.XAPool.<init>(XAPool.java:47)
        at bitronix.tm.resource.jms.PoolingConnectionFactory.buildXAPool(PoolingConnectionFactory.java:92)
        at bitronix.tm.resource.jms.PoolingConnectionFactory.init(PoolingConnectionFactory.java:47)
        ... 46 more

and

<prop key="redeliveryPolicy.backOffMultiplier">2</prop>

causes ...

bitronix.tm.utils.PropertyException: cannot convert values of type 'java.lang.String' into type 'short'



causes ...




stevenmaring wrote
FANTASTIC!  I didn't know you could do that.

Many thanks for the help Ludovic!

Now if I can just figure out how to write this pointcut expression to wrap a transaction around my JmsTemplate sender I will be all set.

-Steve Maring
 

Ludovic Orban wrote
You mean like this ?

        <bean id="jmsConnectionFactory" class="bitronix.tm.resource.jms.PoolingConnectionFactory" init-method="init" destroy-method="close">
                <property name="className" value="org.apache.activemq.ActiveMQXAConnectionFactory" />
                <property name="uniqueName" value="amq1" />
                <property name="maxPoolSize" value="5" />
               
                <property name="driverProperties">
                        <props>
                                <prop key="brokerURL">tcp://localhost:61616</prop>
                                <prop key="redeliveryPolicy.initialRedeliveryDelay">60000</prop>
                                <prop key="redeliveryPolicy.backOffMultiplier">2</prop>
                                <prop key="redeliveryPolicy.useExponentialBackOff">true</prop>
                                <prop key="redeliveryPolicy.maximumRedeliveries">3</prop>
                                <prop key="prefetchPolicy.queuePrefetch">1</prop>
                        </props>
                </property>
        </bean>
Reply | Threaded
Open this post in threaded view
|

Re: Cannot rollback() inside an XASession

Ludovic Orban
Administrator
Looks like you're running version 1.3 as this bug has been fixed in 1.3.1: http://jira.codehaus.org/browse/BTM-30

Please try again with version 1.3.2.