JMS 侦听器和 Oracle 数据源的 Atomikos 事务问题 - XID 引发 -4:提供的 XID 对于此 XA 资源无效
Atomikos transaction issue with JMS listener and Oracle datasource - XID raised -4: the supplied XID is invalid for this XA resource
我有一个 Web 应用程序从 MQ 收集数据并保存在数据库中。
使用 spring JMS 侦听器容器从 MQ 读取消息,
并使用休眠模板将这些消息保存在 XA Oracle 数据源上。
我正在使用 JTA 事务管理器处理这两个事务。
我一般它工作正常,但是
尝试保留在我的数据库中收到的消息时,我遇到了一个随机发生的问题。
Oracle 在尝试持久化数据时引发 XID 无效异常,并且整个全局事务回滚。
该问题很少发生,100 条消息中只有 1 条。但是不能只是理解原因。
我正在使用
MQ 客户端 7.5
Spring3.1.1.RELEASE
休眠 3.3.2.GA
Atomikos 4.0.6
下面是异常的完整堆栈跟踪:
2018-05-23 10:30:32,265 [Atomikos:989] WARN c.a.icatch.imp.ActiveStateHandler - Transaction 10.185.9.141.tm152706422182917585 has timed out and will rollback.
2018-05-23 10:30:36,194 [jmsContainerLuxembourg-2] WARN c.a.d.xa.XAResourceTransaction - XA resource 'oracle': resume for XID '31302E3138352E392E3134312E746D313532373036343232313832393137353835:31302E3138352E392E3134312E746D3839' raised -4: the supplied XID is invalid for this XA resource
oracle.jdbc.xa.OracleXAException: null
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1110)
at oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:240)
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:297)
at com.atomikos.datasource.xa.session.BranchEnlistedStateHandler.<init>(BranchEnlistedStateHandler.java:40)
at com.atomikos.datasource.xa.session.NotInBranchStateHandler.checkEnlistBeforeUse(NotInBranchStateHandler.java:46)
at com.atomikos.datasource.xa.session.TransactionContext.checkEnlistBeforeUse(TransactionContext.java:70)
at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:160)
at com.atomikos.jdbc.AtomikosConnectionProxy.enlist(AtomikosConnectionProxy.java:207)
at com.atomikos.jdbc.AtomikosConnectionProxy.invoke(AtomikosConnectionProxy.java:122)
at com.sun.proxy.$Proxy31.prepareStatement(Unknown Source)
at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:534)
at org.hibernate.jdbc.AbstractBatcher.prepareSelectStatement(AbstractBatcher.java:145)
at org.hibernate.id.SequenceGenerator.generate(SequenceGenerator.java:96)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523)
at org.springframework.orm.hibernate3.HibernateTemplate.doInHibernate(HibernateTemplate.java:740)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:737)
at com.fortis.be.ilms.server.feature.target2.entity.Target2Repository.saveOrUpdate(Target2Repository.java:114)
at com.fortis.be.ilms.server.feature.target2.Target2ListenerService.checkResponseType(Target2ListenerService.java:110)
at com.fortis.be.ilms.server.feature.target2.Target2Listener.onMessage(Target2Listener.java:79)
at com.fortis.be.ilms.server.feature.target2.Target2Listener.onMessage(Target2Listener.java:61)
at com.fortis.be.ilms.server.feature.target2.Target2JmsListener.onMessage(Target2JmsListener.java:23)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:326)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:244)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960)
at java.lang.Thread.run(Thread.java:745)
2018-05-23 10:30:36,195 [jmsContainerLuxembourg-2] WARN c.a.jdbc.JdbcConnectionProxyHelper - Error enlisting in transaction - connection might be broken? Please check the logs for more information...
com.atomikos.datasource.ResourceException: XA resource 'oracle': resume for XID '31302E3138352E392E3134312E746D313532373036343232313832393137353835:31302E3138352E392E3134312E746D3839' raised -4: the supplied XID is invalid for this XA resource
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:303)
at com.atomikos.datasource.xa.session.BranchEnlistedStateHandler.<init>(BranchEnlistedStateHandler.java:40)
at com.atomikos.datasource.xa.session.NotInBranchStateHandler.checkEnlistBeforeUse(NotInBranchStateHandler.java:46)
at com.atomikos.datasource.xa.session.TransactionContext.checkEnlistBeforeUse(TransactionContext.java:70)
at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:160)
at com.sun.proxy.$Proxy31.prepareStatement(Unknown Source)
at org.hibernate.jdbc.AbstractBatcher.prepareSelectStatement(AbstractBatcher.java:145)
at org.hibernate.id.SequenceGenerator.generate(SequenceGenerator.java:96) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:737)
at com.fortis.be.ilms.server.feature.target2.entity.Target2Repository.saveOrUpdate(Target2Repository.java:114)
at com.fortis.be.ilms.server.feature.target2.Target2ListenerService.calcMovements(Target2ListenerService.java:418)
at com.fortis.be.ilms.server.feature.target2.Target2ListenerService.treatReturnTransactionResponse(Target2ListenerService.java:281)
at com.fortis.be.ilms.server.feature.target2.Target2JmsListener.onMessage(Target2JmsListener.java:23)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:562)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:244)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960)
at java.lang.Thread.run(Thread.java:745)
Caused by: oracle.jdbc.xa.OracleXAException: null
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1110)
at oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:240)
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:297)
... 38 common frames omitted
2018-05-23 10:30:36,195 [jmsContainerLuxembourg-2] ERROR c.f.b.i.s.f.t.Target2JmsListener - Error on treating message from TARGET 2 !
com.atomikos.datasource.ResourceException: XA resource 'oracle': resume for XID '31302E3138352E392E3134312E746D313532373036343232313832393137353835:31302E3138352E392E3134312E746D3839' raised -4: the supplied XID is invalid for this XA resource
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:303)
at com.atomikos.datasource.xa.session.BranchEnlistedStateHandler.<init>(BranchEnlistedStateHandler.java:40)
at com.atomikos.datasource.xa.session.NotInBranchStateHandler.checkEnlistBeforeUse(NotInBranchStateHandler.java:46)
at com.atomikos.datasource.xa.session.TransactionContext.checkEnlistBeforeUse(TransactionContext.java:70)
at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:160)
at com.atomikos.jdbc.AtomikosConnectionProxy.enlist(AtomikosConnectionProxy.java:207)
at com.atomikos.jdbc.AtomikosConnectionProxy.invoke(AtomikosConnectionProxy.java:122)
at com.sun.proxy.$Proxy31.prepareStatement(Unknown Source)
at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:534)
at org.hibernate.jdbc.AbstractBatcher.prepareSelectStatement(AbstractBatcher.java:145)
at org.hibernate.id.SequenceGenerator.generate(SequenceGenerator.java:96)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:122)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523)
at org.springframework.orm.hibernate3.HibernateTemplate.doInHibernate(HibernateTemplate.java:740)
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:737)
at com.fortis.be.ilms.server.feature.target2.entity.Target2Repository.saveOrUpdate(Target2Repository.java:114)
at com.fortis.be.ilms.server.feature.target2.Target2ListenerService.calcMovements(Target2ListenerService.java:418)
at com.fortis.be.ilms.server.feature.target2.Target2ListenerService.treatReturnTransactionResponse(Target2ListenerService.java:281)
at com.fortis.be.ilms.server.feature.target2.Target2ListenerService.checkResponseType(Target2ListenerService.java:110)
at com.fortis.be.ilms.server.feature.target2.Target2Listener.onMessage(Target2Listener.java:79)
at com.fortis.be.ilms.server.feature.target2.Target2Listener.onMessage(Target2Listener.java:61)
at com.fortis.be.ilms.server.feature.target2.Target2JmsListener.onMessage(Target2JmsListener.java:23)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:562)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:500)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1071)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960)
at java.lang.Thread.run(Thread.java:745)
Caused by: oracle.jdbc.xa.OracleXAException: null
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1110)
at oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:240)
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:297)
... 38 common frames omitted
2018-05-23 10:30:36,197 [jmsContainerLuxembourg-2] WARN c.a.d.xa.XAResourceTransaction - XA resource 'oracle': resume for XID '31302E3138352E392E3134312E746D313532373036343232313832393137353835:31302E3138352E392E3134312E746D3839' raised -4: the supplied XID is invalid for this XA resource
oracle.jdbc.xa.OracleXAException: null
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1110)
at oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:240)
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:297)
at com.atomikos.datasource.xa.session.BranchEnlistedStateHandler.<init>(BranchEnlistedStateHandler.java:40)
at com.atomikos.datasource.xa.session.NotInBranchStateHandler.checkEnlistBeforeUse(NotInBranchStateHandler.java:46)
at com.atomikos.datasource.xa.session.TransactionContext.checkEnlistBeforeUse(TransactionContext.java:70)
at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:160)
at com.atomikos.jdbc.AtomikosConnectionProxy.enlist(AtomikosConnectionProxy.java:207)
at com.atomikos.jdbc.AtomikosConnectionProxy.invoke(AtomikosConnectionProxy.java:122)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109)
at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2678)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
at org.springframework.orm.hibernate3.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:145)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1063)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960)
at java.lang.Thread.run(Thread.java:745)
2018-05-23 10:30:36,197 [jmsContainerLuxembourg-2] WARN c.a.jdbc.JdbcConnectionProxyHelper - Error enlisting in transaction - connection might be broken? Please check the logs for more information...
com.atomikos.datasource.ResourceException: XA resource 'oracle': resume for XID '31302E3138352E392E3134312E746D313532373036343232313832393137353835:31302E3138352E392E3134312E746D3839' raised -4: the supplied XID is invalid for this XA resource
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:303)
at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:160)
at com.atomikos.jdbc.AtomikosConnectionProxy.enlist(AtomikosConnectionProxy.java:207)
at com.atomikos.jdbc.AtomikosConnectionProxy.invoke(AtomikosConnectionProxy.java:122)
at com.sun.proxy.$Proxy31.prepareStatement(Unknown Source)
at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:534)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:116)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109)
at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2242)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2678)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1063)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960)
at java.lang.Thread.run(Thread.java:745)
Caused by: oracle.jdbc.xa.OracleXAException: null
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1110)
at oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:240)
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:297)
... 30 common frames omitted
2018-05-23 10:30:37,229 [jmsContainerLuxembourg-2] WARN o.s.j.l.DefaultMessageListenerContainer - Setup of JMS message listener invoker failed for destination 'queue://FRILS01P/BGL.TO.ILMS.RESPONSE.MS5' - trying to recover. Cause: XA resource 'oracle': resume for XID '31302E3138352E392E3134312E746D313532373036343232313832393137353835:31302E3138352E392E3134312E746D3839' raised -4: the supplied XID is invalid for this XA resource
2018-05-23 10:30:37,231 [jmsContainerLuxembourg-2] INFO o.s.j.l.DefaultMessageListenerContainer - Successfully refreshed JMS Connection
为了让您详细了解我的设置,
我有一个通过 spring xml 文件配置的 JMS 侦听器容器,如下所示。
<!-- and this is the message listener container -->
<bean id="jmsContainerLuxembourg" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="mqQueueConnectionFactory"/>
<property name="destination" ref="jms-destination-target2-luxembourg"/>
<property name="messageListener" ref="t2messageListener" />
<property name="transactionManager" ref="transactionManager"/>
</bean>
下面是我的 oracle 数据源的配置:
<!-- XA DataSource for target2 services-->
<bean id="dataSourceTarget" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="oracle"/>
<property name="xaDataSourceClassName"><value>oracle.jdbc.xa.client.OracleXADataSource</value></property>
<property name="xaProperties">
<props>
<prop key="user">${jdbc.username}</prop>
<prop key="password">${jdbc.password}</prop>
<prop key="URL">${jdbc.url}</prop>
</props>
</property>
<property name="minPoolSize"><value>1</value></property>
<property name="maxPoolSize"><value>100</value></property>
<property name="borrowConnectionTimeout"><value>30</value></property>
<property name="maxIdleTime"><value>60</value></property>
<property name="reapTimeout"><value>0</value></property>
<property name="maintenanceInterval"><value>60</value></property>
</bean>
下面是我如何使用 Hibernate link 我的数据源:
<!-- Atomikos Transaction Configuration START -->
<!-- Hibernate SessionFactory For Target2 Listener Services-->
<bean id="sessionFactoryTarget"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="dataSourceTarget">
<property name="jtaTransactionManager" ref="AtomikosTransactionManager"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
<prop key="hibernate.cache.provider_class">${hibernate.cache.provider_class}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
<prop key="hibernate.transaction.factory_class">com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.fortis.be.ilms.**</value>
</list>
</property>
<property name="eventListeners">
<map>
<entry key="merge">
<bean
class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener" />
</entry>
</map>
</property>
</bean>
<bean id="hibernateTemplateTarget" class="org.springframework.orm.hibernate3.HibernateTemplate">
<constructor-arg><ref bean="sessionFactoryTarget"/></constructor-arg>
</bean>
这是我设置事务管理器的方式:
<!-- Atomikos Transaction Configuration START -->
<bean id="userTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp" init-method="init" destroy-method="shutdownForce">
<constructor-arg>
<!-- IMPORTANT: specify all Atomikos properties here -->
<props>
<prop key="com.atomikos.icatch.service">com.atomikos.icatch.standalone.UserTransactionServiceFactory</prop>
<prop key="com.atomikos.icatch.max_actives">-1</prop>
<prop key="com.atomikos.icatch.log_base_name">${atomikos.icatch.log_base_name}</prop>
<prop key="com.atomikos.icatch.output_dir">${atomikos.icatch.output_dir}</prop>
<prop key="com.atomikos.icatch.log_base_dir">${atomikos.icatch.log_base_dir}</prop>
</props>
</constructor-arg>
</bean>
<!-- Construct Atomikos UserTransactionManager, needed to configure Spring -->
<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close" depends-on="userTransactionService">
<!-- when close is called, should we force transactions to terminate or not? -->
<property name="forceShutdown" value="false" />
</bean>
<!-- Also use Atomikos UserTransactionImp, needed to configure Spring -->
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" depends-on="userTransactionService">
<property name="transactionTimeout" value="300" />
</bean>
<!-- Configure the Spring framework to use JTA transactions from Atomikos -->
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" depends-on="userTransactionService">
<property name="transactionManager" ref="AtomikosTransactionManager" />
<property name="userTransaction" ref="AtomikosUserTransaction" />
<qualifier value="atomikos"/>
</bean>
这是我的 JMS 侦听器 class:
@Component
@Scope("prototype")
public class Target2JmsListener implements MessageListener {
private final static Logger logger = Logger.getLogger(Target2JmsListener.class.getName());
@Autowired Target2Listener listener;
@Override
public void onMessage(Message msg) {
System.out.println("Received message from SIM [" + msg + "]");
try {
listener.onMessage(msg);
} catch (Exception ex) {
logger.error("Error on treating message from TARGET 2 !", ex);
}
}
}
以及试图通过休眠保存在 DB 中的 DAO:
@Component
public class Target2Repository {
private static final Logger LOGGER = Logger.getLogger(Target2Repository.class);
@Autowired
private HibernateTemplate hibernateTemplateTarget;
public void saveOrUpdate(Object entity) {
if (entity instanceof DbTarget2ControlM && Target2Repository.LOGGER.isDebugEnabled()) {
final DbTarget2ControlM ctrlM = (DbTarget2ControlM) entity;
Target2Repository.LOGGER.info("Control M is updated with : "
+ "Msg Id = " + ctrlM.getMsgId()
+ " Type = " + ctrlM.getMsgType()
+ " Status = " + ctrlM.getStatus());
}
this.hibernateTemplateTarget.saveOrUpdate(entity);
}
}
在此先感谢您的帮助
如我的评论所述,将 'sessionTransacted=true' 放在我的 JMS 侦听器容器上解决了我的问题。
我有一个 Web 应用程序从 MQ 收集数据并保存在数据库中。 使用 spring JMS 侦听器容器从 MQ 读取消息, 并使用休眠模板将这些消息保存在 XA Oracle 数据源上。 我正在使用 JTA 事务管理器处理这两个事务。 我一般它工作正常,但是 尝试保留在我的数据库中收到的消息时,我遇到了一个随机发生的问题。 Oracle 在尝试持久化数据时引发 XID 无效异常,并且整个全局事务回滚。 该问题很少发生,100 条消息中只有 1 条。但是不能只是理解原因。
我正在使用 MQ 客户端 7.5 Spring3.1.1.RELEASE 休眠 3.3.2.GA Atomikos 4.0.6
下面是异常的完整堆栈跟踪:
2018-05-23 10:30:32,265 [Atomikos:989] WARN c.a.icatch.imp.ActiveStateHandler - Transaction 10.185.9.141.tm152706422182917585 has timed out and will rollback.
2018-05-23 10:30:36,194 [jmsContainerLuxembourg-2] WARN c.a.d.xa.XAResourceTransaction - XA resource 'oracle': resume for XID '31302E3138352E392E3134312E746D313532373036343232313832393137353835:31302E3138352E392E3134312E746D3839' raised -4: the supplied XID is invalid for this XA resource
oracle.jdbc.xa.OracleXAException: null
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1110)
at oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:240)
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:297)
at com.atomikos.datasource.xa.session.BranchEnlistedStateHandler.<init>(BranchEnlistedStateHandler.java:40)
at com.atomikos.datasource.xa.session.NotInBranchStateHandler.checkEnlistBeforeUse(NotInBranchStateHandler.java:46)
at com.atomikos.datasource.xa.session.TransactionContext.checkEnlistBeforeUse(TransactionContext.java:70)
at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:160)
at com.atomikos.jdbc.AtomikosConnectionProxy.enlist(AtomikosConnectionProxy.java:207)
at com.atomikos.jdbc.AtomikosConnectionProxy.invoke(AtomikosConnectionProxy.java:122)
at com.sun.proxy.$Proxy31.prepareStatement(Unknown Source)
at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:534)
at org.hibernate.jdbc.AbstractBatcher.prepareSelectStatement(AbstractBatcher.java:145)
at org.hibernate.id.SequenceGenerator.generate(SequenceGenerator.java:96)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523)
at org.springframework.orm.hibernate3.HibernateTemplate.doInHibernate(HibernateTemplate.java:740)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:737)
at com.fortis.be.ilms.server.feature.target2.entity.Target2Repository.saveOrUpdate(Target2Repository.java:114)
at com.fortis.be.ilms.server.feature.target2.Target2ListenerService.checkResponseType(Target2ListenerService.java:110)
at com.fortis.be.ilms.server.feature.target2.Target2Listener.onMessage(Target2Listener.java:79)
at com.fortis.be.ilms.server.feature.target2.Target2Listener.onMessage(Target2Listener.java:61)
at com.fortis.be.ilms.server.feature.target2.Target2JmsListener.onMessage(Target2JmsListener.java:23)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:326)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:244)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960)
at java.lang.Thread.run(Thread.java:745)
2018-05-23 10:30:36,195 [jmsContainerLuxembourg-2] WARN c.a.jdbc.JdbcConnectionProxyHelper - Error enlisting in transaction - connection might be broken? Please check the logs for more information...
com.atomikos.datasource.ResourceException: XA resource 'oracle': resume for XID '31302E3138352E392E3134312E746D313532373036343232313832393137353835:31302E3138352E392E3134312E746D3839' raised -4: the supplied XID is invalid for this XA resource
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:303)
at com.atomikos.datasource.xa.session.BranchEnlistedStateHandler.<init>(BranchEnlistedStateHandler.java:40)
at com.atomikos.datasource.xa.session.NotInBranchStateHandler.checkEnlistBeforeUse(NotInBranchStateHandler.java:46)
at com.atomikos.datasource.xa.session.TransactionContext.checkEnlistBeforeUse(TransactionContext.java:70)
at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:160)
at com.sun.proxy.$Proxy31.prepareStatement(Unknown Source)
at org.hibernate.jdbc.AbstractBatcher.prepareSelectStatement(AbstractBatcher.java:145)
at org.hibernate.id.SequenceGenerator.generate(SequenceGenerator.java:96) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:737)
at com.fortis.be.ilms.server.feature.target2.entity.Target2Repository.saveOrUpdate(Target2Repository.java:114)
at com.fortis.be.ilms.server.feature.target2.Target2ListenerService.calcMovements(Target2ListenerService.java:418)
at com.fortis.be.ilms.server.feature.target2.Target2ListenerService.treatReturnTransactionResponse(Target2ListenerService.java:281)
at com.fortis.be.ilms.server.feature.target2.Target2JmsListener.onMessage(Target2JmsListener.java:23)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:562)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:244)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960)
at java.lang.Thread.run(Thread.java:745)
Caused by: oracle.jdbc.xa.OracleXAException: null
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1110)
at oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:240)
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:297)
... 38 common frames omitted
2018-05-23 10:30:36,195 [jmsContainerLuxembourg-2] ERROR c.f.b.i.s.f.t.Target2JmsListener - Error on treating message from TARGET 2 !
com.atomikos.datasource.ResourceException: XA resource 'oracle': resume for XID '31302E3138352E392E3134312E746D313532373036343232313832393137353835:31302E3138352E392E3134312E746D3839' raised -4: the supplied XID is invalid for this XA resource
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:303)
at com.atomikos.datasource.xa.session.BranchEnlistedStateHandler.<init>(BranchEnlistedStateHandler.java:40)
at com.atomikos.datasource.xa.session.NotInBranchStateHandler.checkEnlistBeforeUse(NotInBranchStateHandler.java:46)
at com.atomikos.datasource.xa.session.TransactionContext.checkEnlistBeforeUse(TransactionContext.java:70)
at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:160)
at com.atomikos.jdbc.AtomikosConnectionProxy.enlist(AtomikosConnectionProxy.java:207)
at com.atomikos.jdbc.AtomikosConnectionProxy.invoke(AtomikosConnectionProxy.java:122)
at com.sun.proxy.$Proxy31.prepareStatement(Unknown Source)
at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:534)
at org.hibernate.jdbc.AbstractBatcher.prepareSelectStatement(AbstractBatcher.java:145)
at org.hibernate.id.SequenceGenerator.generate(SequenceGenerator.java:96)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:122)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523)
at org.springframework.orm.hibernate3.HibernateTemplate.doInHibernate(HibernateTemplate.java:740)
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:737)
at com.fortis.be.ilms.server.feature.target2.entity.Target2Repository.saveOrUpdate(Target2Repository.java:114)
at com.fortis.be.ilms.server.feature.target2.Target2ListenerService.calcMovements(Target2ListenerService.java:418)
at com.fortis.be.ilms.server.feature.target2.Target2ListenerService.treatReturnTransactionResponse(Target2ListenerService.java:281)
at com.fortis.be.ilms.server.feature.target2.Target2ListenerService.checkResponseType(Target2ListenerService.java:110)
at com.fortis.be.ilms.server.feature.target2.Target2Listener.onMessage(Target2Listener.java:79)
at com.fortis.be.ilms.server.feature.target2.Target2Listener.onMessage(Target2Listener.java:61)
at com.fortis.be.ilms.server.feature.target2.Target2JmsListener.onMessage(Target2JmsListener.java:23)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:562)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:500)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1071)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960)
at java.lang.Thread.run(Thread.java:745)
Caused by: oracle.jdbc.xa.OracleXAException: null
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1110)
at oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:240)
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:297)
... 38 common frames omitted
2018-05-23 10:30:36,197 [jmsContainerLuxembourg-2] WARN c.a.d.xa.XAResourceTransaction - XA resource 'oracle': resume for XID '31302E3138352E392E3134312E746D313532373036343232313832393137353835:31302E3138352E392E3134312E746D3839' raised -4: the supplied XID is invalid for this XA resource
oracle.jdbc.xa.OracleXAException: null
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1110)
at oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:240)
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:297)
at com.atomikos.datasource.xa.session.BranchEnlistedStateHandler.<init>(BranchEnlistedStateHandler.java:40)
at com.atomikos.datasource.xa.session.NotInBranchStateHandler.checkEnlistBeforeUse(NotInBranchStateHandler.java:46)
at com.atomikos.datasource.xa.session.TransactionContext.checkEnlistBeforeUse(TransactionContext.java:70)
at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:160)
at com.atomikos.jdbc.AtomikosConnectionProxy.enlist(AtomikosConnectionProxy.java:207)
at com.atomikos.jdbc.AtomikosConnectionProxy.invoke(AtomikosConnectionProxy.java:122)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109)
at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2678)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
at org.springframework.orm.hibernate3.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:145)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1063)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960)
at java.lang.Thread.run(Thread.java:745)
2018-05-23 10:30:36,197 [jmsContainerLuxembourg-2] WARN c.a.jdbc.JdbcConnectionProxyHelper - Error enlisting in transaction - connection might be broken? Please check the logs for more information...
com.atomikos.datasource.ResourceException: XA resource 'oracle': resume for XID '31302E3138352E392E3134312E746D313532373036343232313832393137353835:31302E3138352E392E3134312E746D3839' raised -4: the supplied XID is invalid for this XA resource
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:303)
at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:160)
at com.atomikos.jdbc.AtomikosConnectionProxy.enlist(AtomikosConnectionProxy.java:207)
at com.atomikos.jdbc.AtomikosConnectionProxy.invoke(AtomikosConnectionProxy.java:122)
at com.sun.proxy.$Proxy31.prepareStatement(Unknown Source)
at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:534)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:116)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109)
at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2242)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2678)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1063)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960)
at java.lang.Thread.run(Thread.java:745)
Caused by: oracle.jdbc.xa.OracleXAException: null
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1110)
at oracle.jdbc.xa.client.OracleXAResource.start(OracleXAResource.java:240)
at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:297)
... 30 common frames omitted
2018-05-23 10:30:37,229 [jmsContainerLuxembourg-2] WARN o.s.j.l.DefaultMessageListenerContainer - Setup of JMS message listener invoker failed for destination 'queue://FRILS01P/BGL.TO.ILMS.RESPONSE.MS5' - trying to recover. Cause: XA resource 'oracle': resume for XID '31302E3138352E392E3134312E746D313532373036343232313832393137353835:31302E3138352E392E3134312E746D3839' raised -4: the supplied XID is invalid for this XA resource
2018-05-23 10:30:37,231 [jmsContainerLuxembourg-2] INFO o.s.j.l.DefaultMessageListenerContainer - Successfully refreshed JMS Connection
为了让您详细了解我的设置, 我有一个通过 spring xml 文件配置的 JMS 侦听器容器,如下所示。
<!-- and this is the message listener container -->
<bean id="jmsContainerLuxembourg" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="mqQueueConnectionFactory"/>
<property name="destination" ref="jms-destination-target2-luxembourg"/>
<property name="messageListener" ref="t2messageListener" />
<property name="transactionManager" ref="transactionManager"/>
</bean>
下面是我的 oracle 数据源的配置:
<!-- XA DataSource for target2 services-->
<bean id="dataSourceTarget" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="oracle"/>
<property name="xaDataSourceClassName"><value>oracle.jdbc.xa.client.OracleXADataSource</value></property>
<property name="xaProperties">
<props>
<prop key="user">${jdbc.username}</prop>
<prop key="password">${jdbc.password}</prop>
<prop key="URL">${jdbc.url}</prop>
</props>
</property>
<property name="minPoolSize"><value>1</value></property>
<property name="maxPoolSize"><value>100</value></property>
<property name="borrowConnectionTimeout"><value>30</value></property>
<property name="maxIdleTime"><value>60</value></property>
<property name="reapTimeout"><value>0</value></property>
<property name="maintenanceInterval"><value>60</value></property>
</bean>
下面是我如何使用 Hibernate link 我的数据源:
<!-- Atomikos Transaction Configuration START -->
<!-- Hibernate SessionFactory For Target2 Listener Services-->
<bean id="sessionFactoryTarget"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="dataSourceTarget">
<property name="jtaTransactionManager" ref="AtomikosTransactionManager"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
<prop key="hibernate.cache.provider_class">${hibernate.cache.provider_class}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
<prop key="hibernate.transaction.factory_class">com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.fortis.be.ilms.**</value>
</list>
</property>
<property name="eventListeners">
<map>
<entry key="merge">
<bean
class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener" />
</entry>
</map>
</property>
</bean>
<bean id="hibernateTemplateTarget" class="org.springframework.orm.hibernate3.HibernateTemplate">
<constructor-arg><ref bean="sessionFactoryTarget"/></constructor-arg>
</bean>
这是我设置事务管理器的方式:
<!-- Atomikos Transaction Configuration START -->
<bean id="userTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp" init-method="init" destroy-method="shutdownForce">
<constructor-arg>
<!-- IMPORTANT: specify all Atomikos properties here -->
<props>
<prop key="com.atomikos.icatch.service">com.atomikos.icatch.standalone.UserTransactionServiceFactory</prop>
<prop key="com.atomikos.icatch.max_actives">-1</prop>
<prop key="com.atomikos.icatch.log_base_name">${atomikos.icatch.log_base_name}</prop>
<prop key="com.atomikos.icatch.output_dir">${atomikos.icatch.output_dir}</prop>
<prop key="com.atomikos.icatch.log_base_dir">${atomikos.icatch.log_base_dir}</prop>
</props>
</constructor-arg>
</bean>
<!-- Construct Atomikos UserTransactionManager, needed to configure Spring -->
<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close" depends-on="userTransactionService">
<!-- when close is called, should we force transactions to terminate or not? -->
<property name="forceShutdown" value="false" />
</bean>
<!-- Also use Atomikos UserTransactionImp, needed to configure Spring -->
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" depends-on="userTransactionService">
<property name="transactionTimeout" value="300" />
</bean>
<!-- Configure the Spring framework to use JTA transactions from Atomikos -->
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" depends-on="userTransactionService">
<property name="transactionManager" ref="AtomikosTransactionManager" />
<property name="userTransaction" ref="AtomikosUserTransaction" />
<qualifier value="atomikos"/>
</bean>
这是我的 JMS 侦听器 class:
@Component
@Scope("prototype")
public class Target2JmsListener implements MessageListener {
private final static Logger logger = Logger.getLogger(Target2JmsListener.class.getName());
@Autowired Target2Listener listener;
@Override
public void onMessage(Message msg) {
System.out.println("Received message from SIM [" + msg + "]");
try {
listener.onMessage(msg);
} catch (Exception ex) {
logger.error("Error on treating message from TARGET 2 !", ex);
}
}
}
以及试图通过休眠保存在 DB 中的 DAO:
@Component
public class Target2Repository {
private static final Logger LOGGER = Logger.getLogger(Target2Repository.class);
@Autowired
private HibernateTemplate hibernateTemplateTarget;
public void saveOrUpdate(Object entity) {
if (entity instanceof DbTarget2ControlM && Target2Repository.LOGGER.isDebugEnabled()) {
final DbTarget2ControlM ctrlM = (DbTarget2ControlM) entity;
Target2Repository.LOGGER.info("Control M is updated with : "
+ "Msg Id = " + ctrlM.getMsgId()
+ " Type = " + ctrlM.getMsgType()
+ " Status = " + ctrlM.getStatus());
}
this.hibernateTemplateTarget.saveOrUpdate(entity);
}
}
在此先感谢您的帮助
如我的评论所述,将 'sessionTransacted=true' 放在我的 JMS 侦听器容器上解决了我的问题。