I recently had the chance to follow the Advanced Distributed Systems Design with SOA course with Udi Dahan in Brussels, a rejuvenating experience for various reasons : I had no real-world SOA or Messaging Bus experience, it helped me clear out some misunderstandings I had about DDD and also, although painful at first, Udi finger pointed all the bad habits & misconceptions I had accumulated over the years (I can still hear him squeaking “Northwind ! Northwind !“).
So here I am, entering the realm of SOA, EDA & DDD that might well be heaven on earth for both business people & software-makers, the place we all heard of but never saw. But let’s start slowly, and discover my first endeavor with NServiceBus, shall we?
For a good introduction on NServiceBus, I suggest you to read the post from Jan who has been doing research on the same aforementioned topics as well.
This post will focus on how well NServiceBus, NHibernate, FluentNHibernate & Castle Framework play together and how to make them fly in a DDD context. Ok, ok, enough talking, show me the code man !!!
To manage my NHibernate sessions (ISession), I like to use the Castle’s NHibernate Integration facility, as it gives me a nice abstraction in the form of the ISessionManager component:

Next to that, a little more than a month ago, the 1.0 version of FluentNHibernate was released, and it’s really neat for both NHibernate configuration & mappings. So, I like to use it as well:
Fluently.Configure(config)
.Database(MsSqlConfiguration.MsSql2008
.DefaultSchema("dbo")
.ConnectionString(c => c
.FromConnectionStringWithKey("Northwind"))
.QuerySubstitutions("true 1, false 0")
.DoNot.UseOuterJoin()
.ShowSql())
.Mappings(m => m
.FluentMappings.AddFromAssemblyOf<CatalogMap>()
.ExportTo(System.Environment.CurrentDirectory))
.BuildConfiguration();
One very nice thing about NServiceBus (and its Generic Host) is that it acknowledges from the start that our softwares have to operate in different environments and for that, it offers a very clean solution : Profiles.
Wrapping it all up, wouldn’t it be nice if I could use Castle‘s NHibernate Integration facility for useful components like ISessionManager (and others, more on that later), FluentNHibernate for configuration & mappings and take advantage of NServiceBus Profiles ? Hell yeah !!! Well, that’s actually quite easy & clean.
First, configure the NH facility in your config file:
<castle>
<facilities>
<facility id="nhibernate.facility" type="Castle.Facilities.NHibernateIntegration.NHibernateFacility, Castle.Facilities.NHibernateIntegration">
<factory id="nhibernate.factory"/>
</facility>
</facilities>
</castle>
Notice that the configuration for the factory is empty … indeed, we want to configure it fluently in the code.
Create a Profile Handler class (implements a IHandleProfile role interface) which simply registers an object into the container (NSB is container-agnostic) :
public class IntegrationProfileHandler : IHandleProfile<Integration>
{
public void ProfileActivated()
{
Configure.Instance.Configurer
.RegisterSingleton<IConfigurationContributor>(
new IntegrationNHibernateConfig());
}
}
… and finally, an implementation of the IConfigurationContributor interface … which is part of Castle‘s NHibernate Integration facility, and will be called before NH‘s SessionFactory is built in order to, well, contribute to the configuration.
public class IntegrationNHibernateConfig : IConfigurationContributor
{
public void Process(string name, Configuration config)
{
Fluently.Configure(config)
.Database(MsSqlConfiguration.MsSql2008
.DefaultSchema("dbo")
.ConnectionString(c => c
.FromConnectionStringWithKey("Northwind"))
.QuerySubstitutions("true 1, false 0")
.DoNot.UseOuterJoin()
.ShowSql())
.Mappings(m => m
.FluentMappings.AddFromAssemblyOf<CatalogMap>()
.ExportTo(System.Environment.CurrentDirectory))
.BuildConfiguration();
}
}
Ok, very nice … but I’m not done yet.
A nice concept that we want to use when querying in a true DDD fashion is the notion of Fetching Strategy (read more about it here & there). We need Fetching Strategies for a very simple reason:
Make sure that once we call into the Domain Model to perform a certain action, it has everything it needs to do its job, without causing lazy-loading to trigger and possibly N+1 select problems.
For that matter, I define a simple interface IFetchingStrategy (IEntityRole is just a marker interface):
public interface IFetchingStrategy<TEntityRole>
where TEntityRole : IEntityRole
{
string[] FetchList { get; }
}
… that I can then implement to define a fetching strategy per entity role:
public interface IRegisterProductInCatalog : IEntityRole
{
void RegisterProduct(string category,
string productName, string productDescription);
}
public class RegisterProductInCatalogStrategy : IFetchingStrategy<IRegisterProductInCatalog>
{
public string[] FetchList
{
get { return new[] { "Categories.Products" }; }
}
}
Now, it would be nice if I could get an easy access to those fetching strategies … well, that’s what you use an IoC container for
Here is the configuration of Castle’s Windsor container in NServiceBus endpoint’s configuration class:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization
{
public void Init()
{
var container = new WindsorContainer(new XmlInterpreter());
Configure.With()
.CastleWindsorBuilder(container)
.XmlSerializer();
container.Register(
AllTypes
.Of(typeof(IFetchingStrategy<>))
.Pick(Configure.TypesToScan)
.WithService.FirstInterface()
);
}
}
Fluent configuration for the Bus & the Container ! Woohoo, my head is turning !
Now, for the final part, the MessageHandler that makes use of all those cuties & with the help some little extension methods:
public class ProductManager : IHandleMessages<RegisterProductInCatalogRequest>
{
public virtual IBus Bus { get; set; }
public virtual ISessionManager SessionManager { get; set; }
public virtual IFetchingStrategy<IRegisterProductInCatalog> Strategy { get; set; }
public virtual void Handle(RegisterProductInCatalogRequest message)
{
using (var session = SessionManager.OpenSession())
{
var catalog =
session.For<Catalog>(message.CatalogId)
.Apply(Strategy)
.UniqueResult<IRegisterProductInCatalog>();
catalog.RegisterProduct(message.CategoryName,
message.ProductName,
message.ProductDescription);
}
}
}
I don’t know you, but that’s the kind of code that makes me happy (like a hippo).
Comments, feedback, suggestions are all welcome !