我想通过syslog inbound-channel-adapter messages transactional启动流程。不幸的是,适配器不会采用可以进行事务处理的轮询器(许多示例中使用的典型方法与其他入站适配器一起使用)。
有解决方法吗?
修改
经过一番思考后,我意识到我的意图与最初描述的有点不同(因此改变了标题)。基本上我只想做一些简单直接的方法来制作我的消息流伪事务的任意部分(从流中的某个任意通道开始)。含义 - 如果流完成没有任何异常,我想执行一些自定义代码(但请注意,我不希望我的自定义伪提交代码成为流本身的一部分(步骤))。如果发生任何异常,我想执行一些自定义代码。
使用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>
唯一的问题是如何将其与流程的其余部分连接在一起。我尝试的是定义中间虚拟服务激活器端点,它从我希望事务开始的通道接收消息。然后将事务轮询器添加到该服务激活器。但是这种方法本身存在问题,因为为了使用轮询器,你必须将传入通道定义为一个队列通道,它似乎在一个单独的线程中执行流程(或者至少我观察到一些异步行为)。 p>
答案 0 :(得分:2)
通过使适配器的通道启动事务,可以在事务范围内运行来自消息驱动适配器的任何流:
<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" />
通道(和所有下游通道)必须是DirectChannel
(没有队列通道或任务执行程序)。在异步切换到另一个线程之后,事务将提交。
我相信您理解,但为了其他读者的利益,这不会使syslog适配器本身成为事务性的,只是下游流程。
编辑
另一种技术是使用中流交易网关......
@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" />
这样,您可以在事务范围内处理异常并决定是否提交(从错误流中抛出异常将回滚)。
虚空回归很重要;因为下游流程没有回复。
<强> EDIT2 强>
回复您编辑的问题。
因此,您提供的解决方案(特别是在流中间事务处理网关中)的问题似乎只允许您在成功后想要采取某些(不同)操作时出现错误时采取某些操作。
有两种方法可以做到。
publish-subscribe-channel
;添加第二个使用者(使用order
明确定义它们被调用的顺序)并对第二个订阅者执行“成功”操作 - 在异常后(默认情况下)不会调用它,所以你' d继续处理网关错误通道上的异常情况。ChannelInterceptor
。在preSend()
中启动交易。子流完成后将调用afterSendCompletion()
方法。如果子流抛出异常,则填充Exception
参数的存在(或不存在)。如果你想考虑contributing it,我们可以考虑在框架中添加这样的拦截器。