private void DoResumeSynchronization(List <ITransactionSynchronization> suspendedSynchronizations)
 {
     TransactionSynchronizationManager.InitSynchronization();
     foreach (var synchronization in suspendedSynchronizations)
     {
         synchronization.Resume();
         TransactionSynchronizationManager.RegisterSynchronization(synchronization);
     }
 }
 public static void InvokeAfterCommit(List <ITransactionSynchronization> synchronizations)
 {
     if (synchronizations != null)
     {
         foreach (var synchronization in TransactionSynchronizationManager.GetSynchronizations())
         {
             synchronization.AfterCommit();
         }
     }
 }
 protected virtual void PrepareSynchronization(DefaultTransactionStatus status, ITransactionDefinition definition)
 {
     if (status.IsNewSynchronization)
     {
         TransactionSynchronizationManager.SetActualTransactionActive(status.HasTransaction);
         TransactionSynchronizationManager.SetCurrentTransactionIsolationLevel(definition.IsolationLevel != AbstractTransactionDefinition.ISOLATION_DEFAULT ? definition.IsolationLevel : (int?)null);
         TransactionSynchronizationManager.SetCurrentTransactionReadOnly(definition.IsReadOnly);
         TransactionSynchronizationManager.SetCurrentTransactionName(definition.Name);
         TransactionSynchronizationManager.InitSynchronization();
     }
 }
        private List <ITransactionSynchronization> DoSuspendSynchronization()
        {
            var suspendedSynchronizations = TransactionSynchronizationManager.GetSynchronizations();

            foreach (var synchronization in suspendedSynchronizations)
            {
                synchronization.Suspend();
            }

            TransactionSynchronizationManager.ClearSynchronization();
            return(suspendedSynchronizations);
        }
 public static void TriggerBeforeCompletion(ILogger logger = null)
 {
     foreach (var synchronization in TransactionSynchronizationManager.GetSynchronizations())
     {
         try
         {
             synchronization.BeforeCompletion();
         }
         catch (Exception ex)
         {
             logger?.LogError(ex, "TransactionSynchronization.beforeCompletion threw exception");
         }
     }
 }
 public static void InvokeAfterCompletion(List <ITransactionSynchronization> synchronizations, int completionStatus, ILogger logger = null)
 {
     if (synchronizations != null)
     {
         foreach (var synchronization in TransactionSynchronizationManager.GetSynchronizations())
         {
             try
             {
                 synchronization.AfterCompletion(completionStatus);
             }
             catch (Exception ex)
             {
                 logger.LogError("TransactionSynchronization.afterCompletion threw exception", ex);
             }
         }
     }
 }
        protected virtual SuspendedResourcesHolder Suspend(object transaction)
        {
            if (TransactionSynchronizationManager.IsSynchronizationActive())
            {
                var suspendedSynchronizations = DoSuspendSynchronization();
                try
                {
                    object suspendedResources = null;
                    if (transaction != null)
                    {
                        suspendedResources = DoSuspend(transaction);
                    }

                    var name = TransactionSynchronizationManager.GetCurrentTransactionName();
                    TransactionSynchronizationManager.SetCurrentTransactionName(null);
                    var readOnly = TransactionSynchronizationManager.IsCurrentTransactionReadOnly();
                    TransactionSynchronizationManager.SetCurrentTransactionReadOnly(false);
                    var isolationLevel = TransactionSynchronizationManager.GetCurrentTransactionIsolationLevel();
                    TransactionSynchronizationManager.SetCurrentTransactionIsolationLevel(null);
                    var wasActive = TransactionSynchronizationManager.IsActualTransactionActive();
                    TransactionSynchronizationManager.SetActualTransactionActive(false);
                    return(new SuspendedResourcesHolder(suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive));
                }
                catch (Exception)
                {
                    // doSuspend failed - original transaction is still active...
                    DoResumeSynchronization(suspendedSynchronizations);
                    throw;
                }
            }
            else if (transaction != null)
            {
                // Transaction active but no synchronization active.
                var suspendedResources = DoSuspend(transaction);
                return(new SuspendedResourcesHolder(suspendedResources));
            }
            else
            {
                // Neither transaction nor synchronization active.
                return(null);
            }
        }
        private void CleanupAfterCompletion(DefaultTransactionStatus status)
        {
            status.IsCompleted = true;
            if (status.IsNewSynchronization)
            {
                TransactionSynchronizationManager.Clear();
            }

            if (status.IsNewTransaction)
            {
                DoCleanupAfterCompletion(status.Transaction);
            }

            if (status.SuspendedResources != null)
            {
                _logger?.LogDebug("Resuming suspended transaction after completion of inner transaction");
                var transaction = status.HasTransaction ? status.Transaction : null;
                Resume(transaction, (SuspendedResourcesHolder)status.SuspendedResources);
            }
        }
        protected virtual void Resume(object transaction, SuspendedResourcesHolder resourcesHolder)
        {
            if (resourcesHolder != null)
            {
                var suspendedResources = resourcesHolder.SuspendedResources;
                if (suspendedResources != null)
                {
                    DoResume(transaction, suspendedResources);
                }

                var suspendedSynchronizations = resourcesHolder.SuspendedSynchronizations;
                if (suspendedSynchronizations != null)
                {
                    TransactionSynchronizationManager.SetActualTransactionActive(resourcesHolder.WasActive);
                    TransactionSynchronizationManager.SetCurrentTransactionIsolationLevel(resourcesHolder.IsolationLevel);
                    TransactionSynchronizationManager.SetCurrentTransactionReadOnly(resourcesHolder.ReadOnly);
                    TransactionSynchronizationManager.SetCurrentTransactionName(resourcesHolder.Name);
                    DoResumeSynchronization(suspendedSynchronizations);
                }
            }
        }
        private void TriggerAfterCompletion(DefaultTransactionStatus status, int completionStatus)
        {
            if (status.IsNewSynchronization)
            {
                var synchronizations = TransactionSynchronizationManager.GetSynchronizations();
                TransactionSynchronizationManager.ClearSynchronization();
                if (!status.HasTransaction || status.IsNewTransaction)
                {
                    _logger?.LogTrace("Triggering afterCompletion synchronization");

                    // No transaction or new transaction for the current scope ->
                    // invoke the afterCompletion callbacks immediately
                    InvokeAfterCompletion(synchronizations, completionStatus);
                }
                else if (synchronizations.Count > 0)
                {
                    // Existing transaction that we participate in, controlled outside
                    // of the scope of this Spring transaction manager -> try to register
                    // an afterCompletion callback with the existing (JTA) transaction.
                    RegisterAfterCompletionWithExistingTransaction(status.Transaction, synchronizations);
                }
            }
        }
        public static void TriggerAfterCompletion(int completionStatus)
        {
            var synchronizations = TransactionSynchronizationManager.GetSynchronizations();

            InvokeAfterCompletion(synchronizations, completionStatus);
        }
 public static void TriggerAfterCommit()
 {
     InvokeAfterCommit(TransactionSynchronizationManager.GetSynchronizations());
 }
        private ITransactionStatus HandleExistingTransaction(ITransactionDefinition definition, object transaction)
        {
            if (definition.PropagationBehavior == AbstractTransactionDefinition.PROPAGATION_NEVER)
            {
                throw new IllegalTransactionStateException(
                          "Existing transaction found for transaction marked with propagation 'never'");
            }

            if (definition.PropagationBehavior == AbstractTransactionDefinition.PROPAGATION_NOT_SUPPORTED)
            {
                _logger?.LogDebug("Suspending current transaction");
                var suspendedResources = Suspend(transaction);
                return(PrepareTransactionStatus(definition, null, false, TransactionSynchronization == SYNCHRONIZATION_ALWAYS, suspendedResources));
            }

            if (definition.PropagationBehavior == AbstractTransactionDefinition.PROPAGATION_REQUIRES_NEW)
            {
                _logger?.LogDebug("Suspending current transaction, creating new transaction with name [{name}]", definition.Name);
                var suspendedResources = Suspend(transaction);
                try
                {
                    var status = NewTransactionStatus(definition, transaction, true, TransactionSynchronization != SYNCHRONIZATION_NEVER, suspendedResources);
                    DoBegin(transaction, definition);
                    PrepareSynchronization(status, definition);
                    return(status);
                }
                catch (Exception ex)
                {
                    ResumeAfterBeginException(transaction, suspendedResources, ex);
                    throw;
                }
            }

            if (definition.PropagationBehavior == AbstractTransactionDefinition.PROPAGATION_NESTED)
            {
                if (!NestedTransactionAllowed)
                {
                    throw new NestedTransactionNotSupportedException(
                              "Transaction manager does not allow nested transactions by default - " +
                              "specify 'nestedTransactionAllowed' property with value 'true'");
                }

                _logger?.LogDebug("Creating nested transaction with name [{name}]", definition.Name);
                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.
                    var status = PrepareTransactionStatus(definition, transaction, false, false, 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.
                    var status = NewTransactionStatus(definition, transaction, true, TransactionSynchronization != SYNCHRONIZATION_NEVER, null);
                    DoBegin(transaction, definition);
                    PrepareSynchronization(status, definition);
                    return(status);
                }
            }

            // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
            _logger?.LogDebug("Participating in existing transaction");
            if (ValidateExistingTransaction)
            {
                if (definition.IsolationLevel != AbstractTransactionDefinition.ISOLATION_DEFAULT)
                {
                    var currentIsolationLevel = TransactionSynchronizationManager.GetCurrentTransactionIsolationLevel();
                    if (currentIsolationLevel == null || currentIsolationLevel != definition.IsolationLevel)
                    {
                        throw new IllegalTransactionStateException("Participating transaction with definition [" +
                                                                   definition + "] specifies isolation level which is incompatible with existing transaction: ");
                    }
                }

                if (!definition.IsReadOnly && TransactionSynchronizationManager.IsCurrentTransactionReadOnly())
                {
                    throw new IllegalTransactionStateException("Participating transaction with definition [" +
                                                               definition + "] is not marked as read-only but existing transaction is");
                }
            }

            var newSynchronization = TransactionSynchronization != SYNCHRONIZATION_NEVER;

            return(PrepareTransactionStatus(definition, transaction, false, newSynchronization, null));
        }
        protected virtual DefaultTransactionStatus NewTransactionStatus(ITransactionDefinition definition, object transaction, bool newTransaction, bool newSynchronization, object suspendedResources)
        {
            var actualNewSynchronization = newSynchronization && !TransactionSynchronizationManager.IsSynchronizationActive();

            return(new DefaultTransactionStatus(transaction, newTransaction, actualNewSynchronization, definition.IsReadOnly, suspendedResources, _logger));
        }