使用Control总线停止使用事务会话的消息驱动通道适配器

时间:2013-12-26 16:48:34

标签: spring-integration spring-transactions spring-jms

我的要求是使用事务会话和消息驱动通道适配器(JmsMessageDrivenEndpoint)。我可以使用sessionTransacted = true为DefaultMessageListenerContainer设置配置购买。

工作流程:收到消息 - >致电服务激活器 - >服务激活器调用dao类

成功提交数据库后,spring框架会调用commit(),并且在任何运行时异常上,spring框架都会调用rollback()。哪个工作得很好。当回滚发生时,JMS代理会再次将消息发送回我的应用程序。

对于dao中的特定类型的异常,我想添加一个消息头(即重新传递时间),以便JMS Broker不会立即再次发送消息。我该怎么办?

对于dao中的另一种特定类型的异常,我想使用控制总线来停止终点(消息驱动通道适配器),并在停止之前回滚上一个事务。我该怎么办?

任何人都可以帮助我吗?

3 个答案:

答案 0 :(得分:1)

毫无疑问,如何将控制总线用于启动/停止端点:

<int:control-bus input-channel="controlChannel"/>

<int-jms:message-driven-channel-adapter id="jmsInboundEndpoint"/>

<int:transformer input-channel="stopImsInboundEndpointChannel"
           outbound-channel="controlChannel"
           expression="'@jmsInboundEndpoint.stop()'"/>

或者您可以从代码的任何位置向controlChannel发送相同的命令字符串。

但最后一笔交易将被回滚并不重要。这取决于您的“工作单位”(换句话说 - 您的服务行为)。

但是,您可以在发送'stop command'的同时标记当前事务以进行回滚:

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

另一个关于“添加一些邮件标题”的问题对于Messaging来说是不正常的。 如果您更改了消息,它将是一个新消息,您无法使用一些新信息将消息回滚到队列。

当然,无论如何你都可以做到并有新的信息。但你应该resend它,而不是回滚。所以,你应该提交事务并将新消息发送到某个地方(或者发送到同一个队列),但对于你的应用程序来说,它将是Broker的新消息。还有一次:对于这种情况,你必须提交交易。

不确定它是否非常清楚,我在我的asnwer中走的正确,但希望它对你有所帮助。

答案 1 :(得分:1)

在回滚之前,您无法修改消息(添加标头)。当然,您可以在捕获异常后将其重新排列为新消息。某些代理(例如ActiveMQ)在回滚后提供退避重试策略。如果您的经纪人支持,那可能是更好的解决方案。

您可以使用控制总线来停止容器,但您可能必须异步执行(在另一个线程上调用停止,例如在控制总线上使用ExecutorChannel)。否则,根据您的环境,您可能会遇到停止等待容器线程退出的问题,因此您不应该在容器线程本身上执行停止。

最好的办法是实验。

答案 2 :(得分:0)

感谢Gary和Artem。解决方案正在发挥作用我使用以下配置:

<jms:message-driven-channel-adapter id="jmsMessageDrivenChannelAdapter" connection-factory="connectionFactory"
        destination="destination" transaction-manager="jmsTransactionManager" channel="serviceChannel" error-channel="ultimateErrorChannel" />
<si:service-activator input-channel="ultimateErrorChannel" output-channel="controlChannel">
    <bean class="play.spring.integration.TestErrorHandler">
        <property name="adapterNeedToStop" value="jmsMessageDrivenChannelAdapter" />
        <property name="exceptionWhenNeedToStop" value="play.spring.integration.ShutdownException" />
    </bean>
</si:service-activator>
<si:channel id="controlChannel">
    <si:dispatcher task-executor="controlBusExecutor" />
</si:channel>
<task:executor id='controlBusExecutor' pool-size='10' queue-capacity='50' />
<si:control-bus input-channel="controlChannel" />

现在我的问题是,如果我想停止多个入站适配器,如何向所有这些适配器的控制总线发送单个消息?

我要去研究SpEL。如果有人已经知道,我将不胜感激。

由于