没有重新回复xa事务activemq + spring-integration + spring-jms的回滚

时间:2014-09-11 16:48:05

标签: activemq spring-integration spring-jms

这是我的第一篇文章,所以希望我不会把格式搞得太糟糕。

我有一个Spring集成路由,它按如下方式路由消息:

网关 - >路由器 - > outbound-jms-channel - >消息驱动频道 - >服务活化剂

我正在使用spring集成版本4.0.3和activemq版本5.10.0。在这个特定的实例中,我在weblogic容器中运行(虽然情况并非总是如此)。

路由是将JMS消息发布到activemq队列。如果在执行侦听器期间遇到运行时异常,我希望回滚在侦听器中登记的任何事务资源以及重新传递消息。目前我看到回滚但没有重新传递消息。

我的弹簧配置如下:

 <!-- TaskExecutor is defined elsewhere and is our own object, it's effectively the equivalent of calling Executors.newCachedThreadPool(). -->

<bean id="TransactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager"/>

<bean id="XADataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="${xaJndiName}"/>
</bean>

<amq:broker brokerName="messageBroker" useJmx="true" persistent="true" start="true" schedulerSupport="false">
    <amq:transportConnectors>
        <amq:transportConnector id="tcpConnector"  uri="tcp://garethDell.leeds.retailexp.com:9783"/>
    </amq:transportConnectors>
    <amq:persistenceAdapter>
        <amq:jdbcPersistenceAdapter dataSource="#XADataSource"/>
    </amq:persistenceAdapter>
</amq:broker>

<amq:xaConnectionFactory id="amqConnectionFactory" brokerURL="tcp://garethDell.leeds.retailexp.com:9783" useAsyncSend="false">
    <amq:prefetchPolicy>
        <amq:prefetchPolicy all="1"/>
    </amq:prefetchPolicy>
    <amq:redeliveryPolicy>
        <amq:redeliveryPolicy id="redeliveryPolicy" initialRedeliveryDelay="5000" maximumRedeliveries="5" useExponentialBackOff="true" backOffMultiplier="2" queue="*" />
    </amq:redeliveryPolicy>
</amq:xaConnectionFactory>

<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
    <property name="targetConnectionFactory" ref="amqConnectionFactory"/>
    <property name="reconnectOnException" value="true"/>
</bean>

<int:gateway id="messageGateway" service-interface="com.retailexp.amp.server.spring.MessageGateway" default-request-channel="requestChannel"/>
<bean id="MessagePublisher" class="com.retailexp.amp.server.common.publishing.impl.MessagePublisher">
    <property name="gateway" ref="messageGateway"/>
</bean>

<!-- Routes the messages to the appropriate destination, each queue / topic should have an appropriate channel associated with it which must be registered here-->
<int:channel id="requestChannel"/>
<int:header-value-router id="destinationRouter" input-channel="requestChannel" header-name="destination">
    <int:mapping value="test" channel="testOutChannel"/>
</int:header-value-router>

<int:channel id="testOutChannel"/>
<int-jms:outbound-channel-adapter id="testOut" channel="testOutChannel" connection-factory="connectionFactory" destination="testQueue"/>

<int:channel id="testListener"/>
<int-jms:message-driven-channel-adapter id="testIn" connection-factory="connectionFactory" container="testQueueContainer" channel="testListener"/>

<!-- Define the queues -->
<bean id="testQueue" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg value="test"/>
</bean>

<!-- Define the message listeners -->
<bean id="testMessageHandler" class="com.retailexp.amp.server.spring.TestListener"/>
<int:service-activator input-channel="testListener" ref="testMessageHandler" method="onMessage"/>

<bean id="testQueueContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="connectionFactory"/>
    <property name="transactionManager" ref="TransactionManager"/>
    <property name="taskExecutor" ref="TaskExecutor"/>
    <property name="maxConcurrentConsumers" value="10"/>
    <property name="sessionTransacted" value="true"/>
    <property name="sessionAcknowledgeMode" value="0"/>
    <property name="destination" ref="testQueue"/>
    <property name="cacheLevelName" value="CACHE_CONSUMER"/>
</bean>

我的监听器在这个阶段非常直接,它会注销消息,然后保存我们的一个域对象,最后抛出一个运行时异常来强制回滚。此阶段的回滚显示在日志中,并且数据库更改已正确回滚,因此我知道在侦听器中我将获得事务回滚。我假设消费者不应该作为XA事务的一部分参与,因此消息的消费是作为单独事务的一部分提交的(在某种程度上是非事务性的?)。

由于TransactionContext中的xa jdbc驱动程序,我看到设置事务隔离级别的错误,但我不认为这是问题的原因 - 我尝试使用各种不同的隔离级别,例如8 TRANSACTION_SERIALIZABLE所以我认为这仅仅是驱动程序本身的限制。

例外:

[11 Sep 2014 16:53:07,464] [ActiveMQ Transport: tcp:///192.168.50.100:58292@9783  ] [            ] [            ] TRACE jdbc.TransactionContext                  - Cannot set transaction isolation to 1 due Due to vendor limitations, setting transaction isolation for "Oracle XA" JDBC XA driver is not supported.. This exception is ignored.
java.sql.SQLException: Due to vendor limitations, setting transaction isolation for "Oracle XA" JDBC XA driver is not supported.
    at weblogic.jdbc.wrapper.JTAConnection.setTransactionIsolation(JTAConnection.java:492)
    at org.apache.activemq.store.jdbc.TransactionContext.getConnection(TransactionContext.java:74)
    at org.apache.activemq.store.jdbc.adapter.DefaultJDBCAdapter.doAddMessage(DefaultJDBCAdapter.java:220)
    at org.apache.activemq.store.jdbc.JDBCMessageStore.addMessage(JDBCMessageStore.java:126)
    at org.apache.activemq.store.memory.MemoryTransactionStore.addMessage(MemoryTransactionStore.java:343)
    at org.apache.activemq.store.memory.MemoryTransactionStore$1.asyncAddQueueMessage(MemoryTransactionStore.java:159)
    at org.apache.activemq.broker.region.Queue.doMessageSend(Queue.java:910)
    at org.apache.activemq.broker.region.Queue.send(Queue.java:733)
    at org.apache.activemq.broker.region.AbstractRegion.send(AbstractRegion.java:424)
    at org.apache.activemq.broker.region.RegionBroker.send(RegionBroker.java:445)
    at org.apache.activemq.broker.jmx.ManagedRegionBroker.send(ManagedRegionBroker.java:297)
    at org.apache.activemq.broker.BrokerFilter.send(BrokerFilter.java:147)
    at org.apache.activemq.broker.CompositeDestinationBroker.send(CompositeDestinationBroker.java:96)
    at org.apache.activemq.broker.TransactionBroker.send(TransactionBroker.java:307)
    at org.apache.activemq.broker.MutableBrokerFilter.send(MutableBrokerFilter.java:152)
    at org.apache.activemq.broker.TransportConnection.processMessage(TransportConnection.java:496)
    at org.apache.activemq.command.ActiveMQMessage.visit(ActiveMQMessage.java:756)
    at org.apache.activemq.broker.TransportConnection.service(TransportConnection.java:294)
    at org.apache.activemq.broker.TransportConnection$1.onCommand(TransportConnection.java:148)
    at org.apache.activemq.transport.MutexTransport.onCommand(MutexTransport.java:50)
    at org.apache.activemq.transport.WireFormatNegotiator.onCommand(WireFormatNegotiator.java:113)
    at org.apache.activemq.transport.AbstractInactivityMonitor.onCommand(AbstractInactivityMonitor.java:270)
    at org.apache.activemq.transport.TransportSupport.doConsume(TransportSupport.java:83)
    at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:214)
    at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:196)
    at java.lang.Thread.run(Thread.java:722)

我有跟踪级别的日志,如果需要它们是可用的,它们非常冗长,尽管如此推动我超过这篇文章的字符限制。让我知道他们是否有帮助,我会尽力让他们可以使用。

有人能看出上述配置是否有任何明显错误?

编辑:此处提供跟踪日志:http://pastebin.com/0awmzY2D

由于

1 个答案:

答案 0 :(得分:1)

事实证明,在消息到达侦听器时,会话持有的TransactionContext上没有XID。实际上会话没有被加入到事务中,所以我得到了一个刚刚包含了监听器代码的新事务。

我做了一些关于招募应该在哪里发生的事情,看起来xa连接工厂在创建它时没有做任何事情来与事务进行对话,回想起来我是不知道为什么我认为它会因为它没有引用事务管理器。

更改为XAPooledConnectionFactory导致XaConnectionPool执行自动登记,配置更改如下:

<bean id="connectionFactory" class="org.apache.activemq.jms.pool.XaPooledConnectionFactory">
    <property name="connectionFactory" ref="xaConnectionFactory"/>
    <property name="tmJndiName" value="weblogic.transaction.TransactionManager"/>
    <property name="tmFromJndi" value="true"/>
</bean>

<bean id="testQueueContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="connectionFactory"/>
    <property name="transactionManager" ref="TransactionManager"/>
    <property name="taskExecutor" ref="TaskExecutor"/>
    <property name="maxConcurrentConsumers" value="10"/>
    <property name="sessionTransacted" value="true"/>
    <property name="destination" ref="testQueue"/>
</bean>

我现在正在重新发送消息。我仍然遇到一个问题,即交付延迟和退出政策没有得到遵守(虽然奇怪的是最大的退款),但我确信我可以解决这个问题。

感谢您的时间。

相关问题