Spring Boot version: 3.2.1
If I use the following two services:
@Service
class Service1(
private val service2: Service2
) {
private val log = LoggerFactory.getLogger(this.javaClass)
@Transactional(propagation = Propagation.REQUIRES_NEW)
fun method1() {
log.error("Name from TransactionAspectSupport: " + TransactionAspectSupport.currentTransactionStatus().transactionName)
log.error("Name from TransactionSynchronizationManager: " + TransactionSynchronizationManager.getCurrentTransactionName())
service2.method2()
}
}
@Service
class Service2 {
private val log = LoggerFactory.getLogger(this.javaClass)
@Transactional
fun method2() {
log.error("Name from TransactionAspectSupport: " + TransactionAspectSupport.currentTransactionStatus().transactionName)
log.error("Name from TransactionSynchronizationManager: " + TransactionSynchronizationManager.getCurrentTransactionName())
}
}
the following is printed:
2024-02-22T13:15:35.240+03:00 ERROR 21308 --- [sb-repro] [nio-8080-exec-1] c.r.s.persistence.service.Service1 : Name from TransactionAspectSupport: com.romankudryashov.sbrepro.persistence.service.Service1.method1
2024-02-22T13:15:35.240+03:00 ERROR 21308 --- [sb-repro] [nio-8080-exec-1] c.r.s.persistence.service.Service1 : Name from TransactionSynchronizationManager: com.romankudryashov.sbrepro.persistence.service.Service1.method1
2024-02-22T13:15:35.240+03:00 ERROR 21308 --- [sb-repro] [nio-8080-exec-1] c.r.s.persistence.service.Service2 : Name from TransactionAspectSupport: com.romankudryashov.sbrepro.persistence.service.Service2.method2
2024-02-22T13:15:35.240+03:00 ERROR 21308 --- [sb-repro] [nio-8080-exec-1] c.r.s.persistence.service.Service2 : Name from TransactionSynchronizationManager: com.romankudryashov.sbrepro.persistence.service.Service1.method1
That is TransactionAspectSupport
and TransactionSynchronizationManager
behavior differs for method2
. And TransactionAspectSupport
mistakenly prints wrong transaction name.
If I remove @Transactional
from method2
, all is correct.
To reproduce, you can use: https://github.com/rkudryashov/sb-repro and call http://localhost:8080/test
Comment From: jhoeller
This is a consequence of the different meaning of "transaction" for those two calls: TransactionAspectSupport.currentTransactionStatus()
exposes the locally declared transaction boundary as managed by the aspect (even if it ends up participating in an outer transaction at runtime where the local boundary is less relevant), whereas TransactionSynchronizationManager.getCurrentTransactionName()
exposes the current (outer) resource transaction.
Since TransactionAspectSupport.currentTransactionStatus()
is a rather internal API and shares behavior with TransactionCallback
exposure in TransactionTemplate
usage, the behavior should rather remain as it is. We need to document that difference though and suggest TransactionSynchronizationManager
as the primary API to interact with the actual resource transaction.