如何让 Spring Integration HTTP outbound-channel-adapter 参与 Global Transaction

Posted

技术标签:

【中文标题】如何让 Spring Integration HTTP outbound-channel-adapter 参与 Global Transaction【英文标题】:How to make Spring Integration HTTP outbound-channel-adapter participate in Global Transaction 【发布时间】:2013-09-28 05:19:57 【问题描述】:

我有以下Spring Integration 配置。我在这里做的是dequeuing 来自主题的消息,并在转换后将其发送到某个 HTTP 位置。

JMS Connection Factory配置如下:

<bean id="inboundCF" 
class="org.springframework.jms.connection.CachingConnectionFactory">
    <constructor-arg index="0">
        <jee:jndi-lookup jndi-name="java:comp/resource/ABC_AQ/XATopicConnectionFactories/XATCF" />
    </constructor-arg>
    <property name="sessionCacheSize" value="3" />
</bean>
<bean id="txInboundCF"
class="org.springframework.jms.connection.TransactionAwareConnectionFactoryProxy">
    <property name="targetConnectionFactory" ref="inboundCF" />
<property name="synchedLocalTransactionAllowed" value="true" />
</bean>

Message Listener Container的配置如下:

<bean id="jmsInboundContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer"
destroy-method="destroy">
    <property name="connectionFactory" ref="txInboundCF" />
    <property name="destination" ref="inboundDestination" />
    <property name="pubSubDomain" value="true" />
    <property name="sessionTransacted" value="true" />
    <property name="errorHandler" ref="errorHandlerService" />
    <property name="subscriptionDurable" value="true" />
    <property name="durableSubscriptionName" value="mySub" />
    <property name="cacheLevel" value="3" />
</bean>
<int-jms:message-driven-channel-adapter channel="jmsInChannel"
container="jmsInboundContainer" acknowledge="transacted" />

HTTP outbound adapter的配置如下:

<int-http:outbound-channel-adapter channel="httpOutChannel" url="http://www.example.com/test" http-method="POST" charset="UTF-8" />

在快乐的情况下它工作正常。但是,它不会回滚 http post 消息,而是 jms 消息在topic 中回滚,以防之后发生任何异常。所以,http:outbound-channel-adapter 没有参与全局事务。

我怎样才能做到这一点。感谢您在这方面的任何帮助。

其次,我可以在我的日志文件中找到以下日志条目,但消息正在成功出列。

[23/09/2013 14:27:51] WARN [Thread-102] CachingConnectionFactory.onException(301) | Encountered a JMSException - resetting the underlying JMS Connection
javax.jms.JMSException: java.sql.SQLException: ORA-00942: table or view does not exist

at oracle.jms.AQjmsExceptionListener.run(AQjmsExceptionListener.java:222)
[23/09/2013 14:27:51] WARN [jmsInboundContainer-9] DefaultMessageListenerContainer.handleListenerSetupFailure(821) | Setup of JMS message listener invoker failed for destination 'MY_TOPIC' - trying to recover. Cause: JMS-115: Consumer is closed

【问题讨论】:

【参考方案1】:

这不是&lt;int-http:outbound-channel-adapter&gt; 的问题。根据定义,HTTP 协议不是事务性的。因此,如果您向某个 URL 发送请求并获得 200 OK,则意味着您的请求已成功传递到远程服务器。 但是 Spring Integration 对你有窍门:Transaction Synchronization 它可能看起来像这样:

<jms:inbound-channel-adapter>
    <int:poller>
        <int:transactional synchronization-factory="syncFactory"/>
    </int:poller>
</jms:inbound-channel-adapter>

<int:transaction-synchronization-factory id="syncFactory">
      <int:after-commit channel="httpOutboundChannel"/>
</int:transaction-synchronization-factory>

您的&lt;jms:inbound-channel-adapter&gt; 可能会向某个空处理程序发送消息,例如nullChannel

【讨论】:

我明白。但是如果消息没有成功传递到 http 怎么办?所以事务会回滚?? 您询问过“回滚”成功的 HTTP 请求...在 HTTP 请求失败时回滚事务是另一回事。所以,我认为这是另一个单独的话题 您的解决方案不是回滚成功的 HTTP 请求,而是在提交后发起 HTTP 帖子。请参阅我要求的问题主题。 试着用其他方式解释你想要达到的目标,因为not rolling back successful HTTP request这个词听起来很奇怪......

以上是关于如何让 Spring Integration HTTP outbound-channel-adapter 参与 Global Transaction的主要内容,如果未能解决你的问题,请参考以下文章

Spring Integration:如何一次处理多条消息?

如何在 Spring Integration 中动态注册 Feed Inbound Adapter?

如何使用 Spring Integration 发送 gcm xmpp 消息?

如何将请求标头添加到 outboundGateway spring integration dsl

Spring Integration:如何增加对传入消息的处理

如何使用 Micrometer 获取 Spring Integration 队列中的消息数?