Click here to Skip to main content
15,892,674 members
Articles / Programming Languages / XML

Building a Middle Tier Component using NHibernate and Spring.NET

Rate me:
Please Sign up or sign in to vote.
4.50/5 (21 votes)
10 May 2006CPOL8 min read 158.9K   2.4K   109  
Building a highly pluggable middle-tier component with NHibernate and Spring.Net.
#region Licence

/*
 * Copyright � 2002-2005 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#endregion

#region Imports

using System;
using Spring.Objects.Factory;
using log4net;
using Spring.Transaction.Interceptor;
#endregion

namespace Spring.Transaction.Support
{
	/// <summary>
	///
	/// Abstract base class that allows for easy implementation of concrete
	/// platform transaction managers like JtaTransactionManager and
	/// DataSourceTransactionManager.
	///
	/// <p>This base class provides the following workflow handling:</P>
	/// <ul>
	/// <li>determines if there is an existing transaction;
	/// <li>applies the appropriate propagation behavior;
	/// <li>suspends and resumes transactions if necessary;
	/// <li>checks the rollback-only flag on commit;
	/// <li>applies the appropriate modification on rollback
	/// (actual rollback or setting rollback-only);
	/// <li>triggers registered synchronization callbacks
	/// (if transaction synchronization is active).
	/// </ul>
	///
	/// <p>Subclasses have to implement specific template methods for specific
	/// states of a transaction, for example begin, suspend, resume, commit, rollback.
	/// The most important of them are abstract and must be provided by a concrete
	/// implementation; for the rest, defaults are provided, so overriding is optional.
	///
	/// <p>Transaction synchronization is a generic mechanism for registering callbacks
	/// that get invoked at transaction completion time. This is mainly used internally
	/// by the data access support classes Hibernate transaction:
	///  They register resources that are opened within the
	/// transaction for closing at transaction completion time, allowing e.g. for reuse
	/// of the same Hibernate Session within the transaction. The same mechanism can
	/// also be leveraged for custom synchronization needs in an application.
	/// 
	/// <p>The state of this class is serializable, to allow for serializing the
	/// transaction strategy along with proxies that carry a transaction interceptor.
	/// It is up to subclasses if they wish to make their state to be serializable too.	
	///
	/// <author> Juergen Hoeller </author>
	/// <author> Moim Hossain (.NET ) </author>
	/// </summary>
	public abstract class AbstractPlatformTransactionManager : IPlatformTransactionManager
	{
		#region IPlatformTransactionManager Members		
		/// <summary>
		/// 
		/// </summary>
		/// <param name="definition"></param>
		/// <returns></returns>
		public ITransactionStatus GetTransaction(ITransactionDefinition definition)
		{
			// The Generic Transaction Object
			Object Transaction = null;

			if( definition.GetPropagationBehavior() == TransactionAttribute.PROPAGATION_REQUIRES_NEW )
			{	// Create a new Transacion for this thread,
				Transaction = DoGetNewTransaction();
			}
			else if( definition.GetPropagationBehavior() == TransactionAttribute.PROPAGATION_REQUIRED )
			{	// Create a new Transaction If No Transacion Exists
				Transaction = DoGetTransaction();
			}
			else
			{	// In Any Other Cases We will assume that this Object doesn't need any transaction 
				// support at all.
				// Not Supporting Other Propagation Mode
				Transaction = DoGetPropagationNeutralTransaction();
			}


			if( definition.GetPropagationBehavior().Equals(TransactionAttribute.PROPAGATION_REQUIRES_NEW) ||
				definition.GetPropagationBehavior().Equals(TransactionAttribute.PROPAGATION_REQUIRED ))
			{	// If Propagatin is transactional then Issue the transaction.
				DoBegin( Transaction , definition );
			}

			bool FoundTransactionCreated = IsExistingTransaction( Transaction );
//
//
//			
//			if( IsExistingTransaction( Transaction ) )
//			{
//				DoBegin( Transaction , definition );
//			}
//			else
//			{
//				DoBegin( Transaction , definition );
//			}

			return NewTransactionStatus( Transaction , FoundTransactionCreated , false , false , false , null);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="status"></param>
		public void Commit(ITransactionStatus status)
		{
			DefaultTransactionStatus Status = (DefaultTransactionStatus)status;

			DoCommit( Status );
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="status"></param>
		public void Rollback( ITransactionStatus status )
		{
			DefaultTransactionStatus Status = (DefaultTransactionStatus)status;

			DoRollback( Status );		
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="status"></param>
		public void Dispose( ITransactionStatus status )
		{
			DefaultTransactionStatus Status = (DefaultTransactionStatus)status;

			DoDispose( Status );	
		}
		#endregion
		/// <summary>
		/// 
		/// </summary>
		/// <param name="transaction"></param>
		/// <param name="newTransaction"></param>
		/// <param name="newSynchronization"></param>
		/// <param name="readOnly"></param>
		/// <param name="debug"></param>
		/// <param name="suspendedResources"></param>
		/// <returns></returns>
		private ITransactionStatus NewTransactionStatus(Object transaction, bool newTransaction, bool newSynchronization, bool readOnly, bool debug, Object suspendedResources )
		{
			return new DefaultTransactionStatus(
				transaction, newTransaction, newSynchronization, readOnly, debug, suspendedResources);
		}
		/// <summary>
		/// Perform an actual commit of the given transaction.
		/// <p>An implementation does not need to check the "new transaction" flag
		/// or the rollback-only flag; this will already have been handled before.
		/// Usually, a straight commit will be performed on the transaction object
		/// contained in the passed-in status.</p>
		/// </summary>
		protected abstract void DoCommit(DefaultTransactionStatus status);
		/// <summary>
		/// Perform an actual rollback of the given transaction.
		/// <p>An implementation does not need to check the "new transaction" flag;
		/// this will already have been handled before. Usually, a straight rollback
		/// will be performed on the transaction object contained in the passed-in status.</p>
		/// </summary>
		protected abstract void DoRollback(DefaultTransactionStatus status);
		/// <summary>
		 /// Begin a new transaction with the given transaction definition.
		 /// Does not have to care about applying the propagation behavior,
		 /// as this has already been handled by this abstract manager.
		 /// </summary>
		protected abstract void DoBegin(Object transaction, ITransactionDefinition definition);
		/// <summary>
		/// Dispose the Transaction
		/// </summary>
		/// <param name="status"></param>
		protected abstract void DoDispose(DefaultTransactionStatus status );
		//---------------------------------------------------------------------
		// Template methods to be implemented in subclasses
		//---------------------------------------------------------------------

		/// <summary>
		/// Return a transaction object for the current transaction state.
		/// <p>The returned object will usually be specific to the concrete transaction
		/// manager implementation, carrying corresponding transaction state in a
		/// modifiable fashion. This object will be passed into the other template
		/// methods (e.g. doBegin and doCommit), either directly or as part of a
		/// DefaultTransactionStatus instance.
		/// <p>The returned object should contain information about any existing
		/// transaction, that is, a transaction that has already started before the
		/// current <code>GetTransaction</code> call on the transaction manager.
		/// Consequently, a <code>doGetTransaction</code> implementation will usually
		/// look for an existing transaction and store corresponding state in the
		/// returned transaction object.
		/// </summary>
		protected abstract Object DoGetTransaction() ;
		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		protected abstract Object DoGetNewTransaction() ;
		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		protected abstract Object DoGetPropagationNeutralTransaction();
		/// <summary>		
		/// Check if the given transaction object indicates an existing transaction
		/// (that is, a transaction which has already started).
		/// <p>The result will be evaluated according to the specified propagation
		/// behavior for the new transaction. An existing transaction might get
		/// suspended (in case of PROPAGATION_REQUIRES_NEW), or the new transaction
		/// might participate in the existing one (in case of PROPAGATION_REQUIRED).</p>
		/// <p>Default implementation returns false</p>
		/// <param name="transaction"></param>
		/// </summary>
		protected virtual bool IsExistingTransaction(Object transaction)
		{
			return false;
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Netherlands Netherlands
Engineer Powered by the Cloud

Comments and Discussions