What precisely means setSessionTransacted in JMSTemplate?

半世苍凉 提交于 2019-12-24 18:18:10

问题


Please explain me if I understood correctly Spring documentation.

Spring docs states: https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#jms-tx

(...)When you use the JmsTemplate in an unmanaged environment, you can specify these values (transaction and acknowledgment modes) through the use of the properties sessionTransacted and sessionAcknowledgeMode.

When you use a PlatformTransactionManager with JmsTemplate, the template is always given a transactional JMS Session.(..)

(BTW, that is true - session is transactional)

Javadoc states : https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jms/core/JmsTemplate.html

Default settings for JMS Sessions are "not transacted" and "auto-acknowledge". As defined by the Java EE specification, the transaction and acknowledgement parameters are ignored when a JMS Session is created inside an active transaction, no matter if a JTA transaction or a Spring-managed transaction.

I understood that if transaction is active, JMS Template session transaction settings are ignored - that is true - and the session should participate active transaction - that is not true.

I debug why it is not true and I found: https://github.com/spring-projects/spring-framework/blame/master/spring-jms/src/main/java/org/springframework/jms/connection/ConnectionFactoryUtils.java#L353

if (resourceHolderToUse != resourceHolder) {
  TransactionSynchronizationManager.registerSynchronization(
    new JmsResourceSynchronization(resourceHolderToUse, connectionFactory,

 resourceFactory.isSynchedLocalTransactionAllowed()));
 resourceHolderToUse.setSynchronizedWithTransaction(true);
 TransactionSynchronizationManager.bindResource(connectionFactory, resourceHolderToUse);
}

The line resourceHolderToUse.setSynchronizedWithTransaction(true) is align the documentation.

The issue here: resourceFactory.isSynchedLocalTransactionAllowed()

Because resourceFactory is org.springframework.jms.core.JmsTemplate.JmsTemplateResourceFactory#isSynchedLocalTransactionAllowed which points to JmsTemplate#sessionTransacted.

Conclusion: According to documentation, if transaction is active, JmsTemplate#sessionTransacted should be ignored. But it is not true - although session is transactional, cannot not participate in commit.

JmsTemplate#sessionTransacted is finally mapped to ConnectionFactoryUtils.JmsResourceSynchronization#transacted and default=false prevents commit being called at the end of transaction (JmsResourceSynchronization "thinks" that it does not participate transaction)

Do I understand documentation right and there is really bug here?


回答1:


Guided by M. Deinum, I made more experiments and it seems I wrongly understood term Spring-managed transaction

I simply thought that Spring managed transaction is started by platformTransactionManager. But:

  1. If platformTransactionManager is JtaTransactionManager and transaction is started, it IS Spring managed transaction; JMS template attribute sessionTransacted is ignored and JMS template is part of transaction
  2. if platformTransactionManager is DataSourceTransactionManager or JpaTransactionManager then
    • if sessionTransacted is false, JMS template is not in transaction
    • if sessionTransacted is true, JMS template is synchronized with transaction: after callback/rollback on JDBC/JPA transaction correspondent commit/rollback is called on JMS transaction


来源:https://stackoverflow.com/questions/58491469/what-precisely-means-setsessiontransacted-in-jmstemplate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!