如何从两个不同的连接工厂加入Spring JMS事务?
我正在使用不同的连接工厂来发送和接收消息,在部分提交问题中遇到了发送失败的问题。 jms:message-driven-channel-adapter
使用receiveConnectionFactory
ro从队列中接收消息。 jms:outbound-channel-adapter
使用deliverConnectionFactory
将消息发送到下游队列。我们只有一个JmsTransactionManager
,它使用配置为session-transacted="true"
的receiveConnectionFactory
和jms:outbound-channel-adapter
。如何从两个不同的连接工厂加入Spring JMS事务?
<beans>
<bean id="transactionManager"
class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="receiveConnectionFactory" />
</bean>
<bean id="receiveConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="hostName" value="${mq.host}" />
<property name="channel" value="${mq.channel}" />
<property name="port" value="${mq.port}" />
</bean>
</property>
<property name="sessionCacheSize" value="${receive.factory.cachesize}" />
<property name="cacheProducers" value="${receive.cache.producers.enabled}" />
<property name="cacheConsumers" value="${receive.cache.consumers.enabled}" />
</bean>
<bean id="deliverConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="hostName" value="${mq.host}" />
<property name="channel" value="${mq.channel}" />
<property name="port" value="${mq.port}" />
</bean>
</property>
<property name="sessionCacheSize" value="${send.factory.cachesize}" />
<property name="cacheProducers" value="${send.cache.producers.enabled}" />
<property name="cacheConsumers" value="${send.cache.consumers.enabled}" />
</bean>
<tx:advice id="txAdviceNew" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="send" propagation="REQUIRES_NEW" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="txAdviceNew" pointcut="bean(inputChannel)" />
<aop:advisor advice-ref="txAdviceNew" pointcut="bean(errorChannel)" />
</aop:config>
<jms:message-driven-channel-adapter
id="mdchanneladapter" channel="inputChannel" task-executor="myTaskExecutor"
connection-factory="receiveConnectionFactory" destination="inputQueue"
error-channel="errorChannel" concurrent-consumers="${num.consumers}"
max-concurrent-consumers="${max.num.consumers}" max-messages-per-task="${max.messagesPerTask}"
transaction-manager="transactionManager" />
<jms:outbound-channel-adapter
connection-factory="deliverConnectionFactory" session-transacted="true"
destination-expression="headers.get('Deliver')" explicit-qos-enabled="true" />
</beans>
当任何一个目标存在MQ异常时,发生部分提交,然后发生失败队列提交。我正在查看是否缺少一些配置来加入事务,以便部分提交不会发生。
我试着只有一个连接工厂发送和接收(receiveConnectionFactory
)和parital commit没有发生,一切都按预期工作。
我试着只有一个连接工厂发送和接收(
receiveConnectionFactory
)和parital commit没有发生,一切都按预期工作。
这是正确的方式去你的情况。
我看到你的两个ConnectionFactories
只是他们的对象不同。其余部分看起来像是同一个目标MQ服务器。
如果你绝对不能只用一个ConnectionFactory
生活,你应该考虑使用JtaTransactionManager
或两个JmsTransactionManagers
配置org.springframework.data.transaction.ChainedTransactionManager
- 每个连接工厂之一。
见戴夫Syer对此事的文章:https://www.javaworld.com/article/2077963/open-source-tools/distributed-transactions-in-spring--with-and-without-xa.html
感谢@Artem快速回复。是的,现在我们连接到同一个QManager进行接收和发送。我们正在为将来实现不同的QManager进行发送和接收做准备。我会尝试实现JtaTransactionManager或ChainedTransactionManager,看看是否解决了这个问题。 – Selvakumar
更新 - 我添加了两个JmsTransactionManagers - 每个连接工厂和ChainedTransactionManager加入事务。一切按预期工作,没有部分提交。感谢@artem发布解决方案。 – Selvakumar