我使用Spring的DataSourceTransactionManager进行事务管理,使用JmsTemplate将消息发送到ActiveMQ队列。我的问题是强制在单个事务中使用下一个算法:
Step 1: update DB;
Step 2: send message to queue;
Step 3: update DB;
Step 4: send message to queue.
据我从JmsTemplate的文档中了解,在我的情况下,我必须设置参数" sessionTransacted" = true: 将此标志设置为" true"在托管事务外部运行时将使用短的本地JMS事务,并且在托管事务(XA事务除外)存在时使用同步的本地JMS事务。 后者具有与主事务(可能是本机JDBC事务)一起管理的本地JMS事务的效果,JMS事务在主事务之后立即提交。(c)
我的jms配置文件仅包含:
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" ref="url"/>
<property name="userName" ref="username"/>
<property name="password" ref="password"/>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="defaultDestinationName" value="SomeQueue"/>
<property name="sessionTransacted" value="true"/>
</bean>
之后我尝试以简单的方式测试它:
案例A:
@Transactional
public void sendMessageTransactionalErr(Object message, List<String> queueDestinationNames) throws Exception {
sender.sendMessage(message, queueDestinationNames);
throw new Exception("FatalException!");
}
案例B:
@Transactional
public void sendMessageTransactionalOK(Object message, List<String> queueDestinationNames) throws Exception {
sender.sendMessage(message, queueDestinationNames);
}
但是在两种情况下,请求执行消息都发送到队列。即使JDBC事务回滚,JMS事务提交也会成功。 我该怎么做才能让它按照我的需要工作?
答案 0 :(得分:1)
您需要使用一个事务管理器来处理您的JMS事务和数据库事务。您的JMS事务与数据库事务是分开的。
我不记得确切,但是当我遇到这个问题时,我创建了一个org.springframework.jms.connection.JmsTransactionManager
的实例。创建一个JTA事务管理器,并确保它知道这个和数据库事务管理器。
使用@Transactional("jtaTransactionManager")
作为注释。对于这个用例,我可能已经尝试过Bitronix或JOTM。