Affects: 5.3.22
I am trying to add a secondary DataSource to my application. Therefore, I have made sure I have 2 instances of the following beans: - DataSource - EntityManagerFactory - PlatformTransactionManager
I created this little test:
@SpringBootTest
class ReplicaTest {
@Inject private PlatformTransactionManager masterTransactionManager;
@Inject private EntityManager masterEntityManager;
@Qualifier(ReplicaDataSourceBeanNames.TRANSACTION_MANAGER)
@Inject
private PlatformTransactionManager replicaTransactionManager;
@Qualifier(ReplicaDataSourceBeanNames.ENTITY_MANAGER_FACTORY)
@Inject
private EntityManager replicaEntityManager;
@Test
void test1() {
masterTransactionTemplate.execute(
s -> {
Foo newFoo = new Foo();
replicaEntityManager.persist(newFoo);
return newFoo;
});
}
@Test
void test2() {
replicaEntityManager.persist(newFoo);
}
}
What happens: test1
does not fail while test2
fails with javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
.
What I expect: both tests should fail since replicaEntityManager
has been linked to replicaTransactionManager
during the configuration phase.
SharedEntityManagerCreator
relies on TransactionSynchronizationManager.isActualTransactionActive() to decide wheter a transaction is active. But it does not discriminate the transaction by originating TransactionManager.
Spring allows to qualitfy the requested TransactionManager
in multiple places:
- https://github.com/spring-projects/spring-framework/blob/5e808ad0183a63944ab08017a13cbc7ed75bc581/spring-tx/src/main/java/org/springframework/transaction/annotation/Transactional.java#L129
- https://github.com/spring-projects/spring-data-jpa/blob/88dffa8e90caa1cb39345decd6d697318210f5a8/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/config/EnableJpaRepositories.java#L138
But at the same time relies heavily on TransactionSynchronizationManager.isActualTransactionActive() without carring about the originating transaction manager.
So looks like a bug to me.
Comment From: reda-alaoui
Here is a reproducer: https://github.com/Cosium/spring-framework/blob/2332bc659f1bb089da1b98b26f6ca572face29ab/spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateMultiEntityManagerFactoryIntegrationTests.java#L77-L77
The test will fail because sharedEntityManager.persist(person)
will find the wrong active TransactionManager
.
Note that sharedEntityManager
is controlled by transactionManager
, not transactionManager2
.
Comment From: bclozel
Closing in favor of #29371