为什么远程 Weblogic JMS 不参与 spring 引导中的 XA 事务?
Why isn't Remote Weblogic JMS participating in XA Transaction in spring boot?
我正在开发一个 spring-boot 应用程序,我需要 XA 来确保 JPA 更新和 JMS 消息生成要么全有要么全无。问题是当回滚发生时,DB 正在回滚,而不是 JMS 消息。
我是 运行 嵌入式 tomcat 并且 JMS 服务器是 Weblogic12c。
我按照 spring-boot documentation 中的 JTA 说明添加了 Atomikos(transactions-jms
、transactions-jta
、transactions-jdbc
)以及 spring-boot-starter-jta-atomikos
的依赖项.
在日志中我可以看到 Atomikos 是 运行 并且似乎是 JPA 查询被添加到 XA 事务中,但 JMS 没有。
下面的日志来自我执行 JPA 更新的代码,然后使用 JMSTemplate
发送 JMS 消息,然后我抛出一个 RuntimeException
:
INFO c.a.jdbc.AbstractDataSourceBean - AtomikosDataSoureBean 'dataSource': getConnection ( null )...
INFO c.a.jdbc.AbstractDataSourceBean - AtomikosDataSoureBean 'dataSource': init...
INFO c.a.i.imp.CompositeTransactionImp - addParticipant ( XAResourceTransaction: 31302E33302E36302E3137332E746D30303030313030303434:31302E33302E36302E3137332E746D31 ) for transaction 10.30.60.173.tm0000100044
INFO c.a.d.xa.XAResourceTransaction - XAResource.start ( 31302E33302E36302E3137332E746D30303030313030303434:31302E33302E36302E3137332E746D31 , XAResource.TMJOIN ) on resource dataSource represented by XAResource instance oracle.jdbc.driver.T4CXAResource@621c7c98
INFO c.a.i.imp.CompositeTransactionImp - registerSynchronization ( com.atomikos.jdbc.AtomikosConnectionProxy$JdbcRequeueSynchronization@f4a9582b ) for transaction 10.30.60.173.tm0000100044
INFO c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for oracle.jdbc.driver.LogicalConnection@650a9087: calling prepareStatement(select prjct_rvsn_seq_num_seq.nextval from dual)...
INFO c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for oracle.jdbc.driver.LogicalConnection@650a9087: isClosed()...
INFO c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for oracle.jdbc.driver.LogicalConnection@650a9087: calling getWarnings...
INFO c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for oracle.jdbc.driver.LogicalConnection@650a9087: calling clearWarnings...
INFO c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for oracle.jdbc.driver.LogicalConnection@650a9087: close()...
INFO c.a.d.xa.XAResourceTransaction - XAResource.end ( 31302E33302E36302E3137332E746D30303030313030303434:31302E33302E36302E3137332E746D31 , XAResource.TMSUCCESS ) on resource dataSource represented by XAResource instance oracle.jdbc.driver.T4CXAResource@621c7c98
INFO c.c.ola.order.service.OrderService - Order saved of scope:FIRST with app ID:1127662
INFO c.c.o.o.s.OrderEventBroadcaster - Sending message on queue jms/AppQueue
DEBUG o.s.jms.core.JmsTemplate - Executing callback on JMS Session: weblogic.jms.client.WLSessionImpl@24cfb8e8
DEBUG o.s.j.s.d.JndiDestinationResolver - Located object with JNDI name [jms/AppQueue]
DEBUG o.s.jms.core.JmsTemplate - Sending created message: TextMessage[null, <?xml version="1.0" encoding="...]
INFO c.a.d.xa.XAResourceTransaction - XAResource.rollback ( 31302E33302E36302E3137332E746D30303030313030303434:31302E33302E36302E3137332E746D31 ) on resource dataSource represented by XAResource instance oracle.jdbc.driver.T4CXAResource@621c7c98
INFO com.atomikos.icatch.jta.Sync2Sync - afterCompletion ( STATUS_ROLLEDBACK ) called on Synchronization: org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization@25385341
INFO c.a.i.imp.CompositeTransactionImp - rollback() done of transaction 10.30.60.173.tm0000100044
在我的谷歌搜索中,我看到的不多。看起来它应该可以正常工作,但它不是我丢球的地方?
更新:
下面是我如何创建 ConnectionFactory
:
@Bean
FactoryBean<ConnectionFactory> jmsConnectionFactory(final JndiTemplate jndiTemplate) {
final JndiObjectFactoryBean beanFactory = new JndiObjectFactoryBean();
beanFactory.setJndiTemplate(jndiTemplate);
beanFactory.setJndiName("jms.remoteConnectionFactory");
beanFactory.setProxyInterface(ConnectionFactory.class);
return (FactoryBean) beanFactory;
}
更新:
由于日志引用了 weblogic.jms.client.WLSessionImpl
而不是名称中带有 "XA" 的内容,我调查了 weblogic 返回的内容。从 "jms.remoteConnectionFactory" 返回的实例是 weblogic.jms.client.JMSXAConnectionFactory
,它没有实现 javax.jms.XAConnectionFactory
,这看起来很奇怪。我不知道为什么会这样,或者这是否是问题,但看起来可能是这样。
我的解决方案是在 jmsTemplate
上将 sessionTransacted
设置为 true
。
@Bean
JmsTemplate cciSitesJmsTemplate(@CciSites final ConnectionFactory connectionFactory, final JndiDestinationResolver destinationResolver) {
final JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
jmsTemplate.setDestinationResolver(destinationResolver);
// NOTE: sessionTransacted is required to join the XA transaction
jmsTemplate.setSessionTransacted(true);
return jmsTemplate;
}
我正在开发一个 spring-boot 应用程序,我需要 XA 来确保 JPA 更新和 JMS 消息生成要么全有要么全无。问题是当回滚发生时,DB 正在回滚,而不是 JMS 消息。
我是 运行 嵌入式 tomcat 并且 JMS 服务器是 Weblogic12c。
我按照 spring-boot documentation 中的 JTA 说明添加了 Atomikos(transactions-jms
、transactions-jta
、transactions-jdbc
)以及 spring-boot-starter-jta-atomikos
的依赖项.
在日志中我可以看到 Atomikos 是 运行 并且似乎是 JPA 查询被添加到 XA 事务中,但 JMS 没有。
下面的日志来自我执行 JPA 更新的代码,然后使用 JMSTemplate
发送 JMS 消息,然后我抛出一个 RuntimeException
:
INFO c.a.jdbc.AbstractDataSourceBean - AtomikosDataSoureBean 'dataSource': getConnection ( null )...
INFO c.a.jdbc.AbstractDataSourceBean - AtomikosDataSoureBean 'dataSource': init...
INFO c.a.i.imp.CompositeTransactionImp - addParticipant ( XAResourceTransaction: 31302E33302E36302E3137332E746D30303030313030303434:31302E33302E36302E3137332E746D31 ) for transaction 10.30.60.173.tm0000100044
INFO c.a.d.xa.XAResourceTransaction - XAResource.start ( 31302E33302E36302E3137332E746D30303030313030303434:31302E33302E36302E3137332E746D31 , XAResource.TMJOIN ) on resource dataSource represented by XAResource instance oracle.jdbc.driver.T4CXAResource@621c7c98
INFO c.a.i.imp.CompositeTransactionImp - registerSynchronization ( com.atomikos.jdbc.AtomikosConnectionProxy$JdbcRequeueSynchronization@f4a9582b ) for transaction 10.30.60.173.tm0000100044
INFO c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for oracle.jdbc.driver.LogicalConnection@650a9087: calling prepareStatement(select prjct_rvsn_seq_num_seq.nextval from dual)...
INFO c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for oracle.jdbc.driver.LogicalConnection@650a9087: isClosed()...
INFO c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for oracle.jdbc.driver.LogicalConnection@650a9087: calling getWarnings...
INFO c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for oracle.jdbc.driver.LogicalConnection@650a9087: calling clearWarnings...
INFO c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for oracle.jdbc.driver.LogicalConnection@650a9087: close()...
INFO c.a.d.xa.XAResourceTransaction - XAResource.end ( 31302E33302E36302E3137332E746D30303030313030303434:31302E33302E36302E3137332E746D31 , XAResource.TMSUCCESS ) on resource dataSource represented by XAResource instance oracle.jdbc.driver.T4CXAResource@621c7c98
INFO c.c.ola.order.service.OrderService - Order saved of scope:FIRST with app ID:1127662
INFO c.c.o.o.s.OrderEventBroadcaster - Sending message on queue jms/AppQueue
DEBUG o.s.jms.core.JmsTemplate - Executing callback on JMS Session: weblogic.jms.client.WLSessionImpl@24cfb8e8
DEBUG o.s.j.s.d.JndiDestinationResolver - Located object with JNDI name [jms/AppQueue]
DEBUG o.s.jms.core.JmsTemplate - Sending created message: TextMessage[null, <?xml version="1.0" encoding="...]
INFO c.a.d.xa.XAResourceTransaction - XAResource.rollback ( 31302E33302E36302E3137332E746D30303030313030303434:31302E33302E36302E3137332E746D31 ) on resource dataSource represented by XAResource instance oracle.jdbc.driver.T4CXAResource@621c7c98
INFO com.atomikos.icatch.jta.Sync2Sync - afterCompletion ( STATUS_ROLLEDBACK ) called on Synchronization: org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization@25385341
INFO c.a.i.imp.CompositeTransactionImp - rollback() done of transaction 10.30.60.173.tm0000100044
在我的谷歌搜索中,我看到的不多。看起来它应该可以正常工作,但它不是我丢球的地方?
更新:
下面是我如何创建 ConnectionFactory
:
@Bean
FactoryBean<ConnectionFactory> jmsConnectionFactory(final JndiTemplate jndiTemplate) {
final JndiObjectFactoryBean beanFactory = new JndiObjectFactoryBean();
beanFactory.setJndiTemplate(jndiTemplate);
beanFactory.setJndiName("jms.remoteConnectionFactory");
beanFactory.setProxyInterface(ConnectionFactory.class);
return (FactoryBean) beanFactory;
}
更新:
由于日志引用了 weblogic.jms.client.WLSessionImpl
而不是名称中带有 "XA" 的内容,我调查了 weblogic 返回的内容。从 "jms.remoteConnectionFactory" 返回的实例是 weblogic.jms.client.JMSXAConnectionFactory
,它没有实现 javax.jms.XAConnectionFactory
,这看起来很奇怪。我不知道为什么会这样,或者这是否是问题,但看起来可能是这样。
我的解决方案是在 jmsTemplate
上将 sessionTransacted
设置为 true
。
@Bean
JmsTemplate cciSitesJmsTemplate(@CciSites final ConnectionFactory connectionFactory, final JndiDestinationResolver destinationResolver) {
final JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
jmsTemplate.setDestinationResolver(destinationResolver);
// NOTE: sessionTransacted is required to join the XA transaction
jmsTemplate.setSessionTransacted(true);
return jmsTemplate;
}