Example usage for org.springframework.transaction TransactionDefinition PROPAGATION_NESTED

List of usage examples for org.springframework.transaction TransactionDefinition PROPAGATION_NESTED

Introduction

In this page you can find the example usage for org.springframework.transaction TransactionDefinition PROPAGATION_NESTED.

Prototype

int PROPAGATION_NESTED

To view the source code for org.springframework.transaction TransactionDefinition PROPAGATION_NESTED.

Click Source Link

Document

Execute within a nested transaction if a current transaction exists, behave like #PROPAGATION_REQUIRED otherwise.

Usage

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);
}