2012-02-10 156 views
13

我有一个运行在jboss上的spring web应用程序,当前配置为使用HibernateTransactionManager用于db事务,JmsTransactionManager用于jms。对于jms我们使用Camel和ActiveMQ,我们的数据库是DB2。在一个事务中,我需要向数据库写入一些记录并发送两个异步的jms消息。 jms消息是事件通知,我只希望在数据库事务提交时发送它们。春季交易JDBC和JMS的同步

我愿意接受在jdbc事务已经提交之后与代理通信失败的风险(因此没有发送消息但提交了数据库),所以我不认为我需要适当的XA。

我相信我需要的是使用spring事务同步的“尽力而为”事务管理。

春天的文档提示,spring会同步两个事务,并在jdbc事务提交之后提交jms事务 - 但我不认为它很清楚。这里的春季文档http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#tx-resource-synchronization没有详细说明它的工作原理。

我发现了一些其他的消息来源,说春天会做我想要的东西,包括一些javadoc下面,我写了一些集成测试,也显示它。

http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/jms/support/JmsAccessor.html#setSessionTransacted%28boolean%29 setSessionTransacted在这里的javadoc听起来就像我想要的。

从我所看到的,我认为与成交套数设置为这样的真正的创造了骆驼JmsConfiguration足够:

<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration"> 
    <property name="connectionFactory" ref="pooledConnectionFactory"/> 
    <property name="transacted" value="true"/> 
    <property name="concurrentConsumers" value="10"/> 
</bean> 

不过,我需要说服别人我谁是有点怀疑的工作,认为我集成测试仅适用于记录不良的副作用,而不是故意的弹簧功能。

所以我的问题是 - 我正确地认为可以依靠spring来同步事务,并且始终在jdbc事务之后提交jms事务,或者这不是我应该依赖的事情,并且可以指向任何官方文件说清楚了吗?我想一般来说,这是一个很好的方法来采取还是应该以不同的方式管理这些交易?

+0

你好,你现在有答案吗? – snowindy 2013-05-16 11:31:04

+0

嗨,不,不是。我还没有看到任何真正清晰的文档,这是我想要的,但我们现在正在生产中使用它,没有任何问题。 – laurie 2013-05-16 14:45:45

回答

3

本文可能对您有所帮助Distributed transactions in Spring, with and without XA。我不认为它特别涵盖你的案例 - 发送消息+更新数据库。

+0

谢谢,我已阅读过这篇文章几次。在“尽力而为1PC”部分,他们提供了两个春季同步的例子,但在一个中它们配置了一个TransactionAwareConnectionFactoryProxy,另一个配置了一个ChainedTransactionManager。如果我不需要做任何额外的配置来获得相同的结果,那么我宁可不要。 – laurie 2012-02-12 12:14:06

0

如果您正在使用本地事务 而用例是保存到数据库中,然后发送给JMS

就有可能出现三种情况:刚收到后

  1. 异常(DB和JMS之前)

没问题,一切都会rolledback

  • 保存到DB后,我们有例外
  • 如果有一个插入操作,就会出现由于多发的行中DB retries.With每次重试中,插入件将done.And为JMS,消息会去DeadLetterQueue中

  • 保存到数据库和发送到JMS后,我们有一个例外

    如果插入操作,就会出现在DB多发行由于retries.With每次重试,插件将完成。而对于JMS,消息会去DeadLetterQueue中

  • 现在你不想使用XA,这样的解决方案可能是

    1)检查,如果(混乱age.getJmsRedelivered(){...}

    如果不是,过程中它

    如果重新发送,请检查您是否处理它已经

    检查数据在数据库基础上的消息细节

    注意,重新交付是罕见的是,这种检查也属罕见,并且没有开销

    2)如果你的方法是幂等,那么你不需要这个检查

    和关于XA,XA保证消息被传递一次 并在多个资源

    但随着XA,你必须开销

    所以,如果你不XA管理,最好是

    同步交易