diff --git a/spring-tx/src/main/java/org/springframework/transaction/support/AbstractPlatformTransactionManager.java b/spring-tx/src/main/java/org/springframework/transaction/support/AbstractPlatformTransactionManager.java index b139b85f11..78a4de70e9 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/support/AbstractPlatformTransactionManager.java +++ b/spring-tx/src/main/java/org/springframework/transaction/support/AbstractPlatformTransactionManager.java @@ -416,7 +416,8 @@ public abstract class AbstractPlatformTransactionManager "isolation level will effectively be ignored: " + def); } boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); - return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null); + SuspendedResourcesHolder suspendedResources = suspend(null); + return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, suspendedResources); } } diff --git a/spring-tx/src/test/java/org/springframework/transaction/support/TransactionSupportTests.java b/spring-tx/src/test/java/org/springframework/transaction/support/TransactionSupportTests.java index eebc5f52c8..6467166ae2 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/support/TransactionSupportTests.java +++ b/spring-tx/src/test/java/org/springframework/transaction/support/TransactionSupportTests.java @@ -39,11 +39,14 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatRuntimeException; +import static org.springframework.transaction.TransactionDefinition.ISOLATION_READ_COMMITTED; import static org.springframework.transaction.TransactionDefinition.ISOLATION_REPEATABLE_READ; import static org.springframework.transaction.TransactionDefinition.ISOLATION_SERIALIZABLE; import static org.springframework.transaction.TransactionDefinition.PROPAGATION_MANDATORY; import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRED; import static org.springframework.transaction.TransactionDefinition.PROPAGATION_SUPPORTS; + +import static org.springframework.transaction.support.AbstractPlatformTransactionManager.SYNCHRONIZATION_ALWAYS; import static org.springframework.transaction.support.AbstractPlatformTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION; import static org.springframework.transaction.support.DefaultTransactionDefinition.PREFIX_ISOLATION; import static org.springframework.transaction.support.DefaultTransactionDefinition.PREFIX_PROPAGATION; @@ -78,6 +81,58 @@ class TransactionSupportTests { .isThrownBy(() -> tm.getTransaction(new DefaultTransactionDefinition(PROPAGATION_MANDATORY))); } + @Test + void noExistingTransactionWithExistingAnotherTransactionManager() { + AbstractPlatformTransactionManager tm1 = new TestTransactionManager(false, true); + tm1.setTransactionSynchronization(SYNCHRONIZATION_ALWAYS); + + DefaultTransactionDefinition txDef1 = + new DefaultTransactionDefinition(PROPAGATION_REQUIRED); + txDef1.setName("tx1"); + txDef1.setReadOnly(false); + txDef1.setIsolationLevel(ISOLATION_READ_COMMITTED); + + DefaultTransactionStatus txStatus1 = (DefaultTransactionStatus)tm1.getTransaction(txDef1); + + // assert for txStatus1 and TransactionSynchronizationManager property + assertThat(txStatus1.hasTransaction()).as("Must have transaction").isTrue(); + assertThat(txStatus1.isNewTransaction()).as("Must be new transaction").isTrue(); + assertThat(TransactionSynchronizationManager.isCurrentTransactionReadOnly()) + .as("Transaction1 Must be readOnly false") + .isEqualTo(txStatus1.isReadOnly()); + assertThat(TransactionSynchronizationManager.getCurrentTransactionName()) + .as("TransactionSynchronizationManager have correct transaction name") + .isEqualTo(txStatus1.getTransactionName()); + assertThat(TransactionSynchronizationManager.getCurrentTransactionIsolationLevel()) + .as("isolation level must be default").isNull(); + assertThat(TransactionSynchronizationManager.isSynchronizationActive()).isTrue(); + + // Setting another trnasaction manager + AbstractPlatformTransactionManager tm2 = new TestTransactionManager(false, true); + tm2.setTransactionSynchronization(SYNCHRONIZATION_ALWAYS); + + // Opening a new transaction before `transaction 1` commits. + DefaultTransactionDefinition txDef2 = + new DefaultTransactionDefinition(PROPAGATION_SUPPORTS); + txDef2.setReadOnly(true); + txDef2.setIsolationLevel(ISOLATION_REPEATABLE_READ); + txDef2.setName("tx2"); + + // assert for txStatus1 and TransactionSynchronizationManager property + DefaultTransactionStatus txStatus2 = (DefaultTransactionStatus) + tm2.getTransaction(txDef2); + assertThat(TransactionSynchronizationManager.isActualTransactionActive()).as("Must not have transaction") + .isEqualTo(txStatus2.hasTransaction()); + assertThat(TransactionSynchronizationManager.isCurrentTransactionReadOnly()).as("Must be readOnly true") + .isEqualTo(txStatus2.isReadOnly()); + assertThat(TransactionSynchronizationManager.getCurrentTransactionIsolationLevel()) + .as("isolation level must be Repeatable Read") + .isEqualTo(ISOLATION_REPEATABLE_READ); + assertThat(TransactionSynchronizationManager.isSynchronizationActive()).isTrue(); + + TransactionSynchronizationManager.clearSynchronization(); + } + @Test void existingTransaction() { PlatformTransactionManager tm = new TestTransactionManager(true, true);