Try fast search NHibernate

Showing posts with label Castle Windsor. Show all posts
Showing posts with label Castle Windsor. Show all posts

08 October 2010

Castle Windsor InstantiateAndForgetIt Lifestyle

Directly to the point.

The case

public interface IMySingleton : IDisposable
{
}

public class MySingleton: IMySingleton
{
    public void Dispose()
    {
    }
}

public interface IMyTransient
{
}

public class MyTransient : IMyTransient
{
    private readonly IMySingleton singleton;

    public MyTransient(IMySingleton singleton)
    {
        this.singleton = singleton;
    }
}
As you can see it is pretty common: I have a class MyTransient with a dependency from a singleton. The singleton is disposable.
The transient is from the point of view of its usage, that mean that its lifecycle is managed by an “external context” and, as is, it does not need a special “destructor”. The “external context” may hold the instance somewhere or may use it only in the context of a method and can quite leave the destruction to the garbage collector. If/when MyTransient implements IDisposable the “external context” should dispose the instance. You can see this behavior in various places for example in the DefaultControllerFactory of Asp.NET MVC or in the IInstanceProvider of WCF (both has a ReleaseInstance cheking for IDisposable); personally I have this situation in other places.
If I do something like this
var myInstance = new MyTransient(container.Resolve<IMySingleton>());
The garbage collector will have zero problems to destroy myInstance and I’ll have zero memory leaks… that is clear, no ?

The test using Windsor with Transient Lifestyle

public class TransientLeak
{
    private WindsorContainer GetContainerConfiguredWindsorContainer()
    {
        var container = new WindsorContainer();
        container.Register(Component.For<IMySingleton>().ImplementedBy<MySingleton>());
        container.Register(Component.For<IMyTransient>().ImplementedBy<MyTransient>().LifeStyle.Transient);
        return container;
    }

    [Test]
    public void WhenTransientRequiredThenReturnDifferentInstances()
    {
        using (WindsorContainer container = GetContainerConfiguredWindsorContainer())
        {
            var t0 = container.Resolve<IMyTransient>();
            var t1 = container.Resolve<IMyTransient>();

            t0.Should().Not.Be.SameInstanceAs(t1);
        }
    }

    [Test]
    public void WhenTransientRequiredThenContainerShouldntHaveInstancesOfMyTransient()
    {
        using (WindsorContainer container = GetContainerConfiguredWindsorContainer())
        {
            var t0 = container.Resolve<IMyTransient>();
            var t1 = container.Resolve<IMyTransient>();

            container.Kernel.ReleasePolicy.Satisfy(rp=> !rp.HasTrack(t0));
            container.Kernel.ReleasePolicy.Satisfy(rp => !rp.HasTrack(t1));
        }
    }     
}
Well… the first test pass, that means that each time I asking for a IMyTransient I’ll have a new instance of the concrete implementation injected with the same instance of IMySingleton (as expected).

Now take care : The second test fails. That means that the container is holding two instances of MyTransient class; let me show you where:
TransientLeak
Perhaps there is a good explication for this behavior but I must admit that I can’t understand why all instances of MyTransient should have its lifecycle stuck to the lifecycle of MySingleton only because MySingleton is disposable… bah?!? by the way that is not a matter because Castle.Windsor give us the ability to define the behavior we need.

The solution

First of all I need my custom lifestyle manager:
[Serializable]
public class InstantiateAndForgetIt : ILifestyleManager
{
    private IComponentActivator componentActivator;

    public void Init(IComponentActivator componentActivator, IKernel kernel, ComponentModel model)
    {
        this.componentActivator = componentActivator;
    }

    public object Resolve(CreationContext context)
    {
        return componentActivator.Create(context);
    }

    public bool Release(object instance)
    {
        return true;
    }

    public void Dispose()
    {
     
    }
}

Pretty simple but not enough. Then I need an implementation of IReleasePolicy and I can simply inherit from the default and override a method:
[Serializable]
public class LifecycledComponentsReleasePolicy : Castle.MicroKernel.Releasers.LifecycledComponentsReleasePolicy
{
    private readonly Type instantiateAndForgetItType = typeof (InstantiateAndForgetIt);

    public override void Track(object instance, Burden burden)
    {
        if (instantiateAndForgetItType.Equals(burden.Model.CustomLifestyle))
        {
            return;
        }
        base.Track(instance,burden);
    }
}

The last step is the modification of the container’s configuration:
private WindsorContainer GetContainerConfiguredWindsorContainer()
{
    var container = new WindsorContainer();
    container.Kernel.ReleasePolicy = new LifecycledComponentsReleasePolicy();
    container.Register(Component.For<IMySingleton>().ImplementedBy<MySingleton>());
    container.Register(Component.For<IMyTransient>().ImplementedBy<MyTransient>().LifeStyle.Custom<InstantiateAndForgetIt>());
    return container;
}


Work done!! and bye bye “memory leaks”.


Update: request to have InstantiateAndForgetIt Lifestyle natively supported issue IOC-225 (vote for it)

22 November 2009

The GuyWire

In a afternoon of July I was working refactorizing a web-project. We was using the XML configuration of Castle.Windsor and Santiago Leguiza asked me a way to simplify the configuration.

The natural way to go is the configuration via Fluent-Interface. At that time my opinion about fluent-conf of the IoC was not so good because the fluent-conf needs references to each layer of the application. We have an IApplicationInitializer, for the application startup, but this time I need “something” with a more specific responsibility: wire any application part.

To give a name to a class is not so easy for me… probably because, in my opinion, the name should define the class responsibility. English, other than C#, is not my best, you know… using a mix between internet and my very old Italian-English dictionary, after 15 minutes or so, I have found a pretty good and funny name: GuyWire.

A guy-wire or guy-rope is a tensioned cable designed to add stability to structures. One end of the cable is attached to the structure, and the other is anchored to the ground at a distance from the structure's base.

Happy to have found the name I had twitted it ( first, second )

The interface

The interface is very very simple:

public interface IGuyWire
{
/// <summary>
///
Application wire.
/// </summary>
/// <remarks>
///
IoC container configuration (more probably conf. by code).
/// </remarks>
void Wire();

/// <summary>
///
Application dewire
/// </summary>
/// <remarks>
///
IoC container dispose.
/// </remarks>
void Dewire();
}

Using this interface is easy to realize that you may have different implementation for different IoC or, better, for different scenarios (for example in different test projects or the web-app and the wcf-service).

You can declare the IGuyWire in a separated very simple assembly where the only reference needed is System (nothing more).

Well… the interface is done but if I need to instantiate a concrete implementation I will have again the same problem… my application should know about the IoC and everything about all other parts… hmmm… I’m needing something to inject the injector.

again the solution is so simple as few code lines:

    /// <summary>
///
Helper class to get the <see cref="IGuyWire"/> concrete implementation
/// from application config.
/// </summary>
/// <remarks>
///
The appSetting section should have a key named "GuyWire" (case insensitive)
/// <example>
/// <![CDATA[
/// <appSettings>
/// <add key='GuyWire' value='YourCompany.Product.Wiring.IoC_Fx.GuyWire, YourCompany.Product.Wiring.IoC_Fx'/>
/// </appSettings>"
/// ]]>
/// </example>
/// </remarks>
public static class ApplicationConfiguration
{
private const string GuyWireConfKey = "guywire";
private const string GuyWireConfMessage =
@"The GuyWire was not configured.
Example
<appSettings>
<add key='GuyWire' value='YourCompany.Product.Wiring.IoC_Fx.GuyWire, YourCompany.Product.Wiring.IoC_Fx'/>
</appSettings>"
;

/// <summary>
///
Read the configuration to instantiate the <see cref="IGuyWire"/>.
/// </summary>
/// <returns>
The instance of <see cref="IGuyWire"/>.</returns>
/// <exception cref="ApplicationException">
///
If the key='GuyWire' was not found or if the <see cref="IGuyWire"/> can't be instancied.
/// </exception>
public static IGuyWire GetGuyWire()
{
var guyWireClassKey =
ConfigurationManager.AppSettings.Keys.Cast<string>().FirstOrDefault(k => GuyWireConfKey.Equals(k.ToLowerInvariant()));
if (string.IsNullOrEmpty(guyWireClassKey))
{
throw new ApplicationException(GuyWireConfMessage);
}
var guyWireClass = ConfigurationManager.AppSettings[guyWireClassKey];
var type = Type.GetType(guyWireClass);
try
{
return (IGuyWire)Activator.CreateInstance(type);
}
catch (MissingMethodException ex)
{
throw new ApplicationException("Public constructor was not found for " + type, ex);
}
catch (InvalidCastException ex)
{
throw new ApplicationException(type + "Type does not implement " + typeof(IGuyWire), ex);
}
catch (Exception ex)
{
throw new ApplicationException("Unable to instantiate: " + type, ex);
}
}
}

The ApplicationConfiguration class can stay in the same assembly of the IGuyWire, so, in my application, I will have a reference only to the assembly containing the IGuyWire and the ApplicationConfiguration and, the Global.asax for example, will look like:

private static IGuyWire guywire;

void Application_Start(object sender, EventArgs e)
{
guywire = ApplicationConfiguration.GetGuyWire();
guywire.Wire();
}

void Application_End(object sender, EventArgs e)
{
guywire.Dewire();
}

Doing so my application does not need a strongly reference neither the IoC nor any other concrete implementations of my interfaces.

How use the GuyWire

Some other pieces of the definition:

When steel cable is used, the guys are divided by insulators into multiple sections…

Does it match with something ? Yes it does. We have a web-application a wcf-service and various tests projects… our application is composed by different layers, each layer has its way to be wired and we can re-use the same wiring in different areas. As result of this concept I have an abstract implementation for Castle.Windsor:

namespace YourCompany.YourPrjCodeName.Wiring.Castle
{
public abstract class AbstractGuyWire : IGuyWire
{
protected WindsorContainer Container;

public void Wire()
{
if (Container != null)
{
Dewire();
}

Container = new WindsorContainer();
foreach (var guyWire in GuyWires)
{
guyWire.Wire();
}
}

public void Dewire()
{
if (Container != null)
{
Container.Dispose();
}
Container = null;
}

protected abstract IEnumerable<IGuyWire> GuyWires { get; }
}
}

The concrete class for the web-application is:

public class GuyWire : AbstractGuyWire
{
#region Overrides of AbstractGuyWire

protected override IEnumerable<IGuyWire> GuyWires
{
get
{
yield return new ServiceLocatorGuyWire(Container);
yield return new NhWebSessionManagementGuyWire(Container);
yield return new PersistenceGuyWire(Container);
yield return new ModelsGuyWire(Container);
}
}

#endregion
}

and for the wcf-service (to know where I’m using the ApplicationConfiguration class have a look to this post) :

public class ExternalServicesGuyWire : AbstractGuyWire
{
#region Overrides of AbstractGuyWire

protected override IEnumerable<IGuyWire> GuyWires
{
get
{
yield return new ServiceLocatorGuyWire(Container);
yield return new NhWebSessionManagementGuyWire(Container);
yield return new PersistenceGuyWire(Container);
yield return new WcfServicesGuyWire(Container);
}
}

#endregion
}

in each test-suite you can re-use same GuyWires depending on which layer you are testing and/or the type of the test (integration test or not).

P.S. another pending task was done!! thanks to be patient.

02 November 2009

Validation Abstraction: Custom

If you have read this post you know I’m having some psychological problem at work: multi-personality.

My dear friend Fabio-NHV said me: hey man! I have a very good OSS validation framework strongly recommended if you are validating entities you are using with NHibernate.

And I said: Cool!! but your framework is only an option for me… soon or later I’ll use something else and, btw, I need to mix the validation done by your framework with my BL and/or UI validation.

The IEntityValidator

The IEntityValidator is part of uNhAddIns because José asked me how I’m abstracting the validation stuff from my application, during the implementation of the ChinookMediamanager example (the same happened with the IGuyWire and, a year ago, with the CpBT and Gustavo).

public interface IEntityValidator
{
bool IsValid(object entityInstance);
IList<IInvalidValueInfo> Validate(object entityInstance);
IList<IInvalidValueInfo> Validate<T, TP>(T entityInstance, Expression<Func<T, TP>> property) where T : class;
IList<IInvalidValueInfo> Validate(object entityInstance, string propertyName);
}
public interface IInvalidValueInfo
{
Type EntityType { get; }
string PropertyName { get; }
string Message { get; }
}

any good validation-framework should give me the way to implement an adapter for, at least, these methods.

The implementation for NHibernate.Validator

We having an implementation of IEntityValidator in uNhAddIns… by the way, in an application in production, I’m using a more simple implementation:

public class NhVEntityValidator : IEntityValidator
{
private readonly ValidatorEngine validatorEngine;

public NhVEntityValidator(ValidatorEngine validatorEngine)
{
this.validatorEngine = validatorEngine;
}

#region Implementation of IEntityValidator

public bool IsValid(object entityInstance)
{
return validatorEngine.IsValid(entityInstance);
}

public IList<IInvalidValueInfo> Validate(object entityInstance)
{
InvalidValue[] iv = validatorEngine.Validate(entityInstance);
return
new
List<IInvalidValueInfo>(
from invalidValue in iv
select (IInvalidValueInfo) new InvalidValueInfo(invalidValue));
}

#endregion
}

public class InvalidValueInfo : IInvalidValueInfo
{
private readonly InvalidValue iv;

public InvalidValueInfo(InvalidValue iv)
{
this.iv = iv;
}

#region Implementation of IInvalidValueInfo

public Type EntityType
{
get { return iv.EntityType; }
}

public string PropertyName
{
get { return iv.PropertyName; }
}

public string Message
{
get { return iv.Message; }
}

#endregion
}

The Usage
As you can imagine the usage is simple. Where you need the IEntityValidator you must inject it:
public UsuarioParticularNuevoService(
    IDaoFactory factory,
IUserSessionContext context,
IMailSender mailSender,
IMailMaker mailMaker,
IEntityValidator entityValidator)

and then simply use it

public IInvalidValueInfo[] Register(UsuarioNuevoInfo usuarioInfo)
{
var usuario = GetUsuario(usuarioInfo);

AddPais(usuario);
AddDireccion(usuario, usuarioInfo);
AddTelefono(usuario, usuarioInfo);
AddNewsletter(usuario, usuarioInfo);
AddNegocio(usuario);

var errors = validator.Validate(usuario);

if (errors != null && errors.Count > 0)
return errors.ToArray();

usuarioDao.SaveOrUpdate(usuario);
mailSender.Send(GetMailMaker(usuarioInfo, usuario).Make());
return new IInvalidValueInfo[0];
}

The chunk, of the IoC’s configuration (in this case Castle.Windsor), in my dear IGuyWire look like:

ValidatorEngine validatorEngine = ConfigureNHibernateValidatorEngine();

container.Register(Component.For<ValidatorEngine>().Instance(validatorEngine));
container.Register(Component.For<ISharedEngineProvider>().ImplementedBy<SharedEngineProvider>());
NHibernate.Validator.Cfg.Environment.SharedEngineProvider =
container.Resolve<ISharedEngineProvider>();
container.Register(Component.For<IEntityValidator>().ImplementedBy<NhVEntityValidator>());

Options

In uNhAddIns you can find two more options, for the IEntityValidator, implemented for ValidationApplicationBlock and for DataAnnotation (thanks to José Romaniello for his implementation).

17 September 2009

Configure SessionFactory Providers

This is about a pending task from long time ago… sorry for those waiting for it.

In the AOP example of CpBT you probably saw a class named SessionFactoryProvider; that class was wrote before CpBT and it can be used in others Contexts (ICurrentSessionContext).

ISessionFactoryProvider

The ISessionFactoryProvider is the contract for the implementation responsible for providing NHibernate’s sessionFactory/ies (big fantasy, no?). ISessionFactoryProvider implements IEnumerable<ISessionFactory> and its more important method is:

ISessionFactory GetFactory(string factoryId);

The parameter factoryId is the name you gave to the session-factory configuration:

<hibernate-configuration  xmlns="urn:nhibernate-configuration-2.2">
<
session-factory name="Domain_A">

The parameter factoryId, in this case, should be “Domain_A”.

In uNhAddIns there are two implementations: SessionFactoryProvider and MultiSessionFactoryProvider.

IConfigurationProvider

Both implementations, SessionFactoryProvider and MultiSessionFactoryProvider, have a dependency to an implementation of IConfigurationProvider. The responsibility of an IConfigurationProvider is: provide the set of configured NHibernate’s configurations (again big fantasy).

The contract is:

public interface IConfigurationProvider
{
IEnumerable<Configuration> Configure();
event EventHandler<ConfiguringEventArgs> BeforeConfigure;
event EventHandler<ConfigurationEventArgs> AfterConfigure;
}

In the implementation the BeforeConfigure event should be fired just before call configuration.Configure() of each configuration. You can use the event, for example to use the new NHibernate fluent configuration, or to change some property by code, or to set the ByteCodeProvider, or to use the Fluent-NHibernate configuration way, and so on.

The AfterConfigure event should be fired just after call configuration.Configure() of each configuration. You can use the event to add mappings, create the schema, or integrate it with NHibernate.Validator, or anything else you can do after have a configured NHibernate configuration.

The implementation of Configure method should return instances of NHibernate’s configurations ready to call the BuildSessionFactory method.

In uNhAddIns there are two implementations: DefaultSessionFactoryConfigurationProvider and DefaultMultiFactoryConfigurationProvider.

DefaultSessionFactoryConfigurationProvider

Nothing special to say; basically I can resume its behavior as:

var cfg = new Configuration();
cfg.Configure();

DefaultMultiFactoryConfigurationProvider

For multiple session factories what we need are the names of nhibernate’s config files. The configuration is through appSettings:

<configuration>
<
appSettings>
<
add key="nhfactory.WhatEverYouWant" value="AppApersistence.cfg.xml" />
<
add key="nhfactory.TheOther.NH.configFileName" value="AppBpersistence.cfg.xml" />

As you can see there is only a constant part, the “nhfactory”. The DefaultMultiFactoryConfigurationProvider will iterate all settings looking for those have the key starting with “nhfactory” (what follow is important only for you). The value is the name of the file with each NHibernate configuration. As said above what will be important is the session-factory’s name you will specify inside each configuration.

Custom configuration provider

Obviously you can implement your own configuration provider and use it to inject the behavior to a ISessionFactoryProvider (no matter if you will inject it manually or using a DI framework). You can start your own implementation from scratch or inheriting from AbstractConfigurationProvider or inheriting from one of defaults. An example may look as:

public class MyConfigurationProvider : DefaultMultiFactoryConfigurationProvider
{
public MyConfigurationProvider()
{
AfterConfigure += ConfigureCache;
}

private static void ConfigureCache(object sender, ConfigurationEventArgs e)
{
e.Configuration.QueryCache().ResolveRegion("SearchStatistic")
.Using<TolerantQueryCache>().AlwaysTolerant();
}
}

Configuring your DAOs/Repository for multiple DB

This is the real target of this post. In this example I will show an example using Castle.Windsor.

The start point is that you have, at least, two sessions factories configurations in two files (each one will look as an hibernate.cfg.xml you saw in many examples).

The first

    <session-factory name="Domain_A">

and the second

    <session-factory name="Domain_B">

The container configuration through XML should look like

 <facilities>
<
facility id="factorysupport"
type="Castle.Facilities.FactorySupport.FactorySupportFacility, Castle.MicroKernel" />
</
facilities>

<
component id="sessionFactoryProvider"
service="uNhAddIns.SessionEasier.ISessionFactoryProvider, uNhAddIns"
type="uNhAddIns.SessionEasier.MultiSessionFactoryProvider, uNhAddIns"/>

<
component id="domain_a.sessionFactory"
type="NHibernate.ISessionFactory, NHibernate"
factoryId="sessionFactoryProvider"
factoryCreate="GetFactory">
<
parameters>
<
factoryId>Domain_A</factoryId>
</
parameters>
</
component>

<
component id="domain_b.sessionFactory"
type="NHibernate.ISessionFactory, NHibernate"
factoryId="sessionFactoryProvider"
factoryCreate="GetFactory">
<
parameters>
<
factoryId>Domain_B</factoryId>
</
parameters>
</
component>

<
component id="domain_a.dao.AnEntity"
service='MyCompany.Data.IDao`1[[MyCompany.AnEntity, MyCompany]], MyCompany.Data'
type='MyCompany.Data.Nh.EntityDao`1[[MyCompany.AnEntity, MyCompany]], MyCompany.Data.Nh'>
<
parameters>
<
factory>${domain_a.sessionFactory}</factory>
</
parameters>
</
component>

<
component id="domain_a.dao.AnotherEntity"
service='MyCompany.Data.IDao`1[[MyCompany.AnotherEntity, MyCompany]], MyCompany.Data'
type='MyCompany.Data.Nh.EntityDao`1[[MyCompany.AnotherEntity, MyCompany]], MyCompany.Data.Nh'>
<
parameters>
<
factory>${domain_b.sessionFactory}</factory>
</
parameters>
</
component>

The are two DAOs each one pointing to a different session factory.

If you prefer the configuration by code it should look as:

private const string Domain_A = "Domain_A";
private const string Domain_B = "Domain_B";
private const string SessionFactoryProviderComponentKey = "sessionFactoryProvider";

...

public void ConfigurePersistence()
{
container = new WindsorContainer();
container.AddFacility<FactorySupportFacility>();

container.Register(Component.For<ISessionFactoryProvider>()
.Named(SessionFactoryProviderComponentKey)
.ImplementedBy<MultiSessionFactoryProvider>());

RegisterSessionFactoryFor(Domain_A);
RegisterSessionFactoryFor(Domain_B);

RegisterEntityDao<AnEntity>(Domain_A);
RegisterEntityDao<AnotherEntity>(Domain_B);
}

private void RegisterSessionFactoryFor(string sessionFactoryName)
{
container.Register(
Component.For<ISessionFactory>()
.Named(GetSessionFactoryProviderKey(sessionFactoryName))
.Configuration(Attrib.ForName("factoryId").Eq(SessionFactoryProviderComponentKey),
Attrib.ForName("factoryCreate").Eq("GetFactory"))
.Parameters(Parameter.ForKey("factoryId").Eq(sessionFactoryName)));
}

private void RegisterEntityDao<T>(string sessionFactoryName) where T : class, IGenericEntity<int>
{
container.Register(
Component.For<IDao<T>>().ImplementedBy<EntityDao<T>>()
.Parameters(
Parameter.ForKey("factory")
.Eq("${" + GetSessionFactoryProviderKey(sessionFactoryName) + "}")));
}

private static string GetSessionFactoryProviderKey(string sessionFactoryName)
{
return sessionFactoryName + ".sessionFactory";
}

Acknowledgments

Special thanks to those customers allow me to share the knowledge they paid.

04 August 2009

WPF project with NHibernate: Chinook Media Manager

Well… The work over uNhAddIns.WPF (announced here a month ago) is pretty done.

uNhAddIns.WPF is using some advanced feature of NHibernate and uNhAddIns as, for example, the injection of ICollectionTypeFactory to have Observable collections created directly by NHibernate.

José Romaniello has begun a new example creating a full functional application named Chinook Media Manager using :

  • WPF
  • NHibernate 2.1.0GA + NHibernate.Linq
  • uNhAddIns + uNhAddIns.WPF (with CpBT)
  • IoC + AOP by Castle
  • Chinook as example DB

In the project you will see how easy, and clear, is create a Desktop application using the frameworks mentioned above.

A little example:

public class Artist : Entity
{
public virtual string Name { get; set; }
}

will become IEditableObject implementing INotifyPropertyChanged without touch the real implementation.

A class like this:

public class Album : Entity, IAlbum
{
public virtual Artist Artist { get; set; }
public virtual string Title { get; set; }

public virtual IList<Track> Tracks { get; private set; }

public virtual void AddTrack(Track track)
{
track.Album = this;
Tracks.Add(track);
}

public Album()
{
Tracks = new List<Track>();
}
}

that has this mapping

<class name="Album">
<
id name="Id" column="AlbumId">
<
generator class="hilo"/>
</
id>

<
property name="Title" />
<
many-to-one name="Artist" class="Artist" column="ArtistId" />
<
bag name="Tracks" inverse="true" cascade="all">
<
key column="AlbumId" />
<
one-to-many class="Track" />
</
bag>
</
class>

will have the collection Traks implementing INotifyCollectionChanged.

Do you remember this post… well here the repository look as:

public interface IRepository<T> : IQueryable<T>
{
T Get(object id);
T Load(object id);
T MakePersistent(T entity);
void MakeTransient(T entity);
}

The first post of the series is on the cloud, follow it !

Please start downloading the example and feel free to send us your opinions, advise and so on in uNhAddIns mailing list.

Happy NHibernating even with WPF!

02 July 2009

Evolution of : Less than “Few” is GoF

Do you remember my first blog-post ?

Well… I’m something worried because somebody can take a that concept and improve its insanity.

Perhaps was insane but not so much...

24 May 2009

NHibernate IoC integration

Do you remember this post ?

As you can see you can use Dependency Injection even for entities, but what about all others classes needed by NHibernate ?

Can you inject something in a custom Dialect or in a custom UserType or UserCollectionType or Listener and all others extensions points ?

Sure you can ;)

NHibernate 2.1.0Alpha3, the fresh released today, has IObjectsFactory. As the ProxyFactoryFactory, the ReflectionOptimizer even the ObjectsFactory is a responsibility of the ByteCodeProvider.

To be short… an implementation of a IUserType now can look like this:

public class InjectableStringUserType : IUserType
{
private readonly IDelimiter delimiter;

public InjectableStringUserType(IDelimiter delimiter)
{
this.delimiter = delimiter;
}

The implementation of IPostInsertEventListener now can look like this:

public class YourPostInsertListener : IPostInsertEventListener
{
private readonly IPersistentAuditor auditor;

public YourPostInsertListener(IPersistentAuditor auditor)
{
this.auditor = auditor;
}

public void OnPostInsert(PostInsertEvent @event)

If you want use Dependency-Injection for both entities and all others NH stuff, in uNhAddIns you can find two full implementation for Castle and Spring.

Enjoy NHibernate injectability.

P.S. Part of it (tests), was a live implementation before start the Alt.NET VAN today.

07 January 2009

Aspect Conversation-per-BusinessTransaction

Part I : Conversation-per-Business-Transaction
Part II : Implementing Conversation per Business Transaction
Part III (without AOP) : Using Conversation per Business Transaction

Introduction

For this post I’ll use the same example of the Part III but using a real IoC framework (Castle Windsor). To abstract “aspect” the conversation stuff, from its implementation, I will use some custom Attribute defined in uNhAddIns.Adapters assembly. As you can see, downloading the example, there are few classes changed from the previous example, that are the more simple, and less intrusive, implementation of the FamilyCrudModel and, obviously, the implementation of ServiceLocatorProvider.

Important

The implementation of “Aspect Conversation-per-BusinessTransaction” presented here is only one of the possible implementations. Gustavo Ringel (blog link not available so far) are working in a real-world example using Conversation-per-BusinessTransaction pattern in a Win-Form application with its implementation of uNhAddIns (the example is available here).

“Model” implementation comparison

The new FamilyCrudModel complete implementation is:
[PersistenceConversational]
public class FamilyCrudModel<TAnimal> : IFamilyCrudModel<TAnimal> where TAnimal : Animal
{
private readonly IAnimalReadOnlyDao<TAnimal> animalDao;
private readonly IFamilyDao<TAnimal> familyDao;

public FamilyCrudModel(IDaoFactory factory)
{
animalDao = factory.GetDao<IAnimalReadOnlyDao<TAnimal>>();
familyDao = factory.GetDao<IFamilyDao<TAnimal>>();
}

#region Implementation of IFamilyCrudModel<TAnimal>

[PersistenceConversation]
public IList<TAnimal> GetExistingComponentsList()
{
return animalDao.GetAll();
}

[PersistenceConversation]
public IList<Family<TAnimal>> GetEntirelyList()
{
return familyDao.GetAll();
}

[PersistenceConversation]
public Family<TAnimal> GetIfAvailable(int id)
{
return familyDao.Get(id);
}

[PersistenceConversation]
public Family<TAnimal> Save(Family<TAnimal> entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
return familyDao.MakePersistent(entity);
}

[PersistenceConversation]
public void Delete(Family<TAnimal> entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
familyDao.MakeTransient(entity);
}

[PersistenceConversation(ConversationEndMode = EndMode.End)]
public void AcceptAll() { }

[PersistenceConversation(ConversationEndMode = EndMode.Abort)]
public void CancelAll() { }

#endregion
}
Differences, from the previous implementation are:
  1. don’t need to inherits from any kind of base class.
  2. the constructor injection is more simple
  3. the implementation of each method don’t have boiled code
  4. the class and each persistent-method are marked with a custom attribute
I can avoid the point (4) depending on the AOP framework features, using Castle, for example, I can inject the behavior using XML or Fluent-Interface-Configuration.
The point(3) is, for example, this comparison:
ImplComparison
From the point of view of Conversation-per-Business-Transaction usage that it’s all.

A more deep view

Behind the AOP I’m using, in this example, uNhAddIns.CastleAdapters. For who are familiar with Castle, the CastleAdapters assembly contains:
  • The TransactionProtectionWrapper and its factory; it is a ISession wrapper to ensure the transaction usage for certain ISession methods. The wrapper is used in all session-handlers implementations available in uNhAddIns (a NoWrappedSessionWrapper implementation is available in uNhAddIns core).
  • The AutomaticConversationManagement Castle-Windsor-Facility.
  • uNhAddIns-PersistenceConversation-nh-default.config file to use it as an include in the Windsor configuration, if you want use XML configuration.
If you want use Fluent-Castle-configuration a possible implementation is:
container.AddFacility<PersistenceConversationFacility>();
var sfp = new SessionFactoryProvider();
sfp.AfterConfigure += ((sender, e) => new SchemaExport(e.Configuration).Create(false, true));
container.Register(Component.For<ISessionFactoryProvider>().Instance(sfp));
container.Register(Component.For<ISessionWrapper>().ImplementedBy<SessionWrapper>());
container.Register(Component.For<IConversationFactory>().ImplementedBy<DefaultConversationFactory>());
container.Register(Component.For<IConversationsContainerAccessor>().ImplementedBy<NhConversationsContainerAccessor>());
Note that the class SessionFactoryProvider is the implementation for one-db application and I’m explicit instancing it only because I’m using the AfterConfigure event to create the DB (in production you don’t need to do it).
For who are not familiar with ICurrentSessionContext NHibernate's feature is important to remember that it need a specific NHibernate configuration property:
<property name="current_session_context_class">
uNhAddIns.SessionEasier.Conversations.ThreadLocalConversationalSessionContext, uNhAddIns
</property>
If you want download the example of this post, as usual, the code is available here.


kick it on DotNetKicks.com


26 November 2008

Entities behavior injection

If you are working with NH you know that NH likes POCOs and you must have a default constructor without parameters. Starting from today that is the past.

The domain

image

The implementation of Invoice is:

public class Invoice : IInvoice
{
private readonly IInvoiceTotalCalculator calculator;

public Invoice(IInvoiceTotalCalculator calculator)
{
this.calculator = calculator;
Items = new List<InvoiceItem>();
}

#region IInvoice Members

public string Description { get; set; }
public decimal Tax { get; set; }
public IList<InvoiceItem> Items { get; set; }

public decimal Total
{
get { return calculator.GetTotal(this); }
}

public InvoiceItem AddItem(Product product, int quantity)
{
var result = new InvoiceItem(product, quantity);
Items.Add(result);
return result;
}

#endregion
}

Are you observing something strange ?


  • There is not a property for the Id
  • There is not a default constructor without parameter

The Invoice entity are using an injectable behavior to calculate the total amount of the invoice; the implementation is not so important…

public class SumAndTaxTotalCalculator : IInvoiceTotalCalculator
{
#region Implementation of IInvoiceTotalCalculator

public decimal GetTotal(IInvoice invoice)
{
decimal result = invoice.Tax;
foreach (InvoiceItem item in invoice.Items)
{
result += item.Product.Price * item.Quantity;
}
return result;
}

#endregion
}

The full mapping:

<class name="Invoice" proxy="IInvoice">
<
id type="guid">
<
generator class="guid"/>
</
id>
<
property name="Description"/>
<
property name="Tax"/>
<
list name="Items" cascade="all">
<
key column="InvoiceId"/>
<
list-index column="pos"/>
<
composite-element class="InvoiceItem">
<
many-to-one name="Product"/>
<
property name="Quantity"/>
</
composite-element>
</
list>
</
class>

<
class name="Product">
<
id name="Id" type="guid">
<
generator class="guid"/>
</
id>
<
property name="Description"/>
<
property name="Price"/>
</
class>

The Test

[Test]
public void CRUD()
{
Product p1;
Product p2;
using (ISession s = sessions.OpenSession())
{
using (ITransaction tx = s.BeginTransaction())
{
p1 = new Product {Description = "P1", Price = 10};
p2 = new Product {Description = "P2", Price = 20};
s.Save(p1);
s.Save(p2);
tx.Commit();
}
}

var invoice = DI.Container.Resolve<IInvoice>();
invoice.Tax = 1000;
invoice.AddItem(p1, 1);
invoice.AddItem(p2, 2);
Assert.That(invoice.Total, Is.EqualTo((decimal) (10 + 40 + 1000)));

object savedInvoice;
using (ISession s = sessions.OpenSession())
{
using (ITransaction tx = s.BeginTransaction())
{
savedInvoice = s.Save(invoice);
tx.Commit();
}
}

using (ISession s = sessions.OpenSession())
{
invoice = s.Get<Invoice>(savedInvoice);
Assert.That(invoice.Total, Is.EqualTo((decimal) (10 + 40 + 1000)));
}

using (ISession s = sessions.OpenSession())
{
invoice = (IInvoice) s.Load(typeof (Invoice), savedInvoice);
Assert.That(invoice.Total, Is.EqualTo((decimal) (10 + 40 + 1000)));
}

using (ISession s = sessions.OpenSession())
{
IList<IInvoice> l = s.CreateQuery("from Invoice").List<IInvoice>();
invoice = l[0];
Assert.That(invoice.Total, Is.EqualTo((decimal) (10 + 40 + 1000)));
}

using (ISession s = sessions.OpenSession())
{
using (ITransaction tx = s.BeginTransaction())
{
s.Delete("from Invoice");
s.Delete("from Product");
tx.Commit();
}
}
}

In the previous week I tried to pass the test without change NH’s code-base. The first result was that I found a bug in NH and probably in Hibernate3.2.6, the second result was that it is completely possible to use NH with “fat” entities, without default constructor and using an IoC framework to inject behavior to an entity. After that work I realize that some little “relax” are needed in NH-code-base (NH-1587,NH-1588,NH-1589).

How pass the test

A very simple solution, to use an IoC with NH, is write a custom implementation of IInterceptor and use the Instantiate method to create an entity instance using an IoC container. The problem with this solution is that you still need a default constructor and… well… you must use the same interceptor for all sessions.

Another possible solution, for NH2.1 (trunk), is the use of a custom <tuplizer> for EntityMode.POCO. Probably I will write another blog-post about it.

If you are using the ReflectionOptimizer (used by default) there is a simple short-cut: I can write a IBytecodeProvider implementation based on Castle.Windsor container. The BytecodeProvider is another injectable piece of NH, trough the NHibernate.Cfg.Environment, before create the configuration. The BytecodeProvider has two responsibility: provide the ProxyFactoryFactory and provide the ReflectionOptimizer.

public class BytecodeProvider : IBytecodeProvider
{
private readonly IWindsorContainer container;

public BytecodeProvider(IWindsorContainer container)
{
this.container = container;
}

#region IBytecodeProvider Members

public IReflectionOptimizer GetReflectionOptimizer(Type clazz, IGetter[] getters, ISetter[] setters)
{
return new ReflectionOptimizer(container, clazz, getters, setters);
}

public IProxyFactoryFactory ProxyFactoryFactory
{
get { return new ProxyFactoryFactory(); }
}

#endregion
}
In this case, obviously, the ProxyFactoryFactory class is NHibernate.ByteCode.Castle.ProxyFactoryFactory.

Now the ReflectionOptimizer (using the fresh NH’s trunk):

public class ReflectionOptimizer : NHibernate.Bytecode.Lightweight.ReflectionOptimizer
{
private readonly IWindsorContainer container;

public ReflectionOptimizer(IWindsorContainer container, Type mappedType, IGetter[] getters, ISetter[] setters)
: base(mappedType, getters, setters)
{
this.container = container;
}

public override object CreateInstance()
{
if (container.Kernel.HasComponent(mappedType))
{
return container.Resolve(mappedType);
}
else
{
return container.Kernel.HasComponent(mappedType.FullName)
? container.Resolve(mappedType.FullName)
: base.CreateInstance();
}
}

protected override void ThrowExceptionForNoDefaultCtor(Type type)
{
}
}

As last, a quick view to the configuration:

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<
session-factory name="EntitiesWithDI">
<
property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<
property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<
property name="connection.connection_string">
Data Source=localhost\SQLEXPRESS;Initial Catalog=BlogSpot;Integrated Security=True
</property>
</
session-factory>
</
hibernate-configuration>

As you can see the configuration is minimal and, in this case, I don’t need to configure the “proxyfactory.factory_class” property because I will inject the whole BytecodeProvider.

[TestFixtureSetUp]
public void TestFixtureSetUp()
{
ConfigureWindsorContainer();
Environment.BytecodeProvider = new BytecodeProvider(container);
cfg = new Configuration();
cfg.AddAssembly("EntitiesWithDI");
cfg.Configure();
cfg.Interceptor = new WindsorInterceptor(container);
new SchemaExport(cfg).Create(false, true);
sessions = (ISessionFactoryImplementor) cfg.BuildSessionFactory();
}

The BytecodeProvider injection is the line after the configuration of Windsor container.

The configuration of the container is very simple:

protected override void ConfigureWindsorContainer()
{
container.AddComponent<IInvoiceTotalCalculator, SumAndTaxTotalCalculator>();
container.AddComponentLifeStyle(typeof (Invoice).FullName,
typeof (IInvoice), typeof (Invoice), LifestyleType.Transient);
}

Conclusions


  • The default ctor without parameter constraint was removed.
  • Use an IoC to inject behavior to an entity is possible and easy.

NOTE: Even if is possible to write an entity without the Id, the feature is not fully supported.

Code available here.



kick it on DotNetKicks.com