Composite Applications with NHibernate

On June 21, 2009, in Uncategorized, by derekgreer

Composite application architecture is an approach to software development which seeks to produce applications which can be constructed from pre-built components, thus allowing a single platform to be more easily customized for end users.

The pre-built components, or modules, comprising a composite application often share data access concerns such as the need to access a central database. The use of object-relational mapping frameworks are an increasingly common strategy for facilitating data access needs. This is due to their ability to minimize much of the repetitive, low-level data access coding often required by more traditional approaches, and their ability to abstract much of the idiosyncrasies of specific database vendors, providing greater potential for portability between vendors.

NHibernate, arguably the leading object-relational mapping framework for the .Net platform, facilitates object-relational mapping through a centrally configured component called the SessionFactory. A SessionFactory is configured with the connection parameters for a specific database along with the mapping meta-data required for associating objects to the relational data within the database.

It is generally advised that a single SessionFactory be created per database. This is both due to the overhead required in its creation, and in order to facilitate various caching strategies such as the caching of generated SQL statements, and of entities across sessions (referred to as the second-level cache).

For composite applications, configuration of the SessionFactory can pose a bit of an obstacle given that any centralization of the mapping configuration would tend to couple otherwise independent and optional modules together. Additionally, a centralized configuration of the mappings for each of the modules precludes encapsulation of the configuration needs within each module, and can introduce maintenance complexity for modules developed by separate development teams or organizations. On the other hand, allowing modules to maintain their own SessionFactory for a shared database instance introduces startup overhead and precludes taking advantage of the caching features of the framework.

As demonstrated in the remainder of this article, one approach to solving these challenges is to create a staged application bootstrapping process which both facilitates decentralized mapping registration and centralized SessionFactory initialization.

While potentially applicable in other usage scenarios, the following approach is based upon the use of Fluent NHibernate, the Prism composite application library, and the staged bootstrapping strategy presented within the article: Enhancing the Prism Module Initialization Lifecycle.

Our first step in demonstrating this strategy will be to create a module named DataModule which will serve as an infrastructure-only Prism module for configuring NHibernate. Using the ModuleBase implementation of IModule presented in the aforementioned article, the OnPreInitialization() and OnPostInitialization() methods will be overridden.

namespace CompositeSpike.Data.Module
{
    public class DataModule : ModuleBase
    {
        readonly IUnityContainer _container;

        public DataModule(IUnityContainer container)
        {
            _container = container;
        }

        protected override void OnPreInitialization()
        {
        }

        protected override void OnPostInitialization()
        {
        }
    }
}

The OnPreInitialization() method will be used to register services to be consumed by other modules while the OnPostInitialization phase will be used to perform the final database configuration.

Next, let’s create a CustomerModule which represents a module using NHibernate for its data access needs. This module need only override the OnInitialization() method to gain access to services registered during the Pre-Initialization bootstrapping phase.

namespace CompositeSpike.Data.Module
{
    public class CustomerModule : ModuleBase
    {
        readonly IUnityContainer _container;

        public DataModule(IUnityContainer container)
        {
            _container = container;
        }

        protected override void OnInitialization()
        {
        }
    }
}

Next, we’ll define a mapping service to be used by our CustomerModule for registering which map types and/or assemblies are to be included during the configuration of the SessionFactory.

namespace CompositeSpike.Data.Services
{
    public interface IMappingRegistryService
    {
        void AddMap() where T : IClassMap;
        void AddMap(Type classMap);
        void AddMapsFromAssemblyOf();
        void AddMapsFromAssembly(Assembly assembly);
    }
}

Next, we’ll provide an internal implementation of the mapping service to be contained within t
he DataModule. Two additional properties, Assemblies and Types, are provided to enable the DataModule to access any mapping types and assemblies registered by modules during the Initialization phase.

namespace CompositeSpike.Data.Module.Services
{
    class MappingRegistryService : IMappingRegistryService
    {
        readonly IList _assemblies;
        readonly List _types;

        public MappingRegistryService()
        {
            _assemblies = new List();
            _types = new List();
        }

        public IEnumerable Assemblies
        {
            get { return _assemblies; }
        }

        public IEnumerable Types
        {
            get { return _types; }
        }

        public void AddMap() where T : IClassMap
        {
            AddMap(typeof (T));
        }

        public void AddMap(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (!_types.Contains(type))
            {
                _types.Add(type);
            }
        }

        public void AddMapsFromAssemblyOf()
        {
            AddMapsFromAssembly(typeof (T).Assembly);
        }

        public void AddMapsFromAssembly(Assembly assembly)
        {
            if (!_assemblies.Contains(assembly))
            {
                _assemblies.Add(assembly);
            }
        }
    }
}

With the service defined, let’s return to the DataModule and complete the body of the initialization methods.

To ensure the mapping service is available during the initialization phase of the other modules within the application, the IMappingRegistryService and its internal implementation need to be registered as a singleton with the Unity container during the PreInitialization bootstrapping phase:

        protected override void OnPreInitialization()
        {
            _container.RegisterType(new ContainerControlledLifetimeManager());
        }

After modules have been given an opportunity to register mappings with our service during the Initialization phase, the service can be retrieved and used to supply the class map types and/or assemblies required for the Fluent NHibernate configuration:

        protected override void OnPostInitialization()
        {
            var service = _container.Resolve() as MappingRegistryService;

            ISessionFactory sessionFactory = Fluently.Configure()
                .Database(OracleConfiguration.Oracle9
                              .ConnectionString(
                              c => c.Is(ConfigurationManager.ConnectionStrings["example"].ConnectionString))
                              .ShowSql())
                .Mappings(m =>
                    {
                        service.Types.ForEach(t => m.FluentMappings.Add(t));

                        service.Assemblies.ForEach(a => m.FluentMappings.AddFromAssembly(a));
                    })
                .BuildSessionFactory();

            _container
                .RegisterInstance(new NHibernateDatabaseContext(sessionFactory),
                                  new ContainerControlledLifetimeManager());
        }

Our final step is to complete the initialization method within our CustomerModule to register any desired mappings to be used by the DataModule:

        protected override void OnInitialization()
        {
            var dataMappingService = _container.Resolve();
            if (dataMappingService != null) dataMappingService.AddMapsFromAssemblyOf();
        }

That concludes our example.

By utilizing a mapping service in conjunction with a multi-phased initialization strategy, a proper level of separation of concerns can be maintained for the modules within a composite application while at the same time utilizing NHibernate’s SessionFactory in the prescribed manner.

Tagged with:  

Unity: The Static Factory Extension

On June 15, 2009, in Uncategorized, by derekgreer

The Unity Inversion of Control container comes with an extension called the StaticFactoryExtension. The purpose of this extension is to add the ability to register types within the container while deferring the instantiation of the type to a factory method. This enables a number of scenarios where finer-grained control over the construction of an object is desired.

As the name suggests, one example use of the extension is with a static factory method. In the following test, an ILoggingService is registered with the container by configuring it to call the LoggingService.GetLoggingService() static method via the IStaticFactoryConfiguration.

namespace StaticFactoryExample
{
    public class StaticFactoryExampleSpecs
    {
        [TestFixture]
        public class When_a_logging_service_is_resolved_using_a_static_factory_method
        {
            UnityContainer _container;

            [SetUp]
            public void SetUp()
            {
                _container = new UnityContainer();

                _container
                    .AddNewExtension()
                    .Configure()
                    .RegisterFactory(container =>
                                     LoggingService.GetLoggingService());
            }

            [Test]
            public void A_logging_service_should_be_returned()
            {
                Assert.IsNotNull(_container.Resolve());
            }
        }
    }

    public interface ILoggingService
    {
    }

    public sealed class LoggingService : ILoggingService
    {
        readonly Log4NetLogger _logger;

        LoggingService(Log4NetLogger logger)
        {
            _logger = logger;
        }

        public static ILoggingService GetLoggingService()
        {
            return Nested.instance;
        }

        static class Nested
        {
            internal static readonly ILoggingService instance = new LoggingService(new Log4NetLogger());
        }
    }

    public interface ILogger
    {
    }

    public class Log4NetLogger : ILogger
    {
    }
}

While use with actual static factory methods may have been the driving factor for the creation of this extension, there is nothing inherently prescriptive about the extension which necessitates that the methods used be static.

Another example use of the StaticFactoryExtension is to conceal dependencies of resolved types which you may not want to be accessible through the container. Consider the following alternate example registration of the ILoggingService:

namespace StaticFactoryExample
{
    public class StaticFactoryExampleSpecs
    {
        [TestFixture]
        public class When_a_logging_service_is_resolved_using_a_static_factory_method
        {
            UnityContainer _container;

            [SetUp]
            public void SetUp()
            {
                _container = new UnityContainer();

                _container
                    .AddNewExtension()
                    .RegisterType(new ContainerControlledLifetimeManager())
                    .Configure()
                    .RegisterFactory(container =>
                                     new LoggingService(new Log4NetLogger()));
            }

            [Test]
            public void A_logging_service_should_be_returned()
            {
                Assert.IsNotNull(_container.Resolve());
            }

            [Test]
            public void The_logging_service_returned_should_always_be_the_same_instance()
            {
                Assert.AreSame(
                    _container.Resolve(),
                    _container.Resolve());
            }
        }
    }

    public interface ILoggingService
    {
    }

    public class LoggingService : ILoggingService
    {
        readonly ILogger _logger;

        public LoggingService(ILogger logger)
        {
            _logger = logger;
        }
    }

    public interface ILogger
    {
    }

    public class Log4NetLogger : ILogger
    {
    }
}

In this example, the LoggingService is implemented as a class with an ILogger dependency which must be supplied through the constructor. The factory method responsible for returning the ILoggingService has been rewritten as an expression which returns a newly instantiated instance of the LoggingService and supplies an instance of Log4NetLogger as its dependency implementation. Additionally, the ILoggingService has been registered with a ContainerControlledLifetimeManager. A lifetime manager within Unity is a type responsible for governing how instances of types registered with the container are managed. The ContainerControlledLifetimeManager holds a single instance of the registered type once created and returns the same instance upon all requests. This effectively causes the container to manage the instance as a singleton without placing this responsibility upon the class itself, and without otherwise incurring the drawbacks that the singleton design pattern imposes upon a class.

While enabling the ILoggingService to be resolved by the container could have been achieved without the use of the StaticFactoryExtension by simply registering the LoggingService implementation and the ILogger dependency type, this would have made the instance of ILogger available to types within the system which may not be desired. In this case, the ILoggingService is intended as the public API to be used by types within the system for logging needs. The ILogger type is simply a strategy for how this is accomplished. This approach enables the ILoggingService to be lazy-loaded by the container without exposing the ILogger type.

While the StaticFactoryExtension provides useful behavior to the Unity container, one might argue that the API leaves something to be desired. One of the strengths of the Unity container is its extensibility model. In fact, all of Unity’s functionally is facilitated through extensions. Unfortunately, this means additional functionality such as that provided by the StaticFactoryExtension requires calling the Configure
() method to obtain a reference to the extension. The result is that some degree of ceremony is required each time a factory method needs to be registered for a type.

One approach to improving the API is to encapsulate the required calls to configure a factory method within an extension method. Consider the following extension methods:

    public static class UnityExtensions
    {
        public static IUnityContainer RegisterType(this IUnityContainer container, FactoryDelegate factoryMethod)
        {
            container.Configure().RegisterFactory(factoryMethod);
            return container;
        }

        public static IUnityContainer RegisterType(this IUnityContainer container, FactoryDelegate factoryMethod,
                                                   LifetimeManager lifetimeManager)
        {
            container
                .RegisterType(lifetimeManager)
                .Configure().RegisterFactory(factoryMethod);
            return container;
        }
    }

In the case of the eariler ILoggingService example, where the desired behavior is to always return the same instance, using the extension method which accepts a FactoryDelegate and a LifetimeManager allows the StaticFactoryExtension behavior to be used as follows:

        [SetUp]
        public void SetUp()
        {
            _container = new UnityContainer();

            _container
                .AddNewExtension()
                .RegisterType(container => new LoggingService(new Log4NetLogger()),
                              new ContainerControlledLifetimeManager());
        }
Tagged with:  

Inspired by Jeremy Miller’s presentation of StructureMap’s convention-based type registration at this week’s Austin .Net User’s Group, I set out to create a convention-based type registration extension for the Unity container.

For those unfamiliar with the convention-based approach to type registration for IoC containers, I’ll refer you to Jeremy’s article here which should get you up to speed on the concept.

Unity is fairly easy to extend, so I had the first working prototype after about 15 minutes. I spent several hours afterward, however, trying to tease out an API I felt was suitable. After a few cycles attempting to design a fluent API, I settled upon something similar to Fluent NHibernate’s mapping registration, and one which I think fits decently with Unity’s existing API.

Without further ado, here is an example of its usage:

        [Concern("During setup")]
        public class When_container_configured_with_interface_impl_name_match_convention :
            Behaves_like_context_with_container_with_convention_extension
        {
            protected override void Because()
            {
                _container
                    .Using<IConventionExtension>()
                    .Configure(x =>
                        {
                            x.Conventions.Add<InterfaceImplementionNameMatchConvention>();
                            x.Assemblies.Add(Assembly.GetExecutingAssembly());
                        })
                    .Register();
            }

            [Observation, Test]
            public void Types_matching_convention_should_be_auto_registered()
            {
                _container.Resolve<ITestType>().ShouldBeOfType(typeof (TestType));
            }
        }

After adding the extension to the container, the IConventionExtension configuration is used to configure the conventions and assemblies used during the auto-registration process. The convention used here matches the common .Net naming convention where interface and default implementation pairs share the same name, with the interface carrying an ‘I’ prefix. The test demonstrates resolving an instance of ITestType, though no explicit registration has been provided.

The following test demonstrates using an alternate convention where only implementations of the specified type are auto-registered:

        [Concern("During setup")]
        public class When_container_configured_with_implementation_convention_with_name_replacement :
            Behaves_like_context_with_container_with_convention_extension
        {
            protected override void Because()
            {
                _container
                    .Using<IConventionExtension>()
                    .Configure(x =>
                        {
                            x.Conventions.Add<ImplementationConvention<IController>>();
                            x.Assemblies.Add(Assembly.GetExecutingAssembly());
                        })
                    .Register(x => x.Replace("Controller", ""));
            }

            [Observation, Test]
            public void Controller_types_should_be_resolvable_by_prefix_name()
            {
                _container.Resolve<IController>("MainView").ShouldNotBeNull();
            }

            [Observation, Test]
            public void Types_not_of_type_controller_should_not_be_resolvable()
            {
                try
                {
                    _container.Resolve<ITestType>();
                    throw new Exception("Type ITestType should not be resolvable.");
                }
                catch (ResolutionFailedException)
                {
                }
            }
        }

In this example, the types are registered by name utilizing a delegate to facilitate the ability to modify the default name of the concrete type to be registered in some way. In this case, all implementations of IController are registered under the name of the concrete type, minus the “Controller” suffix.

The full extension source can be downloaded at: http://code.google.com/p/conventionextension/. Enjoy!