From 9c5a7ec3ba41a84d8ba70c3f15526c35d8f69999 Mon Sep 17 00:00:00 2001 From: Steve Bohlen Date: Fri, 27 Mar 2015 11:20:47 -0400 Subject: [PATCH] removing tests, etc. related to CustomSpring132HibernateTxScopeTransactionManager as no longer necessary now that changes are in HibernateTxScopeTransactionManager directly --- ...ng132HibernateTxScopeTransactionManager.cs | 1168 ----------------- ...stomHibernateTxScopeTransactionManager.xml | 11 - ...pring.SessionFactoryImplError.Tests.csproj | 4 - ...ustomHibernateTxScopeTransactionManager.cs | 50 - 4 files changed, 1233 deletions(-) delete mode 100644 test/Spring/Spring.SessionFactoryImplError.Tests/CustomSpring132HibernateTxScopeTransactionManager.cs delete mode 100644 test/Spring/Spring.SessionFactoryImplError.Tests/Spring.CustomHibernateTxScopeTransactionManager.xml delete mode 100644 test/Spring/Spring.SessionFactoryImplError.Tests/TestUsingCustomHibernateTxScopeTransactionManager.cs diff --git a/test/Spring/Spring.SessionFactoryImplError.Tests/CustomSpring132HibernateTxScopeTransactionManager.cs b/test/Spring/Spring.SessionFactoryImplError.Tests/CustomSpring132HibernateTxScopeTransactionManager.cs deleted file mode 100644 index 009f5299..00000000 --- a/test/Spring/Spring.SessionFactoryImplError.Tests/CustomSpring132HibernateTxScopeTransactionManager.cs +++ /dev/null @@ -1,1168 +0,0 @@ -using System; -using System.Data; -using System.Reflection; -using System.Transactions; -using NHibernate; -using NHibernate.Transaction; -using Spring.Core.TypeResolution; -using Spring.Dao; -using Spring.Data.Common; -using Spring.Data.Core; -using Spring.Data.NHibernate; -using Spring.Data.Support; -using Spring.Objects.Factory; -using Spring.Transaction; -using Spring.Transaction.Support; -using HibernateTransactionException = NHibernate.TransactionException; - -namespace Spring.SessionFactoryImplError.Tests -{ - /// - /// A complete copy and selective re-write of the Spring.Data.NHibernate. from the Spring.Data.NHibernate32 DLL - /// to patch bugs with their implementation that could not be rectified by overriding the class (due to so much private scoping). - /// - /// - /// This will be committed to source control in its first version the same way as it appeared in the Spring.NET v1.3.2 (.NET v4.0, VS 2010) source code; therefore, changes - /// from the base version in v1.3.2 will be discernable from source control. Those changes will need to be ported to the version of the - /// in the next upgrade of Spring.NET, and so forth. A new copy of that versions HibernateTxScopeTransactionManager will need to be copied into a CustomSpring132HibernateTxScopeTransactionManager - /// file, that should be committed, then the changes need to be ported. This should continue until Spring's version is bug-free. - /// - public class CustomSpring132HibernateTxScopeTransactionManager : AbstractPlatformTransactionManager, IResourceTransactionManager, IObjectFactoryAware, IInitializingObject - { - #region Fields - - private ISessionFactory sessionFactory; - - private IDbProvider dbProvider; - - private bool autodetectDbProvider = true; - - private Object entityInterceptor; - - private IAdoExceptionTranslator adoExceptionTranslator; - - private IAdoExceptionTranslator defaultExceptionTranslator; - - /// - /// Just needed for entityInterceptorBeanName. - /// - private IObjectFactory objectFactory; - - private TxScopeTransactionManager txScopeTranactionManager; - - private static readonly MethodInfo SessionFactoryUtils_CloseSessionOrRegisterDeferredClose_Method; - - #endregion - - #region Constructor (s) - - /// - /// Static constructor to get a handle to a internal method from a spring assembly that is needed in this assembly. - /// - static CustomSpring132HibernateTxScopeTransactionManager() - { - Type sfuType = typeof (SessionFactoryUtils); - SessionFactoryUtils_CloseSessionOrRegisterDeferredClose_Method = sfuType.GetMethod("CloseSessionOrRegisterDeferredClose", BindingFlags.Static | BindingFlags.NonPublic); - } - - /// - /// Initializes a new instance of the class. - /// - public CustomSpring132HibernateTxScopeTransactionManager() - { - txScopeTranactionManager = new TxScopeTransactionManager(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The session factory. - public CustomSpring132HibernateTxScopeTransactionManager(ISessionFactory sessionFactory) - { - this.sessionFactory = sessionFactory; - AfterPropertiesSet(); - } - - #endregion - - #region Properties - - /// - /// Gets or sets the db provider. - /// - /// The db provider. - public IDbProvider DbProvider - { - get { return dbProvider; } - set { dbProvider = value; } - } - - /// - /// Gets or sets a Hibernate entity interceptor that allows to inspect and change - /// property values before writing to and reading from the database. - /// When getting, return the current Hibernate entity interceptor, or null if none. - /// - /// The entity interceptor. - /// - /// Resolves an entity interceptor object name via the object factory, - /// if necessary. - /// Will get applied to any new Session created by this transaction manager. - /// Such an interceptor can either be set at the SessionFactory level, - /// i.e. on LocalSessionFactoryObject, or at the Session level, i.e. on - /// HibernateTemplate, HibernateInterceptor, and HibernateTransactionManager. - /// It's preferable to set it on LocalSessionFactoryObject or HibernateTransactionManager - /// to avoid repeated configuration and guarantee consistent behavior in transactions. - /// - /// If object factory is null and need to get entity interceptor via object name. - public IInterceptor EntityInterceptor - { - get - { - if (this.entityInterceptor is IInterceptor) - { - return (IInterceptor)entityInterceptor; - } - else if (this.entityInterceptor is string) - { - if (this.objectFactory == null) - { - throw new InvalidOperationException("Cannot get entity interceptor via object name if no object factory set"); - } - String objectName = (String)this.entityInterceptor; - return (IInterceptor)this.objectFactory.GetObject(objectName, typeof(IInterceptor)); - } - else - { - return null; - } - } - set - { - entityInterceptor = value; - } - } - - /// - /// Sets the object name of a Hibernate entity interceptor that - /// allows to inspect and change property values before writing to and reading from the database. - /// - /// The name of the entity interceptor object. - /// - /// Will get applied to any new Session created by this transaction manager. - ///

Requires the object factory to be known, to be able to resolve the object - /// name to an interceptor instance on session creation. Typically used for - /// prototype interceptors, i.e. a new interceptor instance per session. - ///

- ///

Can also be used for shared interceptor instances, but it is recommended - /// to set the interceptor reference directly in such a scenario. - ///

- ///
- public string EntityInterceptorObjectName - { - set - { - entityInterceptor = value; - } - } - - /// - /// Gets or sets the ADO.NET exception translator for this transaction manager. - /// - /// - /// Applied to ADO.NET Exceptions (wrapped by Hibernate's ADOException) - /// - /// The ADO exception translator. - public IAdoExceptionTranslator AdoExceptionTranslator - { - get { return adoExceptionTranslator; } - set { adoExceptionTranslator = value; } - } - - /// - /// Gets the default IAdoException translator, lazily creating it if nece - /// - /// The default IAdoException translator. - public IAdoExceptionTranslator DefaultAdoExceptionTranslator - { - get - { - lock (this) - { - if (defaultExceptionTranslator == null) - { - if (dbProvider != null) - { - defaultExceptionTranslator = new ErrorCodeExceptionTranslator(dbProvider); - } - else - { - defaultExceptionTranslator = SessionFactoryUtils.NewAdoExceptionTranslator(SessionFactory); - } - } - return defaultExceptionTranslator; - } - } - } - - /// - /// Gets or sets the SessionFactory that this instance should manage transactions for. - /// - /// The session factory. - public ISessionFactory SessionFactory - { - get { return sessionFactory; } - set { sessionFactory = value; } - } - - - /// - /// Gets the resource factory that this transaction manager operates on, - /// For the HibenratePlatformTransactionManager this the SessionFactory - /// - /// The SessionFactory. - public object ResourceFactory - { - get { return sessionFactory; } - } - - /// - /// Set whether to autodetect a ADO.NET connection used by the Hibernate SessionFactory, - /// if set via LocalSessionFactoryObject's DbProvider. Default is "true". - /// - /// - /// true if [autodetect data source]; otherwise, false. - /// - /// - ///

Can be turned off to deliberately ignore an available IDbProvider, - /// to not expose Hibernate transactions as ADO.NET transactions for that IDbProvider. - ///

- ///
- public bool AutodetectDbProvider - { - set { autodetectDbProvider = value; } - } - - #endregion - - #region Methods - - #endregion - - - /// - /// The object factory just needs to be known for resolving entity interceptor - /// It does not need to be set for any other mode of operation. - /// - /// - /// Owning - /// (may not be ). The object can immediately - /// call methods on the factory. - /// - public IObjectFactory ObjectFactory - { - set - { - objectFactory = value; - } - } - - /// - /// Return the current transaction object. - /// - /// The current transaction object. - /// - /// If transaction support is not available. - /// - /// - /// In the case of lookup or system errors. - /// - protected override object DoGetTransaction() - { - if (log.IsDebugEnabled) - { - if (System.Transactions.Transaction.Current == null) - { - log.Debug("DoGetTransaction: No transaction currently exists"); - } - else - { - log.Debug(string.Format("DoGetTransaction: Getting transaction object for existing System.Transactions.Transaction{0}", WriteTransactionInformation(System.Transactions.Transaction.Current))); - } - } - - HibernateTransactionObject txObject = new HibernateTransactionObject(); - txObject.SavepointAllowed = NestedTransactionsAllowed; - - if (TransactionSynchronizationManager.HasResource(SessionFactory)) - { - SessionHolder sessionHolder = - (SessionHolder)TransactionSynchronizationManager.GetResource(SessionFactory); - if (log.IsDebugEnabled) - { - log.Debug("Found thread-bound Session [" + sessionHolder.Session + - "] for Hibernate transaction"); - } - txObject.SetSessionHolder(sessionHolder, false); - if (DbProvider != null) - { - ConnectionHolder conHolder = (ConnectionHolder) - TransactionSynchronizationManager.GetResource(DbProvider); - txObject.ConnectionHolder = conHolder; - } - } - txObject.PromotableTxScopeTransactionObject = new TxScopeTransactionManager.PromotableTxScopeTransactionObject(); - - return txObject; - } - - /// - /// Check if the given transaction object indicates an existing, - /// i.e. already begun, transaction. - /// - /// - /// Transaction object returned by - /// . - /// - /// True if there is an existing transaction. - /// - /// In the case of system errors. - /// - protected override bool IsExistingTransaction(object transaction) - { - return - ((HibernateTransactionObject)transaction).PromotableTxScopeTransactionObject.TxScopeAdapter. - IsExistingTransaction && - ((HibernateTransactionObject) transaction).HasTransaction(); - } - - /// - /// Begin a new transaction with the given transaction definition. - /// - /// - /// Transaction object returned by - /// . - /// - /// - /// instance, describing - /// propagation behavior, isolation level, timeout etc. - /// - /// - /// Does not have to care about applying the propagation behavior, - /// as this has already been handled by this abstract manager. - /// - /// - /// In the case of creation or system errors. - /// - protected override void DoBegin(object transaction, ITransactionDefinition definition) - { - - TxScopeTransactionManager.PromotableTxScopeTransactionObject promotableTxScopeTransactionObject = - ((HibernateTransactionObject)transaction).PromotableTxScopeTransactionObject; - try - { - DoTxScopeBegin(promotableTxScopeTransactionObject, definition); - } - catch (Exception e) - { - throw new CannotCreateTransactionException("Transaction Scope failure on begin", e); - } - - if (log.IsDebugEnabled) - { - log.Debug(string.Format("DoBegin: Began new System.Transactions.Transaction{0}", WriteTransactionInformation(System.Transactions.Transaction.Current))); - } - - 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) - { - 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; - try - { - con = session.Connection; - //TODO isolation level mgmt - //IsolationLevel previousIsolationLevel = - } - catch (System.Data.SqlClient.SqlException ex) - { - // Retry logic as a workaround for ADO.NET 2.0 vulnerabilty: KB916002 and MS Connect bug 93731 - if (ex.Message.Contains("New request is not allowed to start because it should come with valid transaction descriptor")) - { - if (log.IsWarnEnabled) - { - log.Warn("Forced to clear all SQL connection pools due to corrupted transaction context on a connection from the connection pool (KB916002)."); - } - System.Data.SqlClient.SqlConnection.ClearAllPools(); - con = session.Connection; - } - else - { - throw; - } - } - - 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); - } - - - } - - private void DoTxScopeBegin(TxScopeTransactionManager.PromotableTxScopeTransactionObject txObject, - Spring.Transaction.ITransactionDefinition definition) - { - - TransactionScopeOption txScopeOption = CreateTransactionScopeOptions(definition); - TransactionOptions txOptions = CreateTransactionOptions(definition); - txObject.TxScopeAdapter.CreateTransactionScope(txScopeOption, txOptions, definition.EnterpriseServicesInteropOption); - - } - - 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; - } - - - private static TransactionOptions CreateTransactionOptions(ITransactionDefinition definition) - { - TransactionOptions txOptions = new TransactionOptions(); - switch (definition.TransactionIsolationLevel) - { - case System.Data.IsolationLevel.Chaos: - txOptions.IsolationLevel = System.Transactions.IsolationLevel.Chaos; - break; - case System.Data.IsolationLevel.ReadCommitted: - txOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; - break; - case System.Data.IsolationLevel.ReadUncommitted: - txOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted; - break; - case System.Data.IsolationLevel.RepeatableRead: - txOptions.IsolationLevel = System.Transactions.IsolationLevel.RepeatableRead; - break; - case System.Data.IsolationLevel.Serializable: - txOptions.IsolationLevel = System.Transactions.IsolationLevel.Serializable; - break; - case System.Data.IsolationLevel.Snapshot: - txOptions.IsolationLevel = System.Transactions.IsolationLevel.Snapshot; - break; - case System.Data.IsolationLevel.Unspecified: - txOptions.IsolationLevel = System.Transactions.IsolationLevel.Unspecified; - break; - } - - if (definition.TransactionTimeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) - { - txOptions.Timeout = new TimeSpan(0, 0, definition.TransactionTimeout); - } - return txOptions; - } - - - - /// - /// Suspend the resources of the current transaction. - /// - /// - /// Transaction object returned by - /// . - /// - /// - /// An object that holds suspended resources (will be kept unexamined for passing it into - /// .) - /// - /// - /// Transaction synchronization will already have been suspended. - /// - /// - /// If suspending is not supported by the transaction manager implementation. - /// - /// - /// in case of system errors. - /// - protected override object DoSuspend(object transaction) - { - HibernateTransactionObject txObject = (HibernateTransactionObject)transaction; - txObject.SetSessionHolder(null, false); - SessionHolder sessionHolder = - (SessionHolder)TransactionSynchronizationManager.UnbindResource(SessionFactory); - ConnectionHolder connectionHolder = null; - if (DbProvider != null) - { - connectionHolder = (ConnectionHolder)TransactionSynchronizationManager.UnbindResource(DbProvider); - } - return new SuspendedResourcesHolder(sessionHolder, connectionHolder); - - } - - /// - /// Resume the resources of the current transaction. - /// - /// - /// Transaction object returned by - /// . - /// - /// - /// The object that holds suspended resources as returned by - /// . - /// - /// - /// Transaction synchronization will be resumed afterwards. - /// - /// - /// If suspending is not supported by the transaction manager implementation. - /// - /// - /// In the case of system errors. - /// - protected override void DoResume(object transaction, object suspendedResources) - { - SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder)suspendedResources; - if (TransactionSynchronizationManager.HasResource(SessionFactory)) - { - // From non-transactional code running in active transaction synchronization - // -> can be safely removed, will be closed on transaction completion. - TransactionSynchronizationManager.UnbindResource(SessionFactory); - } - TransactionSynchronizationManager.BindResource(SessionFactory, resourcesHolder.SessionHolder); - if (DbProvider != null) - { - TransactionSynchronizationManager.BindResource(DbProvider, resourcesHolder.ConnectionHolder); - } - } - - /// - /// Perform an actual commit on the given transaction. - /// - /// The status representation of the transaction. - /// - ///

- /// An implementation does not need to check the rollback-only flag. - ///

- ///
- /// - /// In the case of system errors. - /// - protected override void DoCommit(DefaultTransactionStatus status) - { - HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction; - if (status.Debug) - { - log.Debug("Committing Hibernate transaction on Session [" + - txObject.SessionHolder.Session + "]"); - } - try - { - txObject.SessionHolder.Transaction.Commit(); - } - // Note, unfortunate collision of namespaces/classname for NHibernate.TransactionException - // and Spring.Data.NHibernate requires this wierd construct. - catch (Exception ex) - { - Type nhibTxExceptiontype = TypeResolutionUtils.ResolveType("NHibernate.TransactionException, NHibernate"); - if (ex.GetType().Equals(nhibTxExceptiontype)) - { - // assumably from commit call to the underlying ADO.NET connection - throw new TransactionSystemException("Could not commit Hibernate transaction", ex); - } - HibernateException hibEx = ex as HibernateException; - if (hibEx != null) - { - // assumably failed to flush changes to database - throw ConvertHibernateAccessException(hibEx); - } - throw; - } - finally - { - DoTxScopeCommit(status); - } - - - - } - - /// - /// Does the tx scope commit. - /// - /// The status. - protected void DoTxScopeCommit(DefaultTransactionStatus status) - { - TxScopeTransactionManager.PromotableTxScopeTransactionObject txObject = - ((HibernateTransactionObject)status.Transaction).PromotableTxScopeTransactionObject; - try - { - txObject.TxScopeAdapter.Complete(); - txObject.TxScopeAdapter.Dispose(); - } - catch (TransactionAbortedException ex) - { - throw new UnexpectedRollbackException("Transaction unexpectedly rolled back (maybe due to a timeout)", ex); - } - catch (TransactionInDoubtException ex) - { - throw new HeuristicCompletionException(TransactionOutcomeState.Unknown, ex); - } - catch (Exception ex) - { - throw new TransactionSystemException("Failure on Transaction Scope Commit", ex); - } - } - - /// - /// Perform an actual rollback on the given transaction. - /// - /// The status representation of the transaction. - /// - /// An implementation does not need to check the new transaction flag. - /// - /// - /// In the case of system errors. - /// - protected override void DoRollback(DefaultTransactionStatus status) - { - HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction; - - if (!txObject.NewSessionHolder) - { - // Clear all pending inserts/updates/deletes in the Session. - // Necessary for pre-bound Sessions, to avoid inconsistent state. - txObject.SessionHolder.Session.Clear(); - } - - DoTxScopeRollback(status); - return; - - - /* HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction; - - if (status.Debug) - { - log.Debug("Rolling back Hibernate transaction on Session [" + - txObject.SessionHolder.Session + "]"); - } - try - { - if (txObject.SessionHolder.Session != null && txObject.SessionHolder.Transaction != null && !txObject.SessionHolder.Transaction.IsActive) - { - return; - } - - IDbTransaction adoTx = GetIDbTransaction(txObject.SessionHolder.Transaction); - - if (adoTx != null && adoTx.Connection != null) - { - txObject.SessionHolder.Transaction.Rollback(); - } - else - { - if (status.Debug) - { - log.Debug("Unable to RollBack Hibernate transaction; connection for Hibernate transaction on Session [" + - txObject.SessionHolder.Session + "] was null"); - } - } - - } - catch (HibernateTransactionException ex) - { - throw new TransactionSystemException("Could not roll back Hibernate transaction", ex); - } - catch (HibernateException ex) - { - // Shouldn't really happen, as a rollback doesn't cause a flush. - throw ConvertHibernateAccessException(ex); - } - finally - { - if (!txObject.NewSessionHolder) - { - // Clear all pending inserts/updates/deletes in the Session. - // Necessary for pre-bound Sessions, to avoid inconsistent state. - txObject.SessionHolder.Session.Clear(); - } - DoTxScopeRollback(status); - }*/ - } - - /// - /// Does the tx scope rollback. - /// - /// The status. - protected void DoTxScopeRollback(DefaultTransactionStatus status) - { - TxScopeTransactionManager.PromotableTxScopeTransactionObject txObject = - ((HibernateTransactionObject)status.Transaction).PromotableTxScopeTransactionObject; - - try - { - - txObject.TxScopeAdapter.Dispose(); - } - catch (Exception e) - { - throw new Spring.Transaction.TransactionSystemException("Failure on Transaction Scope rollback.", e); - } - } - - /// - /// Set the given transaction rollback-only. Only called on rollback - /// if the current transaction takes part in an existing one. - /// - /// The status representation of the transaction. - /// - /// In the case of system errors. - /// - protected override void DoSetRollbackOnly(DefaultTransactionStatus status) - { - HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction; - if (status.Debug) - { - log.Debug("Setting Hibernate transaction on Session [" + - txObject.SessionHolder.Session + "] rollback-only"); - } - txObject.SetRollbackOnly(); - - DoTxScopeSetRollbackOnly(status); - } - - /// - /// Does the tx scope set rollback only. - /// - /// The status. - protected void DoTxScopeSetRollbackOnly(DefaultTransactionStatus status) - { - if (status.Debug) - { - log.Debug("Setting transaction rollback-only"); - } - try - { - System.Transactions.Transaction.Current.Rollback(); - } - catch (Exception ex) - { - throw new TransactionSystemException("Failure on System.Transactions.Transaction.Current.Rollback", ex); - } - } - - - /// - /// Gets the ADO.NET IDbTransaction object from the NHibernate ITransaction object. - /// - /// The hibernate transaction. - /// The ADO.NET transaction. Null if could not get the transaction. Warning - /// messages will be logged in that case. - protected IDbTransaction GetIDbTransaction(ITransaction hibernateTx) - { - AdoTransaction hibernateAdoTx = hibernateTx as AdoTransaction; - - IDbTransaction adoTransaction = null; - if (hibernateAdoTx != null) - { - try - { - FieldInfo fi = hibernateAdoTx.GetType().GetField("trans", BindingFlags.Instance | BindingFlags.NonPublic); - adoTransaction = fi.GetValue(hibernateAdoTx) as IDbTransaction; - } - catch (Exception e) - { - log.Warn("Could not extract IDbTransaction from Hibernate AdoTransaction using field name trans.", e); - } - } - else - { - log.Warn("Hibernate ITransaction not of expected type AdoTransaction. Could not extract IDbTransaction from Hibernate AdoTransaction."); - } - return adoTransaction; - } - - /// - /// Convert the given HibernateException to an appropriate exception from - /// the Spring.Dao hierarchy. Can be overridden in subclasses. - /// - /// The HibernateException that occured. - /// The corresponding DataAccessException instance - protected virtual DataAccessException ConvertHibernateAccessException(HibernateException ex) - { - if (AdoExceptionTranslator != null && ex is ADOException) - { - return ConvertAdoAccessException((ADOException)ex, AdoExceptionTranslator); - } - else if (ex is ADOException) - { - return ConvertAdoAccessException((ADOException)ex, DefaultAdoExceptionTranslator); - } - return SessionFactoryUtils.ConvertHibernateAccessException(ex); - } - - /// - /// Convert the given ADOException to an appropriate exception from the - /// the Spring.Dao hierarchy. Can be overridden in subclasses. - /// - /// The ADOException that occured, wrapping the underlying - /// ADO.NET thrown exception. - /// The translator to convert hibernate ADOExceptions. - /// - /// The corresponding DataAccessException instance - /// - protected virtual DataAccessException ConvertAdoAccessException(ADOException ex, IAdoExceptionTranslator translator) - { - return translator.Translate("Hibernate flushing: " + ex.Message, null, ex.InnerException); - } - - /// - /// Cleanup resources after transaction completion. - /// - /// Transaction object returned by - /// . - /// - /// - /// This implemenation unbinds the SessionFactory and - /// DbProvider from thread local storage and closes the - /// ISession. - /// - ///

- /// Called after - /// and - /// - /// execution on any outcome. - ///

- ///

- /// Should not throw any exceptions but just issue warnings on errors. - ///

- ///
- protected override void DoCleanupAfterCompletion(object transaction) - { - HibernateTransactionObject txObject = (HibernateTransactionObject)transaction; - - // Remove the session holder from the thread. - if (txObject.NewSessionHolder) - { - TransactionSynchronizationManager.UnbindResource(SessionFactory); - } - // Remove the ADO.NET connection holder from the thread, if exposed. - if (DbProvider != null) - { - TransactionSynchronizationManager.UnbindResource(DbProvider); - } - /* - try - { - //TODO investigate isolation level settings... - //IDbConnection con = txObject.SessionHolder.Session.Connection; - //AdoUtils.ResetConnectionAfterTransaction(con, txObject.PreviousIsolationLevel); - } - catch (HibernateException ex) - { - log.Info("Could not access ADO.NET IDbConnection of Hibernate Session", ex); - } - */ - ISession session = txObject.SessionHolder.Session; - if (txObject.NewSessionHolder) - { - if (log.IsDebugEnabled) - { - log.Debug("Closing Hibernate Session [" + session + "] after transaction"); - } - // SessionFactoryUtils.CloseSessionOrRegisterDeferredClose(session, SessionFactory); - // NOTE: The above line has to be called via reflection since it is an internal method - SessionFactoryUtils_CloseSessionOrRegisterDeferredClose_Method.Invoke(null, BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic, null, new object[] { session, SessionFactory }, null); - } - else - { - if (log.IsDebugEnabled) - { - log.Debug("Not closing pre-bound Hibernate Session [" + session + "] after transaction"); - } - if (txObject.SessionHolder.AssignedPreviousFlushMode) - { - session.FlushMode = txObject.SessionHolder.PreviousFlushMode; - } - } - txObject.SessionHolder.Clear(); - - - } - - private class HibernateTransactionObject : AdoTransactionObjectSupport - { - - private SessionHolder sessionHolder; - - private bool newSessionHolder; - - private TxScopeTransactionManager.PromotableTxScopeTransactionObject promotableTxScopeTransactionObject; - - - public void SetSessionHolder(SessionHolder sessionHolder, bool newSessionHolder) - { - this.sessionHolder = sessionHolder; - this.newSessionHolder = newSessionHolder; - } - - public TxScopeTransactionManager.PromotableTxScopeTransactionObject PromotableTxScopeTransactionObject - { - get { return promotableTxScopeTransactionObject; } - set { this.promotableTxScopeTransactionObject = value; } - } - - public SessionHolder SessionHolder - { - get - { - return sessionHolder; - } - } - - public bool NewSessionHolder - { - get - { - return newSessionHolder; - } - } - - public bool HasTransaction() - { - return (this.sessionHolder != null && this.sessionHolder.Transaction != null); - } - - public void SetRollbackOnly() - { - if (SessionHolder != null) - { - SessionHolder.RollbackOnly = true; - } - if (ConnectionHolder != null) - { - ConnectionHolder.RollbackOnly = true; - } - } - - /// - /// Return whether the transaction is internally marked as rollback-only. - /// - /// - /// True of the transaction is marked as rollback-only. - public override bool RollbackOnly - { - get - { - return ((SessionHolder != null && SessionHolder.RollbackOnly) || - (ConnectionHolder != null && ConnectionHolder.RollbackOnly)); - } - } - } - - private class SuspendedResourcesHolder - { - - private readonly SessionHolder sessionHolder; - - private readonly ConnectionHolder connectionHolder; - - public SuspendedResourcesHolder(SessionHolder sessionHolder, ConnectionHolder conHolder) - { - this.sessionHolder = sessionHolder; - this.connectionHolder = conHolder; - } - - public SessionHolder SessionHolder - { - get - { - return sessionHolder; - } - - } - - public ConnectionHolder ConnectionHolder - { - get - { - return connectionHolder; - } - - } - } - - /// - /// Invoked by an - /// after it has injected all of an object's dependencies. - /// - /// - ///

- /// This method allows the object instance to perform the kind of - /// initialization only possible when all of it's dependencies have - /// been injected (set), and to throw an appropriate exception in the - /// event of misconfiguration. - ///

- ///

- /// Please do consult the class level documentation for the - /// interface for a - /// description of exactly when this method is invoked. In - /// particular, it is worth noting that the - /// - /// and - /// callbacks will have been invoked prior to this method being - /// called. - ///

- ///
- /// - /// In the event of misconfiguration (such as the failure to set a - /// required property) or if initialization fails. - /// - public void AfterPropertiesSet() - { - if (SessionFactory == null) - { - throw new ArgumentException("sessionFactory is required"); - } - if (this.entityInterceptor is string && this.objectFactory == null) - { - throw new ArgumentException("objectFactory is required for entityInterceptorBeanName"); - } - - // Try to derive a DbProvider given the SessionFactory. - if (this.autodetectDbProvider && DbProvider == null) - { - IDbProvider sfDbProvider = SessionFactoryUtils.GetDbProvider(SessionFactory); - if (sfDbProvider != null) - { - // Use the SessionFactory's DataSource for exposing transactions to ADO.NET code. - if (log.IsInfoEnabled) - { - log.Info("Derived DbProvider [" + sfDbProvider.DbMetadata.ProductName + - "] of Hibernate SessionFactory for HibernateTransactionManager"); - } - DbProvider = sfDbProvider; - } - else - { - log.Info("Could not auto detect DbProvider from SessionFactory configuration"); - } - - } - } - - private static string WriteTransactionInformation(System.Transactions.Transaction tx) - { - if (tx == null) - { - return "NULL"; - } - - string isoLevel = System.Transactions.Transaction.Current.IsolationLevel.ToString(); - TransactionInformation txInfo = System.Transactions.Transaction.Current.TransactionInformation; - return string.Format("{{LocalId = {0}, DistributedId = {1}, Status = {2}, IsolationLevel = {3}, CreationTime = {4}}}", txInfo.LocalIdentifier, txInfo.DistributedIdentifier, txInfo.Status, isoLevel, txInfo.CreationTime.ToString("o")); - } - - } -} diff --git a/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.CustomHibernateTxScopeTransactionManager.xml b/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.CustomHibernateTxScopeTransactionManager.xml deleted file mode 100644 index 5657013e..00000000 --- a/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.CustomHibernateTxScopeTransactionManager.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests.csproj b/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests.csproj index 9b6c8909..2231a6d1 100644 --- a/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests.csproj +++ b/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests.csproj @@ -56,8 +56,6 @@ - - @@ -97,8 +95,6 @@ - - diff --git a/test/Spring/Spring.SessionFactoryImplError.Tests/TestUsingCustomHibernateTxScopeTransactionManager.cs b/test/Spring/Spring.SessionFactoryImplError.Tests/TestUsingCustomHibernateTxScopeTransactionManager.cs deleted file mode 100644 index 9766825e..00000000 --- a/test/Spring/Spring.SessionFactoryImplError.Tests/TestUsingCustomHibernateTxScopeTransactionManager.cs +++ /dev/null @@ -1,50 +0,0 @@ -using NUnit.Framework; -using Spring.Data.NHibernate.Generic; -using Spring.Testing.NUnit; - -namespace Spring.SessionFactoryImplError.Tests -{ - [TestFixture] - public class TestUsingCustomHibernateTxScopeTransactionManager : AbstractTransactionalSpringContextTests - { - #region DI - - public HibernateTemplate HibernateTemplate { get; set; } - public IService1 Service1 { get; set; } - public IService2 Service2 { get; set; } - - #endregion - - protected override string[] ConfigLocations - { - get - { - return new[] - { - "config://spring/objects", - "assembly://Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests/Spring.Configuration.xml", - "assembly://Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests/Spring.NHibernate.xml", - "assembly://Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests/Spring.CustomHibernateTxScopeTransactionManager.xml" - }; - } - } - - [Test(Description = "This is failing test case in my unit test with original NH TX Scope Manager, but not Custom TX Scope Manager, Not Supported -> Not Supported")] - public void TestSuspendTransactionOnNotSupported() - { - Service1.ServiceMethodWithNotSupported1(); - } - - [Test(Description = "This is also failing with NH TX Scope manager, but nto with Custom TX Scope Manager, Not Supported -> Requires New")] - public void TestSuspendTransactionOnNotSupportedWithNestedRequiresNew() - { - Service2.ServiceMethodWithNotSupported(); - } - - [Test(Description = "This is failing test case in my unit test with Custom TX Scope Manager (this is the original bug reported), Not Supported -> Not Supported -> Required")] - public void TestSuspendTransactionOnNotSupportedWithNestedRequired() - { - Service1.ServiceMethodWithNotSupported3(); - } - } -}