Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring integration 使用控制总线停止使用事务会话的消息驱动通道适配器_Spring Integration_Spring Transactions_Spring Jms - Fatal编程技术网

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

Spring integration 使用控制总线停止使用事务会话的消息驱动通道适配器,spring-integration,spring-transactions,spring-jms,Spring Integration,Spring Transactions,Spring Jms,我的要求是使用带有消息驱动通道适配器(JmsMessageDrivenEndpoint)的事务会话。我可以为DefaultMessageListenerContainer使用sessionTransact=true设置配置 工作流程:接收消息->调用服务激活器->服务激活器调用dao类 成功提交到数据库时,spring framework调用commit(),在任何运行时异常时,spring framework调用rollback()。这很好用。当回滚发生时,JMS代理将消息再次发送回我的应用程

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

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

成功提交到数据库时,spring framework调用commit(),在任何运行时异常时,spring framework调用rollback()。这很好用。当回滚发生时,JMS代理将消息再次发送回我的应用程序

对于dao中的特定类型的异常,我希望添加一个消息头(即重新交付时间),以便JMS代理不会立即再次发送消息。我怎么做

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


有人能帮我吗?

难怪,如何使用控制总线来启动/停止端点:

<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()'"/>
您关于“添加一些消息头”的另一个问题对于消息来说根本不正常。 如果您更改消息,它将是一个新消息,并且您无法使用一些新信息将消息回滚到队列中

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


我不确定它是否非常清楚,我的asnwer也走对了方向,但希望它能对您有所帮助。

您不能在回滚之前修改消息(添加标题)。当然,您可以在捕获异常后将其作为新消息重新查询。某些代理(例如ActiveMQ)在回滚后提供回退重试策略。如果您的代理支持,那么这可能是一个更好的解决方案

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


最好的办法就是做实验。

谢谢加里和阿尔特姆。解决方案正在发挥作用。我正在使用以下配置:

<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。如果有人已经知道,我将不胜感激


谢谢

你好,加里:谢谢你的回复。根据@Artem的建议,如果我将当前事务(JMS事务)标记为rollbackOnly,它将与异步调用stop()的建议一起工作吗?顺便说一句,我正在使用一个专有的JMS代理,并且还没有为我的测试设置JNDI。一旦我有了JNDI设置,我就会进行实验,因为它(可能)需要异步完成,您可能会遇到一个竞争条件,即回滚发生在
stop()
完成之前,您可能会得到另一个交付。这就是为什么我建议在同步和异步停止之间进行实验。
<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" />