让我们考虑以下情况:
2个spring集成通道,它们每个都在单独的数据库事务中。在第一笔交易结束时,一条消息被放入第二个通道。在第一个通道中,将在数据库中创建元素,这些元素随后会被从第一个通道发送到第二个通道的相应消息使用。
为确保在触发第二个通道之前,通道1的事务已完全提交,我们的JpaTransactionManager
的子类正在TransactionSynchronization
方法中注册一个prepareForCommit
,它从JpaTransactionManager
流(通道1)如下所示:
TransactionSynchronization
,该MessageChannel.send
在afterCommit
阶段执行afterCommit
,以将消息发送到通道2 我的理解是,在将消息发送到第二个通道(在Chain 1
中时),通道1的数据库事务中所做的所有更改都被刷新并提交。
现在,第二个通道可以完成一些工作(例如MQ PUT),并随后更新在第一个流中创建的条目。现在我们已经观察到存储库方法在数据库中没有返回任何条目,但是稍后在表中可见。但是,在第一个通道的事务中也创建的其他条目是可见的。每隔几千条消息只会发生一次,通常它们在那里,但有时在通道1提交事务后的几毫秒内第二个通道看不到它们。
ServiceActivators
是第一个链,由多个执行数据库工作的ServiceActivator
,一个生成更多消息的拆分器以及另一个我命名为SENDER
的{{1}}组成。注册TransactionSynchronization
,(据我所知)应该在红色事务完全提交之后,蓝色事务开始之前将例如3生成的消息发送到链2。
我注意到的一件事是,有时存在但有时不是全部的条目都属于一种(不是故意的)使用javax.transaction.Transactional
而不是org.springframework.transaction.annotation.Transactional
的方法。但是,我们使用的是 spring core 5.0.8.RELEASE ,在其他问题中,我发现自Spring 4.2.x以来,这应该有0的差异。
答案 0 :(得分:1)
我认为afterCommit
是向下游发送消息的正确位置。
应该足够有一个用@Transactional
标记的POJO服务激活器。这样,事务将完全围绕此方法调用开始和完成。该方法的结果将在提交事务之后立即发送到输出通道。
更新
达到要求的最好方法是在Chain1上使用<gateway>
。这样,在从网关生成对Chain2的答复之前,将TX提交到那里。
使用TransactionSynchronization::afterCommit
不能保证当QueueChannel准备轮询消息时,TX将在DB上提交。尽管您可以使用JdbcChannelMessageStore
进行消息的事务性存储。这样,直到在数据库中进行TX提交后,它们才可见。
在文档中查看有关<gateway>
的更多信息:https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-routing-chapter.html#_calling_a_chain_from_within_a_chain