List of usage examples for org.springframework.transaction TransactionDefinition PROPAGATION_NESTED
int PROPAGATION_NESTED
To view the source code for org.springframework.transaction TransactionDefinition PROPAGATION_NESTED.
Click Source Link
From source file:org.dalesbred.integration.spring.SpringTransactionManager.java
static int springPropagationCode(@NotNull Propagation propagation) { switch (propagation) { case REQUIRED: return TransactionDefinition.PROPAGATION_REQUIRED; case MANDATORY: return TransactionDefinition.PROPAGATION_MANDATORY; case NESTED://from w w w. ja va 2 s. co m return TransactionDefinition.PROPAGATION_NESTED; case REQUIRES_NEW: return TransactionDefinition.PROPAGATION_REQUIRES_NEW; } throw new IllegalArgumentException("unknown propagation: " + propagation); }
From source file:com.newmainsoftech.spray.slingong.datastore.Slim3PlatformTransactionManager.java
@Override protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException { // Validation on transaction argument ----------------------------------------------------- /* transaction Object should be either * null/*from ww w.ja va2 s.com*/ * either TransactionDefinition.PROPAGATION_REQUIRED, * TransactionDefinition.PROPAGATION_REQUIRES_NEW or TransactionDefinition.PROPAGATION_NESTED * active GlobalTransactoin object (one before current one) * either TransactionDefinition.PROPAGATION_REQUIRES_NEW or * TransactionDefinition.PROPAGATION_NESTED * if TransactionDefinition.PROPAGATION_NESTED case, then * useSavepointForNestedTransaction method returns false */ GlobalTransaction gtx = (GlobalTransaction) transaction; Set<GlobalTransactionState> gtxStateSet = getGlobalTransactionStates(gtx); GlobalTransaction currentGtx = Datastore.getCurrentGlobalTransaction(); Set<GlobalTransactionState> currentGtxStateSet = getGlobalTransactionStates(currentGtx); if (!currentGtxStateSet.contains(GlobalTransactionState.ActiveGlobalTransaction)) { throw new IllegalTransactionStateException(String.format( "Unexpected system state: getCurrentGlobalTransaction method of Slim3 Datastore " + "returned inactive GlobalTransaction instance (ID:%3$s). Expected it to return " + "active GlobalTransaction instance as new GlobalTransaction instance has begun " + "by newTransactionStatus method.", (currentGtxStateSet.contains(GlobalTransactionState.GlobalTransactionInstance) ? currentGtx.getId() : "null"))); } String gtxIdStr = (gtxStateSet.contains(GlobalTransactionState.GlobalTransactionInstance) ? gtx.getId() : "null"); if (gtxIdStr.equals(currentGtx.getId())) { throw new IllegalTransactionStateException(String.format( "Unexpected system state: the transaction Object argument refers to current " + "active GlobalTransaction instance (ID:%1$s). Expected it not to refer to " + "current active GlobalTransaction instance rather refer to the GlobalTransaction " + "instance available before newTransaction method execution or hold null value.", gtxIdStr)); } if (!gtxStateSet.contains(GlobalTransactionState.GlobalTransactionInstance)) { switch (definition.getPropagationBehavior()) { case TransactionDefinition.PROPAGATION_REQUIRED: case TransactionDefinition.PROPAGATION_REQUIRES_NEW: case TransactionDefinition.PROPAGATION_NESTED: break; default: throw new IllegalTransactionStateException(String.format( "Unexpected system state: found that the %1$s propagation behavior (%2$d) was " + "specified when the transaction Object argument holds null value. Expected " + "propagation behavior to be either PROPAGATION_REQUIRED (%3$d), " + "PROPAGATION_REQUIRES_NEW (%4$d) or PROPAGATION_NESTED (%5$d) when the " + "transaction Object argument holds null value.", getPropagationBehaviorStr(definition.getPropagationBehavior()), definition.getPropagationBehavior(), TransactionDefinition.PROPAGATION_REQUIRED, TransactionDefinition.PROPAGATION_REQUIRES_NEW, TransactionDefinition.PROPAGATION_NESTED)); } // switch } else if (gtxStateSet.contains(GlobalTransactionState.ActiveGlobalTransaction)) { switch (definition.getPropagationBehavior()) { case TransactionDefinition.PROPAGATION_REQUIRES_NEW: case TransactionDefinition.PROPAGATION_NESTED: break; default: throw new IllegalTransactionStateException(String.format( "Unexpected system state: found that the %1$s propagation behavior (%2$d) was " + "specified when the transaction Object argument holds active " + "GlobalTransaction instance (ID:%3$s). Expected propagation behavior to be " + "either PROPAGATION_REQUIRES_NEW (%4$d) or PROPAGATION_NESTED (%5$d) when " + "the transaction Object argument holds active GlobalTransaction instance.", getPropagationBehaviorStr(definition.getPropagationBehavior()), definition.getPropagationBehavior(), gtx.getId(), TransactionDefinition.PROPAGATION_REQUIRES_NEW, TransactionDefinition.PROPAGATION_NESTED)); } // switch } else { throw new IllegalTransactionStateException( String.format("Unexpected system state: the transaction Object argument holds inactive " + "GlobalTransaction instance (ID:%1$s). Expected it to hold either null or " + "active GlobalTransaction instance.", gtx.getId())); } // ---------------------------------------------------------------------------------------- }
From source file:com.newmainsoftech.spray.slingong.datastore.Slim3PlatformTransactionManagerTest.java
protected void verifyNotGetNewTransactionProcess(boolean existingTransactionFlag, int isolationLevel, int propagationBehavior, int timeOutSec, boolean debugEnabled) { // public final TransactionStatus getTransaction(TransactionDefinition definition) mockedSlim3TxMangerInOrder.verify(slim3PlatformTransactionManager, Mockito.times(1)).doGetTransaction(); ArgumentCaptor<GlobalTransaction> globalTransactionArgumentCaptor = ArgumentCaptor .forClass(GlobalTransaction.class); mockedSlim3TxMangerInOrder.verify(slim3PlatformTransactionManager, Mockito.times(1)) .getGlobalTransactionStates(globalTransactionArgumentCaptor.capture()); GlobalTransaction gtx = globalTransactionArgumentCaptor.getValue(); if (existingTransactionFlag) { Assert.assertTrue(gtx instanceof GlobalTransaction); } else {/*w w w . j a va 2 s.c o m*/ Assert.assertNull(gtx); } ArgumentCaptor<Object> objectArgumentCaptor = ArgumentCaptor.forClass(Object.class); mockedSlim3TxMangerInOrder.verify(slim3PlatformTransactionManager, Mockito.times(1)) .isExistingTransaction(Mockito.eq(gtx)); mockedSlim3TxMangerInOrder.verify(slim3PlatformTransactionManager, Mockito.times(1)) .getGlobalTransactionStates(Mockito.eq(gtx)); if (existingTransactionFlag) { Assert.fail("Wrong usage of this test method; should be used for the case that " + "no GlobalTransaction is available"); /* The below codes are for the time to extend this test method to handle (active) GlobalTransaction is available. // private TransactionStatus handleExistingTransaction( TransactionDefinition definition, Object transaction, boolean debugEnabled) switch( propagationBehavior) { case TransactionAttribute.PROPAGATION_NEVER: // Do nothing since IllegalTransactionStateException should have been thrown at // AbstractPlatformTransactionManager.handleExistingTransaction method. break; case TransactionAttribute.PROPAGATION_NOT_SUPPORTED: case TransactionDefinition.PROPAGATION_REQUIRES_NEW: // Do nothing since, in this scenario, TransactionSuspensionNotSupportedException // should have been thrown at AbstractPlatformTransactionManager.doSuspend method // by following logic flow: // protected final SuspendedResourcesHolder suspend(Object transaction) // - TransactionSynchronizationManager.isSynchronizationActive() should always be false // due to Slim3PlatformTransactionManager does not support transaction synchronization currently. // - transaction argument to suspend method should not be null due to // value of existingTransactionFlag argument to this verifyNotGetNewTransactionProcess method. // protected Object doSuspend(Object transaction) // throws TransactionSuspensionNotSupportedException break; case TransactionDefinition.PROPAGATION_NESTED: // Do nothing since, in this scenario, NestedTransactionNotSupportedException should // have been thrown at AbstractPlatformTransactionManager.handleExistingTransaction // by following logic below // public final boolean isNestedTransactionAllowed() // Should return false because the use case of this verifyNotGetNewTransactionProcess // method is for not getting new transaction. break; default: // public final boolean isValidateExistingTransaction() // IllegalTransactionStateException can be thrown depends on value of isolation // public final int getTransactionSynchronization() // protected final DefaultTransactionStatus prepareTransactionStatus( TransactionDefinition definition, Object transaction, boolean newTransaction, boolean newSynchronization, boolean debug, Object suspendedResources) ArgumentCaptor<TransactionDefinition> transactionDefinitionArgumentCaptor = ArgumentCaptor.forClass( TransactionDefinition.class); ArgumentCaptor<Boolean> booleanArgumentCaptor = ArgumentCaptor.forClass( Boolean.class); mockedSlim3TxMangerInOrder.verify( slim3PlatformTransactionManager, Mockito.times( 1)) .newTransactionStatus( transactionDefinitionArgumentCaptor.capture(), // TransactionDefinition definition Mockito.eq( gtx), // Object transaction Mockito.eq( false), Mockito.eq( false), // boolean newTransaction, boolean newSynchronization Mockito.eq( debugEnabled), Mockito.eq( null) //boolean debug, Object suspendedResources ); TransactionDefinition transactionDefinition = transactionDefinitionArgumentCaptor.getValue(); Assert.assertEquals( isolationLevel, transactionDefinition.getIsolationLevel()); Assert.assertEquals( propagationBehavior, transactionDefinition.getPropagationBehavior()); Assert.assertEquals( timeOutSec, transactionDefinition.getTimeout()); // protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) break; } // switch */ } else { switch (propagationBehavior) { case TransactionDefinition.PROPAGATION_REQUIRED: case TransactionDefinition.PROPAGATION_REQUIRES_NEW: case TransactionDefinition.PROPAGATION_NESTED: Assert.fail("Wrong usage of this test method; value of propagationBehavior argument should be " + "one among the nexts: PROPAGATION_SUPPORTS, PROPAGATION_NOT_SUPPORTED, " + "and PROPAGATION_NEVER"); /* The below codes are for the time to extend this test method to handle (active) GlobalTransaction is available. // protected final SuspendedResourcesHolder suspend(Object transaction) // suspend method should return null due to the following logic flow: // - TransactionSynchronizationManager.isSynchronizationActive() should always be false // due to Slim3PlatformTransactionManager does not support transaction synchronization currently. // - transaction argument to suspend method should be null due to // value of existingTransactionFlag argument to this verifyNotGetNewTransactionProcess method. // public final int getTransactionSynchronization() ArgumentCaptor<TransactionDefinition> transactionDefinitionArgumentCaptor = ArgumentCaptor.forClass( TransactionDefinition.class); ArgumentCaptor<Boolean> booleanArgumentCaptor = ArgumentCaptor.forClass( Boolean.class); mockedSlim3TxMangerInOrder.verify( slim3PlatformTransactionManager, Mockito.times( 1)) .newTransactionStatus( transactionDefinitionArgumentCaptor.capture(), // TransactionDefinition definition Mockito.eq( null), // Object transaction Mockito.eq( true), Mockito.eq( false), // boolean newTransaction, boolean newSynchronization Mockito.eq( debugEnabled), Mockito.eq( null) //boolean debug, Object suspendedResources ); TransactionDefinition transactionDefinition = transactionDefinitionArgumentCaptor.getValue(); Assert.assertEquals( isolationLevel, transactionDefinition.getIsolationLevel()); Assert.assertEquals( propagationBehavior, transactionDefinition.getPropagationBehavior()); Assert.assertEquals( timeOutSec, transactionDefinition.getTimeout()); // protected void doBegin( Object transaction, TransactionDefinition definition) // protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) */ break; default: // Case of creating "empty" transaction: no actual transaction, but potentially synchronization. // public final int getTransactionSynchronization() // protected final DefaultTransactionStatus prepareTransactionStatus( TransactionDefinition definition, Object transaction, boolean newTransaction, boolean newSynchronization, boolean debug, Object suspendedResources) ArgumentCaptor<TransactionDefinition> transactionDefinitionArgumentCaptor = ArgumentCaptor .forClass(TransactionDefinition.class); final boolean newSynchronization = true; // value true is from result of comparison operation of // getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS mockedSlim3TxMangerInOrder.verify(slim3PlatformTransactionManager, Mockito.times(1)) .newTransactionStatus(transactionDefinitionArgumentCaptor.capture(), Mockito.eq(null), Mockito.eq(true), Mockito.eq(newSynchronization), Mockito.eq(debugEnabled), Mockito.eq(null)); TransactionDefinition transactionDefinition = transactionDefinitionArgumentCaptor.getValue(); Assert.assertEquals(isolationLevel, transactionDefinition.getIsolationLevel()); Assert.assertEquals(propagationBehavior, transactionDefinition.getPropagationBehavior()); Assert.assertEquals(timeOutSec, transactionDefinition.getTimeout()); mockedSlim3TxMangerInOrder.verify(slim3PlatformTransactionManager, Mockito.times(1)) .validateIsolationLevel(Mockito.eq(isolationLevel)); mockedSlim3TxMangerInOrder.verify(slim3PlatformTransactionManager, Mockito.times(1)) .getGlobalTransactionStates(null); // protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) break; } // switch } }
From source file:org.springframework.transaction.reactive.AbstractReactiveTransactionManager.java
/** * This implementation handles propagation behavior. Delegates to * {@code doGetTransaction}, {@code isExistingTransaction} * and {@code doBegin}.// w w w.ja va 2s .c o m * @see #doGetTransaction * @see #isExistingTransaction * @see #doBegin */ @Override public final Mono<ReactiveTransaction> getReactiveTransaction(@Nullable TransactionDefinition definition) throws TransactionException { // Use defaults if no transaction definition given. TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults()); return TransactionSynchronizationManager.currentTransaction().flatMap(synchronizationManager -> { Object transaction = doGetTransaction(synchronizationManager); // Cache debug flag to avoid repeated checks. boolean debugEnabled = logger.isDebugEnabled(); if (isExistingTransaction(transaction)) { // Existing transaction found -> check propagation behavior to find out how to behave. return handleExistingTransaction(synchronizationManager, def, transaction, debugEnabled); } // Check definition settings for new transaction. if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { return Mono.error(new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout())); } // No existing transaction found -> check propagation behavior to find out how to proceed. if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { return Mono.error(new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'")); } else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { return TransactionContextManager.currentContext().map(TransactionSynchronizationManager::new) .flatMap(nestedSynchronizationManager -> suspend(nestedSynchronizationManager, null) .map(Optional::of).defaultIfEmpty(Optional.empty()).flatMap(suspendedResources -> { if (debugEnabled) { logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def); } return Mono.defer(() -> { GenericReactiveTransaction status = newReactiveTransaction( nestedSynchronizationManager, def, transaction, true, debugEnabled, suspendedResources.orElse(null)); return doBegin(nestedSynchronizationManager, transaction, def) .doOnSuccess(ignore -> prepareSynchronization( nestedSynchronizationManager, status, def)) .thenReturn(status); }).onErrorResume(ErrorPredicates.RUNTIME_OR_ERROR, ex -> resume(nestedSynchronizationManager, null, suspendedResources.orElse(null)).then(Mono.error(ex))); })); } else { // Create "empty" transaction: no actual transaction, but potentially synchronization. if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) { logger.warn("Custom isolation level specified but no actual transaction initiated; " + "isolation level will effectively be ignored: " + def); } return Mono.just( prepareReactiveTransaction(synchronizationManager, def, null, true, debugEnabled, null)); } }); }
From source file:org.springframework.transaction.reactive.AbstractReactiveTransactionManager.java
/** * Create a ReactiveTransaction for an existing transaction. *//*from w w w.j a v a 2 s.com*/ private Mono<ReactiveTransaction> handleExistingTransaction( TransactionSynchronizationManager synchronizationManager, TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException { if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) { return Mono.error(new IllegalTransactionStateException( "Existing transaction found for transaction marked with propagation 'never'")); } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) { if (debugEnabled) { logger.debug("Suspending current transaction"); } Mono<SuspendedResourcesHolder> suspend = suspend(synchronizationManager, transaction); return suspend .map(suspendedResources -> prepareReactiveTransaction(synchronizationManager, definition, null, false, debugEnabled, suspendedResources)) // .switchIfEmpty(Mono.fromSupplier(() -> prepareReactiveTransaction(synchronizationManager, definition, null, false, debugEnabled, null))) .cast(ReactiveTransaction.class); } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) { if (debugEnabled) { logger.debug("Suspending current transaction, creating new transaction with name [" + definition.getName() + "]"); } Mono<SuspendedResourcesHolder> suspendedResources = suspend(synchronizationManager, transaction); return suspendedResources.flatMap(suspendedResourcesHolder -> { GenericReactiveTransaction status = newReactiveTransaction(synchronizationManager, definition, transaction, true, debugEnabled, suspendedResourcesHolder); return doBegin(synchronizationManager, transaction, definition) .doOnSuccess(ignore -> prepareSynchronization(synchronizationManager, status, definition)) .thenReturn(status).onErrorResume(ErrorPredicates.RUNTIME_OR_ERROR, beginEx -> resumeAfterBeginException(synchronizationManager, transaction, suspendedResourcesHolder, beginEx).then(Mono.error(beginEx))); }); } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { if (debugEnabled) { logger.debug("Creating nested transaction with name [" + definition.getName() + "]"); } // Nested transaction through nested begin and commit/rollback calls. GenericReactiveTransaction status = newReactiveTransaction(synchronizationManager, definition, transaction, true, debugEnabled, null); return doBegin(synchronizationManager, transaction, definition) .doOnSuccess(ignore -> prepareSynchronization(synchronizationManager, status, definition)) .thenReturn(status); } // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED. if (debugEnabled) { logger.debug("Participating in existing transaction"); } return Mono.just(prepareReactiveTransaction(synchronizationManager, definition, transaction, false, debugEnabled, null)); }
From source file:org.springframework.transaction.support.AbstractPlatformTransactionManager.java
/** * This implementation handles propagation behavior. Delegates to * {@code doGetTransaction}, {@code isExistingTransaction} * and {@code doBegin}./*from w ww .j ava 2 s .co m*/ * @see #doGetTransaction * @see #isExistingTransaction * @see #doBegin */ @Override public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException { Object transaction = doGetTransaction(); // Cache debug flag to avoid repeated checks. boolean debugEnabled = logger.isDebugEnabled(); if (definition == null) { // Use defaults if no transaction definition given. definition = new DefaultTransactionDefinition(); } if (isExistingTransaction(transaction)) { // Existing transaction found -> check propagation behavior to find out how to behave. return handleExistingTransaction(definition, transaction, debugEnabled); } // Check definition settings for new transaction. if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); } // No existing transaction found -> check propagation behavior to find out how to proceed. if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { SuspendedResourcesHolder suspendedResources = suspend(null); if (debugEnabled) { logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition); } try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } catch (RuntimeException | Error ex) { resume(null, suspendedResources); throw ex; } } else { // Create "empty" transaction: no actual transaction, but potentially synchronization. if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) { logger.warn("Custom isolation level specified but no actual transaction initiated; " + "isolation level will effectively be ignored: " + definition); } boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); } }
From source file:org.springframework.transaction.support.AbstractPlatformTransactionManager.java
/** * Create a TransactionStatus for an existing transaction. *//* w w w . java 2 s.com*/ private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException { if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) { throw new IllegalTransactionStateException( "Existing transaction found for transaction marked with propagation 'never'"); } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) { if (debugEnabled) { logger.debug("Suspending current transaction"); } Object suspendedResources = suspend(transaction); boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus(definition, null, false, newSynchronization, debugEnabled, suspendedResources); } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) { if (debugEnabled) { logger.debug("Suspending current transaction, creating new transaction with name [" + definition.getName() + "]"); } SuspendedResourcesHolder suspendedResources = suspend(transaction); try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } catch (RuntimeException | Error beginEx) { resumeAfterBeginException(transaction, suspendedResources, beginEx); throw beginEx; } } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { if (!isNestedTransactionAllowed()) { throw new NestedTransactionNotSupportedException( "Transaction manager does not allow nested transactions by default - " + "specify 'nestedTransactionAllowed' property with value 'true'"); } if (debugEnabled) { logger.debug("Creating nested transaction with name [" + definition.getName() + "]"); } if (useSavepointForNestedTransaction()) { // Create savepoint within existing Spring-managed transaction, // through the SavepointManager API implemented by TransactionStatus. // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization. DefaultTransactionStatus status = prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null); status.createAndHoldSavepoint(); return status; } else { // Nested transaction through nested begin and commit/rollback calls. // Usually only for JTA: Spring synchronization might get activated here // in case of a pre-existing JTA transaction. boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } } // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED. if (debugEnabled) { logger.debug("Participating in existing transaction"); } if (isValidateExistingTransaction()) { if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { Integer currentIsolationLevel = TransactionSynchronizationManager .getCurrentTransactionIsolationLevel(); if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) { Constants isoConstants = DefaultTransactionDefinition.constants; throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] specifies isolation level which is incompatible with existing transaction: " + (currentIsolationLevel != null ? isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) : "(unknown)")); } } if (!definition.isReadOnly()) { if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] is not marked as read-only but existing transaction is"); } } } boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); }