Cannot rollback() inside an XASession

View: New views
8 Messages — Rating Filter:   Alert me  

Cannot rollback() inside an XASession

by stevenmaring :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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

Re: Cannot rollback() inside an XASession

by Ludovic Orban :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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).

Re: Cannot rollback() inside an XASession

by stevenmaring :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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).

Re: Cannot rollback() inside an XASession

by Ludovic Orban :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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>

Re: Cannot rollback() inside an XASession

by stevenmaring :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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>

Re: Cannot rollback() inside an XASession

by Dennis Brakhane-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Jun 16, 2009 at 9:07 PM, stevenmaring<steve.maring@...> 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



Re: Cannot rollback() inside an XASession

by stevenmaring :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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 ...





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>


Re: Cannot rollback() inside an XASession

by Ludovic Orban :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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.