使用TransactionManager使用Spring JmsTemplate编写消息 [英] Writing messages with Spring JmsTemplate using a TransactionManager

查看:446
本文介绍了使用TransactionManager使用Spring JmsTemplate编写消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Spring-JMS可以通过 DefaultMessageListenerContainer

Using Spring-JMS it is possible to receive messages within an external transaction context via the DefaultMessageListenerContainer.

然而消息的唯一记录方式是通过 JmsTemplate.send(...)我无法看到如何强制使用给定的 TransactionManager

However the only documented way to write a message is via JmsTemplate.send(…) and I can't see how this can be coerced to use a given TransactionManager.

任何人都可以指出我正朝着正确的方向前进?

Can anyone point me in the right direction?

更多信息:确保事务管理器可用( WebSphereUowTransactionManager ),使用 JmsTemplate.write 针对Oracle AQjmsFactory.getQueueConnectionFactory(dataSource)导致:

More info: Ensuring a transaction manager is available (WebSphereUowTransactionManager), using JmsTemplate.write against an Oracle AQjmsFactory.getQueueConnectionFactory(dataSource) results in:

org.springframework.jms.UncategorizedJmsException: Uncategorized exception occured during JMS processing; nested exception is oracle.jms.AQjmsException: could not use local transaction commit in a global transaction
  at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:316)
  at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:168)
  at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:469)
  at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:534)
Caused by: oracle.jms.AQjmsException: could not use local transaction commit in a global transaction
  at oracle.jms.AQjmsSession.commitNoCheck(AQjmsSession.java:1053)
  at oracle.jms.AQjmsSession.commit(AQjmsSession.java:1021)
  at org.springframework.jms.support.JmsUtils.commitIfNecessary(JmsUtils.java:217)
  at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:573)
  at org.springframework.jms.core.JmsTemplate$3.doInJms(JmsTemplate.java:536)
  at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:466)
  ... 24 more
Caused by: java.sql.SQLException: could not use local transaction commit in a global transaction
  at oracle.jdbc.driver.PhysicalConnection.disallowGlobalTxnMode(PhysicalConnection.java:6647)
  at oracle.jdbc.driver.PhysicalConnection.commit(PhysicalConnection.java:3635)
  at oracle.jdbc.driver.PhysicalConnection.commit(PhysicalConnection.java:3680)
  at oracle.jdbc.OracleConnectionWrapper.commit(OracleConnectionWrapper.java:133)
  at oracle.jms.AQjmsSession.commitNoCheck(AQjmsSession.java:1049)
  ... 29 more

因此,虽然我没有理由怀疑下面的建议,但我无法对其进行测试因为我无法弄清楚如何让AQ JMS不尝试提交。随着我的了解更新将会更新。

So whilst I have no reason to doubt the advise below, I am not able to test it as I can't figure out how to get AQ JMS to not attempt a commit. Will update as I learn more.

推荐答案

我的理解是JMS生产者通过JTA进行固有交易。通过JMS MessageProducer 发送消息,使用线程本地JTA事务(如果存在)。

My understanding is that JMS producers are inherently transacted via JTA. By sending a message via JMS MessageProducer, the thread-local JTA transaction is used (if one is present).

这是Spring手册的暗示(部分21.2.5 ):

This is hinting at by the Spring manual (section 21.2.5):


JmsTemplate 也可以用于用于执行分布式事务的 JtaTransactionManager 和支持XA的JMS ConnectionFactory 。请注意,这需要使用JTA事务管理器以及正确配置XA的 ConnectionFactory

JmsTemplate can also be used with the JtaTransactionManager and an XA-capable JMS ConnectionFactory for performing distributed transactions. Note that this requires the use of a JTA transaction manager as well as a properly XA-configured ConnectionFactory.

这也是由 JmsAccessor.setSessionTransacted JmsTemplate 的超类)( javadoc ):

This is also suggested by JmsAccessor.setSessionTransacted (the superclass of JmsTemplate) (javadoc):


设置创建JMS会话时使用的事务模式。默认为false。
请注意,在JTA事务中,传递给 create(Queue / Topic)Session(boolean transacted,int acknowledgeMode)方法的参数不会被采用帐户。根据J2EE事务上下文,容器会自行决定这些值。类似地,这些参数也不会在本地管理的事务中考虑,因为在这种情况下访问者在现有的JMS会话上运行。

Set the transaction mode that is used when creating a JMS Session. Default is "false". Note that within a JTA transaction, the parameters passed to create(Queue/Topic)Session(boolean transacted, int acknowledgeMode) method are not taken into account. Depending on the J2EE transaction context, the container makes its own decisions on these values. Analogously, these parameters are not taken into account within a locally managed transaction either, since the accessor operates on an existing JMS Session in this case.

将此标志设置为true将在托管事务外部运行时使用短本地JMS事务,在托管事务时使用同步本地JMS事务(除了XA交易之外)。后者具有与主事务(可能是本机JDBC事务)一起管理的本地JMS事务的效果,JMS事务在主事务之后立即提交。

Setting this flag to "true" will use a short local JMS transaction when running outside of a managed transaction, and a synchronized local JMS transaction in case of a managed transaction (other than an XA transaction) being present. The latter has the effect of a local JMS transaction being managed alongside the main transaction (which might be a native JDBC transaction), with the JMS transaction committing right after the main transaction.

因此,通过启动JTA事务(即使用Spring的事务API与 JtaTransactionManager )并调用 JmsTemplate.send (...),您将发送绑定到该交易的消息。

So by start a JTA transaction (i.e. by using Spring's transaction API with JtaTransactionManager) and calling JmsTemplate.send(...), you will be sending the message bound to that transaction.

这篇关于使用TransactionManager使用Spring JmsTemplate编写消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆