Spring integration 如何使消息流的任意部分(伪)具有事务性?

Spring integration 如何使消息流的任意部分(伪)具有事务性?,spring-integration,Spring Integration,我想使syslog入站通道适配器消息启动的流具有事务性。不幸的是,适配器没有采用可以进行事务处理的轮询器(在许多示例中,其他入站适配器都使用了这种典型方法) 有什么解决办法吗 编辑 经过一番思考后,我意识到我的意图和最初描述的略有不同(因此更改了标题)。基本上,我只想做一些简单而直接的方法,使消息流的任意部分(从流中的任意通道开始)成为伪事务性的。意思-如果流在没有任何异常的情况下完成,我希望执行一些自定义代码(但请注意,我不希望自定义伪提交代码成为流本身的一部分(步骤)。如果发生任何异常,我想

我想使syslog入站通道适配器消息启动的流具有事务性。不幸的是,适配器没有采用可以进行事务处理的轮询器(在许多示例中,其他入站适配器都使用了这种典型方法)

有什么解决办法吗

编辑

经过一番思考后,我意识到我的意图和最初描述的略有不同(因此更改了标题)。基本上,我只想做一些简单而直接的方法,使消息流的任意部分(从流中的任意通道开始)成为伪事务性的。意思-如果流在没有任何异常的情况下完成,我希望执行一些自定义代码(但请注意,我不希望自定义伪提交代码成为流本身的一部分(步骤)。如果发生任何异常,我想执行一些自定义代码

使用TransactionSynchronizationFactory的语义将非常适合我

<int:transaction-synchronization-factory id="syncFactory">
    <int:after-commit expression="payload.renameTo('/success/' + payload.name)" channel="committedChannel" />
    <int:after-rollback expression="payload.renameTo('/failed/' + payload.name)" channel="rolledBackChannel" />
</int:transaction-synchronization-factory>


唯一的问题是如何将其与流的其余部分连接在一起。我尝试的是定义中间虚拟ServiceActivator端点,它从我希望事务开始的通道接收消息。然后将事务轮询器添加到该服务激活器。但是这种方法本身也有问题,因为为了使用poller,您必须将传入通道定义为队列通道,这似乎使流在单独的线程中执行(或者至少我观察到一些异步行为).

通过使适配器的通道启动事务,来自消息驱动适配器的任何流都可以在事务范围内运行:

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="send"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:advisor advice-ref="txAdvice" pointcut="bean(fromSyslog)"/>
</aop:config>

<int:channel id="fromSyslog" />
这样,您就可以处理事务范围内的异常,并决定是否提交(从错误流抛出异常将回滚)

无效收益是重要的;因为下游流不会返回应答

EDIT2

回答您编辑的问题

因此,我提供的解决方案(特别是在中间流程事务网关中)的问题似乎只允许您在成功后还希望采取一些(不同)措施时,在出现错误时采取一些措施

有两种方法可以做到这一点

  • 将子流中的最后一个频道设置为a
    publish-subscribe频道
    ;添加第二个使用者(使用
    order
    明确定义调用它们的顺序),并对第二个订户执行“成功”操作-在异常(默认情况下)后不会调用他,因此您可以继续在网关的错误通道上处理异常情况
  • 使用
    通道拦截器
    。在
    preSend()
    中启动事务。子流完成后将调用
    afterEndCompletion()
    方法。如果子流引发异常,则填充
    异常
    参数的存在(或不存在)

  • 我们可以考虑在框架中添加这样一个拦截器,如果你想考虑的话。

    我在提问之前尝试了这个方法。无法找到在发生失败(回滚)或成功(提交)时如何插入自定义代码的方法。我尝试使用的事务管理器是伪事务管理器;回滚后,它将获得一条
    错误消息
    ,其中包含一个
    消息异常
    负载,该负载有两个属性,
    原因
    失败消息
    。如果您想在事务范围内处理错误(并决定是否提交),我可以使用不同的技术编辑我的答案。
    @Transactional
    public interface TxGate {
    
        void oneWay(Message<?> message);
    
    }
    
    <int:service-activator input-channel="fromSyslog" ref="txGate" />
    
    <int:gateway id="txGate" service-interface="foo.TxGate"
         default-request-channel="txSyslog" error-channel="foo" />