Inherited @Transactional methods use wrong TransactionManager
See original GitHub issueSetup: In a multi-DB environment, there is an abstract Service/DAO class with @Transactional
methods common to all entities from all DBs. Then there are multiple concrete Service/DAO beans, one per DB, each with specific transactionManager in the class-level @Transactional
annotation.
Problem: When calling a base-class method via some DB-specific bean, a wrong transactionManager is used (always the @Primary
one). The worst is that no exceptions are thrown, no error messages printed in log. The entities are simply silently e.g. not saved/updated in DB. Or, I afraid, they could even be saved to wrong DB.
The problem has already been described at least in #14011, #14295, #17080. Related issue is also #11839. But all the issues have been closed (as outdated) without a solution.
There were also some workarounds: https://stackoverflow.com/questions/51087660/dynamic-selection-of-transactionmanager-spring-boot, https://www.tirasa.net/en/blog/dynamic-springs-at-transactional, also #14295. But they all are not working (anymore).
How can it be solved? What do you, guys, do in such situation? Am I missing something obvious? Thank you for your thoughts.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:6
- Comments:13 (2 by maintainers)
I finally managed to solve the problem without patching the spring-tx library (now, no need to create a patch for every new version of Spring):
The default “transactionAttributeSource” bean (defined in ProxyTransactionManagementConfiguration) will be replaced (1) by an instance of the own MergeAnnotationTransactionAttributeSource (2).
(1) AnnotationTransactionAttributeSourceReplacer
An important part was to implement the
PriorityOrdered
interface in the replacer, otherwise it was invoked too late (after instantiation of the “transactionAttributeSource” bean), see PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors for details. (Ordered
interface would probably suffice, too.)(2) MergeAnnotationTransactionAttributeSource
The PR with patch and additional unit test for the initial use case is created.
I also added the “declaring class of the specific method” again to “priorities” (as it was in the original implementation), while also keeping the previously added “target class”.
The new priorities are:
As the new (“merging”) behavior is not backward compatible, we would need some parameter to switch the implementation (TODO), e.g.