Spring Integration的DefaultMessageListenerContainer和JPA中的事务

时间:2017-12-29 13:00:13

标签: spring jpa transactions spring-integration spring-jms

假设我有简单的IntegrationFlow,它以异步方式读取JMS消息,转换,应用业务逻辑等。

@Bean
public IntegrationFlow upstreamEventFlow() {
    return IntegrationFlows.from(
            Jms.messageDrivenChannelAdapter(jmsConnectionFactory)
                    .configureListenerContainer(container -> container.destinationResolver(destinationResolver))
                    .destination("myQueue")
                    .get()
    )
            .transform(xmlToObjectTransformer)
            .transform(upstreamTransformer)
            .handle(evaluationHandler)
            .transform(objectToXmlTransformer)
            .channel(downstreamEventChannel)
            .get();
}

evaluationHandler是GenericHandler,它使用JPA从数据库中获取数据并应用一些业务逻辑

我的问题与Spring和Spring Integration中的事务有关

当我使用以下记录器启用日志记录时:

<logger name="org.springframework.transaction" level="trace"/>
<logger name="org.springframework.jms.connection.JmsTransactionManager" level="debug"/>
<logger name="org.springframework.orm.jpa.JpaTransactionManager" level="debug"/>
<logger name="org.springframework.orm.hibernate5.HibernateTransactionManager" level="debug"/>
<logger name="org.springframework.jdbc.datasource.DataSourceTransactionManager" level="debug"/>
<logger name="org.springframework.integration" level="debug"/>
<logger name="org.springframework.messaging" level="debug"/>
<logger name="org.springframework.jms" level="debug"/>

我可以看到这一切都始于JPA事务,而不是Spring Integration或至少JMS创建的事务

来自日志:

o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name ...: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager ... for JPA transaction
o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC transaction ...

为什么?

您能详细说明事务在DefaultMessageListenerContainer中的工作方式以及它与JMS事务,JMS事务会话,JPA事务等的关系吗?

交易边界在哪里?

交易会话与DefaultMessageListenerContainer中的事务管理器之间的区别是什么?

如果我在处理程序中抛出RuntimeException,我可以看到它被回滚并多次看到消息Execution of JMS message listener failed, and no ErrorHandler has been set.和activemq broker redelivers消息

我应该设置ErrorHandler吗?

1 个答案:

答案 0 :(得分:1)

最佳猜测是你的一个豆类,例如evaluationHandler或方法已注释@Transactional。那是JPA交易开始的时候。该方法退出时,事务将提交(或回滚)。

由于默认情况下会对MD通道适配器进行事务处理,因此JMS(本地)事务会包装整个流,并且在整个流完成(或中止)之前不会提交(或回滚)。

所以,这两个交易并没有真正以任何方式同步;他们是独立的。

如果将JPA事务管理器注入适配器的侦听器容器,该框架将提供“尽力而为1PC”事务同步 - 请参阅Dave Syer's Javaworld Article "Distributed transactions in Spring, with and without XA"

JPA事务将由容器启动,两个事务将背靠背(DB优先)提交,从而有效地同步它们。这不是真正的JTA,并且在JMS Tx回滚时DB Tx可能会提交的可能性很小 - 因此您必须处理重复交付的可能性。