问题
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:
- If
platformTransactionManager
isJtaTransactionManager
and transaction is started, it IS Spring managed transaction; JMS template attribute sessionTransacted is ignored and JMS template is part of transaction - if
platformTransactionManager
isDataSourceTransactionManager
orJpaTransactionManager
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
- if
来源:https://stackoverflow.com/questions/58491469/what-precisely-means-setsessiontransacted-in-jmstemplate