protected override void DoBegin(object transaction, ITransactionDefinition definition) { if (this.sqlMapper == null) { throw new ArgumentException("SqlMapper is required to be set on IbatisPlatformTransactionManager"); } this.sqlMapper.BeginTransaction(); ; }
/// <summary> /// Determines the timeout to use for the given definition. Will fall back to this manager's default /// timeout if the transaction definition doesn't specify a non-default value. /// </summary> /// <param name="definition">The transaction definition.</param> /// <returns>the actual timeout to use.</returns> protected int DetermineTimeout(ITransactionDefinition definition) { if (definition.TransactionTimeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { return definition.TransactionTimeout; } return _defaultTimeout; }
private ITransactionStatus HandleExistingTransaction(ITransactionDefinition definition, object transaction, bool debugEnabled) { //bool newSynchronization; if (definition.PropagationBehavior == TransactionPropagation.Never) { throw new IllegalTransactionStateException( "Transaction propagation 'never' but existing transaction found."); } if (definition.PropagationBehavior == TransactionPropagation.NotSupported) { if (debugEnabled) { log.Debug("Suspending current transaction"); } object suspendedResources = Suspend(transaction); bool newSynchronization = (_transactionSyncState == TransactionSynchronizationState.Always); return PrepareTransactionStatus(definition, null, false, newSynchronization, debugEnabled, suspendedResources); } if (definition.PropagationBehavior == TransactionPropagation.RequiresNew) { if (debugEnabled) { log.Debug("Suspending current transaction, creating new transaction with name [" + definition.Name + "]:" + definition); } object suspendedResources = Suspend(transaction); try { bool newSynchronization = (_transactionSyncState != TransactionSynchronizationState.Never); DefaultTransactionStatus status = NewTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); PrepareSynchronization(status, definition); DoBegin(transaction, definition); return status; } catch (TransactionException beginEx) { try { Resume(transaction, suspendedResources); //TODO: java code rethrows the ex here...should we do so as well? //throw; } catch (TransactionException resumeEx) { log.Error( "Inner transaction begin exception overridden by outer transaction resume exception"); log.Error("Begin Transaction Exception", beginEx); log.Error("Resume Transaction Exception", resumeEx); throw; } throw; } } if (definition.PropagationBehavior == TransactionPropagation.Nested) { if (!NestedTransactionsAllowed) { throw new NestedTransactionNotSupportedException( "Transaction manager does not allow nested transactions by default - " + "specify 'NestedTransactionsAllowed' property with value 'true'"); } if (debugEnabled) { log.Debug("Creating nested transaction with name [" + definition.Name + "]:" + definition); } if (UseSavepointForNestedTransaction()) { DefaultTransactionStatus status = PrepareTransactionStatus(definition, transaction, false, false, debugEnabled, null); status.CreateAndHoldSavepoint(DateTime.Now.ToLongTimeString()); return status; } else { bool newSynchronization = (_transactionSyncState != TransactionSynchronizationState.Never); DefaultTransactionStatus status = NewTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null); PrepareSynchronization(status, definition); DoBegin(transaction, definition); return status; } } // Assumably PROPAGATION_SUPPORTS. if (debugEnabled) { log.Debug("Participating in existing transaction"); } //TODO: this block related to un-ported java feature permitting setting the ValidateExistingTransaction flag // default is FALSE anyway so skipping this validation block should have no effect on code excecution path /*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.ReadOnly) { if (TransactionSynchronizationManager.CurrentTransactionReadOnly) { throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] is not marked as read-only but existing transaction is"); } } bool newSynch = (_transactionSyncState != TransactionSynchronizationState.Never); return PrepareTransactionStatus(definition, transaction, false, newSynch, debugEnabled, null); }
protected DefaultTransactionStatus PrepareTransactionStatus( ITransactionDefinition definition, Object transaction, bool newTransaction, bool newSynchronization, bool debug, Object suspendedResources) { DefaultTransactionStatus status = NewTransactionStatus( definition, transaction, newTransaction, newSynchronization, debug, suspendedResources); PrepareSynchronization(status, definition); return status; }
/// <summary> /// Begin a new transaction with the given transaction definition. /// </summary> /// <remarks> /// Does not have to care about applying the propagation behavior, /// as this has already been handled by this abstract manager. /// </remarks> /// <param name="transaction"> /// Transaction object returned by /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>. /// </param> /// <param name="definition"> /// <see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing /// propagation behavior, isolation level, timeout etc. /// </param> /// <exception cref="Spring.Transaction.TransactionException"> /// In the case of creation or system errors. /// </exception> protected abstract void DoBegin(object transaction, ITransactionDefinition definition);
/** * Create a rae TransactionStatus instance for the given arguments. */ /// <summary>The new transaction status.</summary> /// <param name="definition">The definition.</param> /// <param name="transaction">The transaction.</param> /// <param name="newTransaction">The new transaction.</param> /// <param name="newSynchronization">The new synchronization.</param> /// <param name="debug">The debug.</param> /// <param name="suspendedResources">The suspended resources.</param> /// <returns>The Spring.Transaction.Support.DefaultTransactionStatus.</returns> protected DefaultTransactionStatus NewTransactionStatus(ITransactionDefinition definition, object transaction, bool newTransaction, bool newSynchronization, bool debug, object suspendedResources) { var actualNewSynchronization = newSynchronization && !TransactionSynchronizationManager.SynchronizationActive; return new DefaultTransactionStatus(transaction, newTransaction, actualNewSynchronization, definition.ReadOnly, debug, suspendedResources); }
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(); } }
/// <summary> /// Begin a new transaction with the given transaction definition. /// </summary> /// <param name="transaction">Transaction object returned by /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param> /// <param name="definition"><see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing /// propagation behavior, isolation level, timeout etc.</param> /// <exception cref="Spring.Transaction.TransactionException"> /// In the case of creation or system errors. /// </exception> protected override void DoBegin(object transaction, ITransactionDefinition definition) { MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) transaction; MessageQueueTransaction mqt = new MessageQueueTransaction(); mqt.Begin(); txObject.ResourceHolder = new MessageQueueResourceHolder(mqt); txObject.ResourceHolder.SynchronizedWithTransaction = true; int timeout = DetermineTimeout(definition); if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { txObject.ResourceHolder.TimeoutInSeconds = timeout; } TransactionSynchronizationManager.BindResource(CURRENT_TRANSACTION_SLOTNAME, txObject.ResourceHolder); }
private void DoServiceDomainBegin(ServiceDomainTransactionObject serviceDomainTxObject, ITransactionDefinition definition) { SimpleServiceConfig serviceConfig = CreateServiceConfig(definition); //The context is created when we call Enter. serviceDomainTxObject.ServiceDomainAdapter.Enter(serviceConfig); if (log.IsDebugEnabled) { log.Debug("Context created. TransactionId = " + ContextUtil.TransactionId + ", ActivityId = " + ContextUtil.ActivityId); } }
protected override void DoBegin(object transaction, ITransactionDefinition definition) { }
/// <summary>The do begin.</summary> /// <param name="transaction">The transaction.</param> /// <param name="definition">The definition.</param> protected override void DoBegin(object transaction, ITransactionDefinition definition) { ((ResourcelessTransaction)transaction).Begin(); }
public TransactionTemplate(IPlatformTransactionManager transactionManager, ITransactionDefinition transactionDefinition, ILogger logger = null) : base(transactionDefinition) { _logger = logger; TransactionManager = transactionManager; }
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 [" + 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 [" + 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 abstract void DoBegin(object transaction, ITransactionDefinition definition);
/// <summary> /// Prevents the transaction. /// </summary> protected virtual void PreventTransaction() { this.transactionDefinition = null; }
/// <summary> /// Begin a new transaction with the given transaction definition. /// </summary> /// <param name="transaction"> /// Transaction object returned by /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>. /// </param> /// <param name="definition"> /// <see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing /// propagation behavior, isolation level, timeout etc. /// </param> /// <remarks> /// Does not have to care about applying the propagation behavior, /// as this has already been handled by this abstract manager. /// </remarks> /// <exception cref="Spring.Transaction.TransactionException"> /// In the case of creation or system errors. /// </exception> protected override void DoBegin(object transaction, ITransactionDefinition definition) { HibernateTransactionObject txObject = (HibernateTransactionObject)transaction; if (DbProvider != null && TransactionSynchronizationManager.HasResource(DbProvider) && !txObject.ConnectionHolder.SynchronizedWithTransaction) { throw new IllegalTransactionStateException( "Pre-bound ADO.NET Connection found - HibernateTransactionManager does not support " + "running within AdoTransactionManager if told to manage the DbProvider itself. " + "It is recommended to use a single HibernateTransactionManager for all transactions " + "on a single DbProvider, no matter whether Hibernate or ADO.NET access."); } ISession session = null; try { if (txObject.SessionHolder == null || txObject.SessionHolder.SynchronizedWithTransaction) //if (txObject.SessionHolder == null || (txObject.SessionHolder.SynchronizedWithTransaction && TransactionSynchronizationManager.SynchronizationActive)) //if (txObject.SessionHolder == null || (txObject.SessionHolder.SynchronizedWithTransaction && TransactionSynchronizationManager.ActualTransactionActive)) { IInterceptor interceptor = EntityInterceptor; ISession newSession = (interceptor != null ? SessionFactory.OpenSession(interceptor) : SessionFactory.OpenSession()); if (log.IsDebugEnabled) { log.Debug("Opened new Session [" + newSession + "] for Hibernate transaction"); } txObject.SetSessionHolder(new SessionHolder(newSession), true); } txObject.SessionHolder.SynchronizedWithTransaction = true; session = txObject.SessionHolder.Session; IDbConnection con = session.Connection; //TODO isolation level mgmt //IsolationLevel previousIsolationLevel = if (definition.ReadOnly && txObject.NewSessionHolder) { // Just set to NEVER in case of a new Session for this transaction. session.FlushMode = FlushMode.Never; } if (!definition.ReadOnly && !txObject.NewSessionHolder) { // We need AUTO or COMMIT for a non-read-only transaction. FlushMode flushMode = session.FlushMode; if (FlushMode.Never == flushMode) { session.FlushMode = FlushMode.Auto; txObject.SessionHolder.PreviousFlushMode = flushMode; } } // Add the Hibernate transaction to the session holder. // for now pass in tx options isolation level. ITransaction hibernateTx = session.BeginTransaction(definition.TransactionIsolationLevel); IDbTransaction adoTx = GetIDbTransaction(hibernateTx); // Add the Hibernate transaction to the session holder. txObject.SessionHolder.Transaction = hibernateTx; // Register transaction timeout. int timeout = DetermineTimeout(definition); if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { txObject.SessionHolder.TimeoutInSeconds = timeout; } // Register the Hibernate Session's ADO.NET Connection/TX pair for the DbProvider, if set. if (DbProvider != null) { //investigate passing null for tx. ConnectionHolder conHolder = new ConnectionHolder(con, adoTx); if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { conHolder.TimeoutInMillis = definition.TransactionTimeout; } if (log.IsDebugEnabled) { log.Debug("Exposing Hibernate transaction as ADO transaction [" + con + "]"); } TransactionSynchronizationManager.BindResource(DbProvider, conHolder); txObject.ConnectionHolder = conHolder; } // Bind the session holder to the thread. if (txObject.NewSessionHolder) { TransactionSynchronizationManager.BindResource(SessionFactory, txObject.SessionHolder); } } catch (Exception ex) { SessionFactoryUtils.CloseSession(session); throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex); } }
/// <summary> /// Begin a new transaction with the given transaction definition. /// </summary> /// <param name="transaction"> /// Transaction object returned by /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>. /// </param> /// <param name="definition"> /// <see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing /// propagation behavior, isolation level, timeout etc. /// </param> /// <remarks> /// Does not have to care about applying the propagation behavior, /// as this has already been handled by this abstract manager. /// </remarks> /// <exception cref="Spring.Transaction.TransactionException"> /// In the case of creation or system errors. /// </exception> protected override void DoBegin(object transaction, ITransactionDefinition definition) { HibernateTransactionObject txObject = (HibernateTransactionObject)transaction; if (DbProvider != null && TransactionSynchronizationManager.HasResource(DbProvider) && !txObject.ConnectionHolder.SynchronizedWithTransaction) { throw new IllegalTransactionStateException( "Pre-bound ADO.NET Connection found - HibernateTransactionManager does not support " + "running within AdoTransactionManager if told to manage the DbProvider itself. " + "It is recommended to use a single HibernateTransactionManager for all transactions " + "on a single DbProvider, no matter whether Hibernate or ADO.NET access."); } ISession session = null; try { if (txObject.SessionHolder == null || txObject.SessionHolder.SynchronizedWithTransaction) //if (txObject.SessionHolder == null || (txObject.SessionHolder.SynchronizedWithTransaction && TransactionSynchronizationManager.SynchronizationActive)) //if (txObject.SessionHolder == null || (txObject.SessionHolder.SynchronizedWithTransaction && TransactionSynchronizationManager.ActualTransactionActive)) { IInterceptor interceptor = EntityInterceptor; ISession newSession = (interceptor != null ? SessionFactory.OpenSession(interceptor) : SessionFactory.OpenSession()); if (log.IsDebugEnabled) { log.Debug("Opened new Session [" + newSession + "] for Hibernate transaction"); } txObject.SetSessionHolder(new SessionHolder(newSession), true); } txObject.SessionHolder.SynchronizedWithTransaction = true; session = txObject.SessionHolder.Session; IDbConnection con = session.Connection; //TODO isolation level mgmt //IsolationLevel previousIsolationLevel = if (definition.ReadOnly && txObject.NewSessionHolder) { // Just set to NEVER in case of a new Session for this transaction. session.FlushMode = FlushMode.Never; } if (!definition.ReadOnly && !txObject.NewSessionHolder) { // We need AUTO or COMMIT for a non-read-only transaction. FlushMode flushMode = session.FlushMode; if (FlushMode.Never == flushMode) { session.FlushMode = FlushMode.Auto; txObject.SessionHolder.PreviousFlushMode = flushMode; } } // Add the Hibernate transaction to the session holder. // for now pass in tx options isolation level. ITransaction hibernateTx = session.BeginTransaction(definition.TransactionIsolationLevel); IDbTransaction adoTx = GetIDbTransaction(hibernateTx); // Add the Hibernate transaction to the session holder. txObject.SessionHolder.Transaction = hibernateTx; // Register transaction timeout. int timeout = DetermineTimeout(definition); if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { txObject.SessionHolder.TimeoutInSeconds = timeout; } // Register the Hibernate Session's ADO.NET Connection/TX pair for the DbProvider, if set. if (DbProvider != null) { //investigate passing null for tx. ConnectionHolder conHolder = new ConnectionHolder(con, adoTx); if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { conHolder.TimeoutInSeconds = timeout; } if (log.IsDebugEnabled) { log.Debug("Exposing Hibernate transaction as ADO transaction [" + con + "]"); } TransactionSynchronizationManager.BindResource(DbProvider, conHolder); txObject.ConnectionHolder = conHolder; } // Bind the session holder to the thread. if (txObject.NewSessionHolder) { TransactionSynchronizationManager.BindResource(SessionFactory, txObject.SessionHolder); } } catch (Exception ex) { SessionFactoryUtils.CloseSession(session); throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex); } }
private static TransactionOptions CreateTransactionOptions(ITransactionDefinition definition) { TransactionOptions txOptions = new TransactionOptions(); switch (definition.TransactionIsolationLevel ) { case System.Data.IsolationLevel.Chaos: txOptions.IsolationLevel = IsolationLevel.Chaos; break; case System.Data.IsolationLevel.ReadCommitted: txOptions.IsolationLevel = IsolationLevel.ReadCommitted; break; case System.Data.IsolationLevel.ReadUncommitted: txOptions.IsolationLevel = IsolationLevel.ReadUncommitted; break; case System.Data.IsolationLevel.RepeatableRead: txOptions.IsolationLevel = IsolationLevel.RepeatableRead; break; case System.Data.IsolationLevel.Serializable: txOptions.IsolationLevel = IsolationLevel.Serializable; break; case System.Data.IsolationLevel.Snapshot: txOptions.IsolationLevel = IsolationLevel.Snapshot; break; case System.Data.IsolationLevel.Unspecified: txOptions.IsolationLevel = IsolationLevel.Unspecified; break; } if (definition.TransactionTimeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { txOptions.Timeout = new TimeSpan(0, 0, definition.TransactionTimeout); } return txOptions; }
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)); }
/// <summary>Create a TransactionStatus for an existing transaction.</summary> /// <param name="definition">The transaction definition.</param> /// <param name="transaction">The transaction.</param> /// <param name="debugEnabled">Flag indicating debug is enabled.</param> /// <returns>The transaction status.</returns> private ITransactionStatus HandleExistingTransaction(ITransactionDefinition definition, object transaction, bool debugEnabled) { if (definition.PropagationBehavior == TransactionPropagation.Never) { throw new IllegalTransactionStateException( "Existing transaction found for transaction marked with propagation 'never'"); } if (definition.PropagationBehavior == TransactionPropagation.NotSupported) { if (debugEnabled) { Logger.Debug("Suspending current transaction"); } var suspendedResources = this.Suspend(transaction); var newSynchronization1 = this.transactionSynchronization == TransactionSynchronizationState.Always; return this.PrepareTransactionStatus(definition, null, false, newSynchronization1, debugEnabled, suspendedResources); } if (definition.PropagationBehavior == TransactionPropagation.RequiresNew) { if (debugEnabled) { Logger.Debug( "Suspending current transaction, creating new transaction with name [" + definition.Name + "]"); } var suspendedResources = this.Suspend(transaction); try { var newSynchronization2 = this.transactionSynchronization != TransactionSynchronizationState.Never; var status = this.NewTransactionStatus(definition, transaction, true, newSynchronization2, debugEnabled, suspendedResources); this.DoBegin(transaction, definition); this.PrepareSynchronization(status, definition); return status; } catch (Exception beginEx) { this.ResumeAfterBeginException(transaction, suspendedResources, beginEx); throw; } } if (definition.PropagationBehavior == TransactionPropagation.Nested) { if (!this.nestedTransactionAllowed) { 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.Name + "]"); } if (this.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 = this.PrepareTransactionStatus(definition, transaction, false, false, debugEnabled, null); status.CreateAndHoldSavepoint(Guid.NewGuid().ToString()); // TODO: Java equivalent does not require name 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 newSynchronization3 = this.transactionSynchronization != TransactionSynchronizationState.Never; var status = this.NewTransactionStatus( definition, transaction, true, newSynchronization3, debugEnabled, null); this.DoBegin(transaction, definition); this.PrepareSynchronization(status, definition); return status; } } // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED. if (debugEnabled) { Logger.Debug("Participating in existing transaction"); } if (this.validateExistingTransaction) { if (definition.TransactionIsolationLevel != IsolationLevel.Unspecified) { var currentIsolationLevel = TransactionSynchronizationManager.CurrentTransactionIsolationLevel; if (currentIsolationLevel == null || currentIsolationLevel != definition.TransactionIsolationLevel) { // 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.ReadOnly) { if (TransactionSynchronizationManager.CurrentTransactionReadOnly) { throw new IllegalTransactionStateException( "Participating transaction with definition [" + definition + "] is not marked as read-only but existing transaction is"); } } } var newSynchronization = this.transactionSynchronization != TransactionSynchronizationState.Never; return this.PrepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); }
protected override void DoBegin(object transaction, ITransactionDefinition definition) { try { ServiceDomainTransactionObject txObject = (ServiceDomainTransactionObject)transaction; DoServiceDomainBegin(txObject, definition); } catch (PlatformNotSupportedException ex) { throw new TransactionSystemException("ServiceDomain failure on begin of transaction. Platform does not support EnterpriseServices 'Services without Components'", ex); } catch (Exception e) { throw new CannotCreateTransactionException("ServiceDomain failure on begin of transaction", e); } }
/** * Determine the actual timeout to use for the given definition. * Will fall back to this manager's default timeout if the * transaction definition doesn't specify a non-default value. * @param definition the transaction definition * @return the actual timeout to use * @see org.springframework.transaction.TransactionDefinition#getTimeout() * @see #setDefaultTimeout */ /// <summary>The determine timeout.</summary> /// <param name="definition">The definition.</param> /// <returns>The System.Int32.</returns> protected int DetermineTimeout(ITransactionDefinition definition) { if (definition.TransactionTimeout != -1) { return definition.TransactionTimeout; } return this.defaultTimeout; }
/// <summary> /// Return a currently active transaction or create a new one. /// </summary> /// <remarks> /// <p> /// This implementation handles propagation behavior. /// </p> /// <p> /// Delegates to /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>, /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.IsExistingTransaction"/>, /// and /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoBegin"/>. /// </p> /// <p> /// Note that parameters like isolation level or timeout will only be applied /// to new transactions, and thus be ignored when participating in active ones. /// Furthermore, they aren't supported by every transaction manager: /// a proper implementation should throw an exception when custom values /// that it doesn't support are specified. /// </p> /// </remarks> /// <param name="definition"> /// <see cref="Spring.Transaction.ITransactionDefinition"/> instance (can be null for /// defaults), describing propagation behavior, isolation level, timeout etc. /// </param> /// <exception cref="Spring.Transaction.TransactionException"> /// In case of lookup, creation, or system errors. /// </exception> /// <returns> /// <see cref="Spring.Transaction.ITransactionStatus"/> representing the new or current transaction. /// </returns> public ITransactionStatus GetTransaction(ITransactionDefinition definition) { object transaction = DoGetTransaction(); bool debugEnabled = log.IsDebugEnabled; if (debugEnabled) { log.Debug("Using transaction object [" + transaction + "]"); } if (definition == null) { 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.TransactionTimeout < DefaultTransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.TransactionTimeout); } // No existing transaction found -> check propagation behavior to find out how to proceed. if (definition.PropagationBehavior == TransactionPropagation.Mandatory) { throw new IllegalTransactionStateException( "Transaction propagation 'mandatory' but no existing transaction found"); } else if (definition.PropagationBehavior == TransactionPropagation.Required || definition.PropagationBehavior == TransactionPropagation.RequiresNew || definition.PropagationBehavior == TransactionPropagation.Nested) { object suspendedResources = Suspend(null); if (debugEnabled) { log.Debug("Creating new transaction with name [" + definition.Name + "]:" + definition); } try { bool newSynchronization = (_transactionSyncState != TransactionSynchronizationState.Never); DefaultTransactionStatus status = NewTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); DoBegin(transaction, definition); PrepareSynchronization(status, definition); return status; } catch (TransactionException) { Resume(null, suspendedResources); throw; } } else { // Create "empty" transaction: no actual transaction, but potentially synchronization. bool newSynchronization = (_transactionSyncState == TransactionSynchronizationState.Always); return PrepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); } }
private SimpleServiceConfig CreateServiceConfig(ITransactionDefinition definition) { SimpleServiceConfig serviceConfig = new SimpleServiceConfig(); //TODO investigate BringYourOwnTransaction and TipUrl properties of ServiceConfig serviceConfig.TransactionDescription = definition.Name; serviceConfig.TrackingEnabled = TrackingEnabled; serviceConfig.TrackingAppName = TrackingAppName; serviceConfig.TrackingComponentName = TrackingComponentName; ApplyPropagationBehavior(serviceConfig, definition); ApplyIsolationLevel(serviceConfig, definition); // infinite==-1 would cause transactions to be aborted immediately! if(definition.TransactionTimeout != Timeout.Infinite) { serviceConfig.TransactionTimeout = definition.TransactionTimeout; } return serviceConfig; }
protected void PrepareSynchronization(DefaultTransactionStatus status, ITransactionDefinition definition) { if (status.NewSynchronization) { TransactionSynchronizationManager.ActualTransactionActive = status.HasTransaction(); TransactionSynchronizationManager.CurrentTransactionIsolationLevel = definition.TransactionIsolationLevel != System.Data.IsolationLevel.Unspecified ? definition.TransactionIsolationLevel : IsolationLevel.Unspecified; TransactionSynchronizationManager.CurrentTransactionReadOnly = definition.ReadOnly; TransactionSynchronizationManager.CurrentTransactionName = definition.Name; TransactionSynchronizationManager.InitSynchronization(); } }
protected void ApplyIsolationLevel(SimpleServiceConfig serviceConfig, ITransactionDefinition definition) { switch (definition.TransactionIsolationLevel) { case System.Data.IsolationLevel.Chaos: if (log.IsInfoEnabled) { log.Info("IsolationLevel Chaos does not have a direct counterpart in EnterpriseServices, using Any"); } serviceConfig.IsolationLevel = TransactionIsolationLevel.Any; break; case System.Data.IsolationLevel.ReadCommitted: serviceConfig.IsolationLevel = TransactionIsolationLevel.ReadCommitted; break; case System.Data.IsolationLevel.ReadUncommitted: serviceConfig.IsolationLevel = TransactionIsolationLevel.ReadUncommitted; break; case System.Data.IsolationLevel.RepeatableRead: serviceConfig.IsolationLevel = TransactionIsolationLevel.RepeatableRead; break; case System.Data.IsolationLevel.Serializable: serviceConfig.IsolationLevel = TransactionIsolationLevel.Serializable; break; case System.Data.IsolationLevel.Snapshot: if (log.IsInfoEnabled) { log.Info("IsolationLevel Snapshot does not have a direct counterpart in EnterpriseServices, using ReadCommitted. Introduced in SqlServer 2005. Consider using System.Transactions for transaction management instead."); } serviceConfig.IsolationLevel = TransactionIsolationLevel.ReadCommitted; //err on the side of consistency break; case System.Data.IsolationLevel.Unspecified: serviceConfig.IsolationLevel = TransactionIsolationLevel.Any; break; } }
private DefaultTransactionStatus NewTransactionStatus(ITransactionDefinition definition, object transaction, bool newTransaction, bool newSynchronization, bool debug, object suspendedResources) { bool actualNewSynchronization = newSynchronization && !TransactionSynchronizationManager.SynchronizationActive; // if (actualNewSynchronization) // { // TransactionSynchronizationManager.ActualTransactionActive = (transaction != null); // TransactionSynchronizationManager.CurrentTransactionIsolationLevel = // definition.TransactionIsolationLevel; // TransactionSynchronizationManager.CurrentTransactionReadOnly = definition.ReadOnly; // TransactionSynchronizationManager.CurrentTransactionName = definition.Name; // TransactionSynchronizationManager.InitSynchronization(); // } return new DefaultTransactionStatus(transaction, newTransaction, actualNewSynchronization, definition.ReadOnly, debug, suspendedResources); }
protected void ApplyPropagationBehavior(SimpleServiceConfig serviceConfig, ITransactionDefinition definition) { if (definition.PropagationBehavior == TransactionPropagation.Required) { serviceConfig.TransactionOption = TransactionOption.Required; } else if (definition.PropagationBehavior == TransactionPropagation.RequiresNew) { serviceConfig.TransactionOption = TransactionOption.RequiresNew; } else if (definition.PropagationBehavior == TransactionPropagation.Supports) { serviceConfig.TransactionOption = TransactionOption.Supported; } else if (definition.PropagationBehavior == TransactionPropagation.NotSupported) { serviceConfig.TransactionOption = TransactionOption.NotSupported; } else if (definition.PropagationBehavior == TransactionPropagation.Never) { //TODO check the validity of this mapping serviceConfig.TransactionOption = TransactionOption.Disabled; } else { //TODO Should we throw an exception instead? log.Warn("The requested transaction propagation option " + definition.PropagationBehavior + " is not supported. " + "Defaulting to Never(Disabled) "); } }
/// <summary>The do begin.</summary> /// <param name="transaction">The transaction.</param> /// <param name="definition">The definition.</param> protected override void DoBegin(object transaction, ITransactionDefinition definition) { }
/// <summary> /// Do begin. /// </summary> /// <param name="transaction"> /// The transaction. /// </param> /// <param name="definition"> /// The definition. /// </param> /// <exception cref="InvalidIsolationLevelException"> /// </exception> /// <exception cref="CannotCreateTransactionException"> /// </exception> protected override void DoBegin(object transaction, ITransactionDefinition definition) { // TODO: Figure out the right isolation level. if (definition.TransactionIsolationLevel != IsolationLevel.Unspecified) { throw new InvalidIsolationLevelException("AMQP does not support an isolation level concept"); } var txObject = (RabbitTransactionObject)transaction; RabbitResourceHolder resourceHolder = null; try { resourceHolder = ConnectionFactoryUtils.GetTransactionalResourceHolder(this.ConnectionFactory, true); if (this.logger.IsDebugEnabled) { this.logger.Debug("Created AMQP transaction on channel [" + resourceHolder.Channel + "]"); } // resourceHolder.DeclareTransactional(); txObject.ResourceHolder = resourceHolder; txObject.ResourceHolder.SynchronizedWithTransaction = true; var timeout = DetermineTimeout(definition); if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { txObject.ResourceHolder.TimeoutInSeconds = timeout; } TransactionSynchronizationManager.BindResource(this.ConnectionFactory, txObject.ResourceHolder); } catch (AmqpException ex) { if (resourceHolder != null) { ConnectionFactoryUtils.ReleaseResources(resourceHolder); } throw new CannotCreateTransactionException("Could not create AMQP transaction", ex); } }
/// <summary> /// Begin a new transaction with the given transaction definition. /// </summary> /// <param name="transaction">Transaction object returned by /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param> /// <param name="definition"><see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing /// propagation behavior, isolation level, timeout etc.</param> /// <remarks> /// Does not have to care about applying the propagation behavior, /// as this has already been handled by this abstract manager. /// </remarks> /// <exception cref="Spring.Transaction.TransactionException"> /// In the case of creation or system errors. /// </exception> protected override void DoBegin(object transaction, ITransactionDefinition definition) { //This is the default value defined in DefaultTransactionDefinition if (definition.TransactionIsolationLevel != IsolationLevel.Unspecified) { throw new InvalidIsolationLevelException("NMS does not support an isoliation level concept"); } MessageTransactionObject txObject = (MessageTransactionObject) transaction; IConnection con = null; ISession session = null; try { con = CreateConnection(); session = CreateSession(con); if (LOG.IsDebugEnabled) { log.Debug("Created NMS transaction on Session [" + session + "] from Connection [" + con + "]"); } txObject.ResourceHolder = new NmsResourceHolder(ConnectionFactory, con, session); txObject.ResourceHolder.SynchronizedWithTransaction = true; int timeout = DetermineTimeout(definition); if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { txObject.ResourceHolder.TimeoutInSeconds = timeout; } TransactionSynchronizationManager.BindResource(ConnectionFactory, txObject.ResourceHolder); } catch (NMSException ex) { if (session != null) { try { session.Close(); } catch (Exception) {} } if (con != null) { try { con.Close(); } catch (Exception){} } throw new CannotCreateTransactionException("Could not create NMS Transaction", ex); } }
private ITransactionStatus HandleExistingTransaction(ITransactionDefinition definition, object transaction, bool debugEnabled) { //bool newSynchronization; if (definition.PropagationBehavior == TransactionPropagation.Never) { throw new IllegalTransactionStateException( "Transaction propagation 'never' but existing transaction found."); } if (definition.PropagationBehavior == TransactionPropagation.NotSupported) { if (debugEnabled) { log.Debug("Suspending current transaction"); } object suspendedResources = Suspend(transaction); bool newSynchronization = (_transactionSyncState == TransactionSynchronizationState.Always); return NewTransactionStatus(definition, null, false, newSynchronization, debugEnabled, suspendedResources); } if (definition.PropagationBehavior == TransactionPropagation.RequiresNew) { if (debugEnabled) { log.Debug("Suspending current transaction, creating new transaction with name [" + definition.Name + "]:" + definition); } object suspendedResources = Suspend(transaction); try { DoBegin(transaction, definition); } catch (TransactionException beginEx) { try { Resume(transaction, suspendedResources); } catch (TransactionException resumeEx) { log.Error( "Inner transaction begin exception overridden by outer transaction resume exception"); log.Error("Begin Transaction Exception", beginEx); log.Error("Resume Transaction Exception", resumeEx); throw; } throw; } bool newSynchronization = (_transactionSyncState != TransactionSynchronizationState.Never); return NewTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); } if (definition.PropagationBehavior == TransactionPropagation.Nested) { if (!NestedTransactionsAllowed) { throw new NestedTransactionNotSupportedException( "Transaction manager does not allow nested transactions by default - " + "specify 'NestedTransactionsAllowed' property with value 'true'"); } if (debugEnabled) { log.Debug("Creating nested transaction with name [" + definition.Name + "]:" + definition); } if (UseSavepointForNestedTransaction()) { DefaultTransactionStatus status = NewTransactionStatus(definition, transaction, false, false, debugEnabled, null); status.CreateAndHoldSavepoint(DateTime.Now.ToLongTimeString()); return status; } else { DoBegin(transaction, definition); bool newSynchronization = (_transactionSyncState != TransactionSynchronizationState.Never); return NewTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null); } } // Assumably PROPAGATION_SUPPORTS. if (debugEnabled) { log.Debug("Participating in existing transaction"); } bool newSynch = (_transactionSyncState != TransactionSynchronizationState.Never); return NewTransactionStatus(definition, transaction, false, newSynch, debugEnabled, null); }
/// <summary>Do begin.</summary> /// <param name="transaction">The transaction.</param> /// <param name="definition">The definition.</param> protected override void DoBegin(object transaction, ITransactionDefinition definition) { // https://jira.springsource.org/browse/SPRNET-1444 (SPRNET 2.0) has default TransactionIsolationLevel as IsolationLevel.Unspecified, letting this work. Will not work for SPRNET <= 1.3.2. if (definition.TransactionIsolationLevel != IsolationLevel.Unspecified) { throw new InvalidIsolationLevelException("AMQP does not support an isolation level concept"); } var transactionObject = (RabbitTransactionObject)transaction; RabbitResourceHolder resourceHolder = null; try { resourceHolder = ConnectionFactoryUtils.GetTransactionalResourceHolder(this.ConnectionFactory, true); Logger.Debug(m => m("Created AMQP transaction on channel [{0}]", resourceHolder.Channel)); // resourceHolder.DeclareTransactional(); transactionObject.ResourceHolder = resourceHolder; transactionObject.ResourceHolder.SynchronizedWithTransaction = true; var timeout = this.DetermineTimeout(definition); if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { transactionObject.ResourceHolder.TimeoutInSeconds = timeout; } TransactionSynchronizationManager.BindResource(this.ConnectionFactory, transactionObject.ResourceHolder); } catch (AmqpException ex) { if (resourceHolder != null) { ConnectionFactoryUtils.ReleaseResources(resourceHolder); } throw new CannotCreateTransactionException("Could not create AMQP transaction", ex); } }
/// <summary> /// Begin a new transaction with the given transaction definition. /// </summary> /// <param name="transaction"> /// Transaction object returned by /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>. /// </param> /// <param name="definition"> /// <see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing /// propagation behavior, isolation level, timeout etc. /// </param> /// <remarks> /// Does not have to care about applying the propagation behavior, /// as this has already been handled by this abstract manager. /// </remarks> /// <exception cref="Spring.Transaction.TransactionException"> /// In the case of creation or system errors. /// </exception> protected override void DoBegin(object transaction, ITransactionDefinition definition) { DbProviderTransactionObject txMgrStateObject = (DbProviderTransactionObject)transaction; IDbConnection con = null; if (dbProvider == null) { throw new ArgumentException("DbProvider is required to be set on AdoPlatformTransactionManager"); } try { if (txMgrStateObject.ConnectionHolder == null || txMgrStateObject.ConnectionHolder.SynchronizedWithTransaction) { IDbConnection newCon = DbProvider.CreateConnection(); if (log.IsDebugEnabled) { log.Debug("Acquired Connection [" + newCon + ", " + newCon.ConnectionString + "] for ADO.NET transaction"); } newCon.Open(); //TODO isolation level mgmt - will need to abstract out SQL used to specify this in DbMetaData //MSDN docs... //With one exception, you can switch from one isolation level to another at any time during a transaction. The exception occurs when changing from any isolation level to SNAPSHOT isolation //IsolationLevel previousIsolationLevel = IDbTransaction newTrans = newCon.BeginTransaction(definition.TransactionIsolationLevel); txMgrStateObject.SetConnectionHolder(new ConnectionHolder(newCon, newTrans), true); } txMgrStateObject.ConnectionHolder.SynchronizedWithTransaction = true; con = txMgrStateObject.ConnectionHolder.Connection; txMgrStateObject.ConnectionHolder.TransactionActive = true; int timeout = DetermineTimeout(definition); if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { txMgrStateObject.ConnectionHolder.TimeoutInSeconds = timeout; } //Bind transactional resources to thread if (txMgrStateObject.NewConnectionHolder) { TransactionSynchronizationManager.BindResource(DbProvider, txMgrStateObject.ConnectionHolder); } } //TODO catch specific exception catch (Exception e) { ConnectionUtils.DisposeConnection(con, DbProvider); throw new CannotCreateTransactionException("Could not create ADO.NET connection for transaction", e); } }
protected override void DoBegin(object transaction, ITransactionDefinition definition) { ++begun; ++inflight; }
private static TransactionScopeOption CreateTransactionScopeOptions(ITransactionDefinition definition) { TransactionScopeOption txScopeOption; if (definition.PropagationBehavior == TransactionPropagation.Required) { txScopeOption = TransactionScopeOption.Required; } else if (definition.PropagationBehavior == TransactionPropagation.RequiresNew) { txScopeOption = TransactionScopeOption.RequiresNew; } else if (definition.PropagationBehavior == TransactionPropagation.NotSupported) { txScopeOption = TransactionScopeOption.Suppress; } else { throw new Spring.Transaction.TransactionSystemException("Transaction Propagation Behavior" + definition.PropagationBehavior + " not supported by TransactionScope. Use Required or RequiredNew"); } return txScopeOption; }
/// <summary>The get transaction.</summary> /// <param name="definition">The definition.</param> /// <returns>The Spring.Transaction.ITransactionStatus.</returns> public ITransactionStatus GetTransaction(ITransactionDefinition definition) { var transaction = this.DoGetTransaction(); // Cache debug flag to avoid repeated checks. var debugEnabled = Logger.IsDebugEnabled; if (definition == null) { // Use defaults if no transaction definition given. definition = new DefaultTransactionDefinition(); } if (this.IsExistingTransaction(transaction)) { // Existing transaction found -> check propagation behavior to find out how to behave. return this.HandleExistingTransaction(definition, transaction, debugEnabled); } // Check definition settings for new transaction. if (definition.TransactionTimeout < -1) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.TransactionTimeout); } // No existing transaction found -> check propagation behavior to find out how to proceed. if (definition.PropagationBehavior == TransactionPropagation.Mandatory) { throw new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'"); } else if (definition.PropagationBehavior == TransactionPropagation.Required || definition.PropagationBehavior == TransactionPropagation.RequiresNew || definition.PropagationBehavior == TransactionPropagation.Nested) { var suspendedResources = this.Suspend(null); if (debugEnabled) { Logger.Debug("Creating new transaction with name [" + definition.Name + "]: " + definition); } try { var newSynchronization = this.transactionSynchronization != TransactionSynchronizationState.Never; var status = this.NewTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); this.DoBegin(transaction, definition); this.PrepareSynchronization(status, definition); return status; } catch (Exception ex) { this.Resume(null, suspendedResources); throw ex; } } else { // Create "empty" transaction: no actual transaction, but potentially synchronization. var newSynchronization = this.transactionSynchronization == TransactionSynchronizationState.Always; return this.PrepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); } }