首页 文章

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

提问于
浏览
0

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

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

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

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

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

任何人都可以帮助我吗?

3 回答

  • 1

    毫无疑问,如何使用Control Bus作为启动/停止 endpoints :

    <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();
    

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

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

    不确定它是非常清楚的,我在我的asnwer中正确的方式,但希望它有点帮助你 .

  • 0

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

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

    最好的办法是实验 .

  • 1

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

    谢谢

相关问题