johnllao

October 22, 2010

Manual NServiceBus Configuration

Filed under: Uncategorized — johnllao @ 5:12 pm

In my previous post I have shown a simple implementation of Publish / Subscribe messages using the NServiceBus. We may notice from the example provided that to run the Service Bus we executed configuration through a series of extesion methods supplied.

Bus = Configure.With().DefaultBuilder().BinarySerializer()
         .MsmqTransport().IsTransactional(true).PurgeOnStartup(false)
         .UnicastBus().ImpersonateSender(false).LoadMessageHandlers()
         .CreateBus()
         .Start();

I managed to explore more and look into how each extension methods are performing the configuration. Here is what I discovered.

Configure config = Configure.With();

// Setting the DefaultBuilder
IContainer container = new SpringObjectBuilder();
CommonObjectBuilder b = new CommonObjectBuilder { Container = container, Synchronized = SyncConfig.Synchronize };
config.Builder = b;
config.Configurer = b;
config.Configurer.ConfigureComponent<CommonObjectBuilder>(ComponentCallModelEnum.Singleton)
    .ConfigureProperty(c => c.Container, container);
SyncConfig.MarkConfigured();

// Setting the Serialization
config.Configurer.ConfigureComponent<SimpleMessageMapper>(ComponentCallModelEnum.Singleton);
config.Configurer.ConfigureComponent(typeof(MessageSerializer), ComponentCallModelEnum.Singleton);

// Setting MSMQ Transport
ConfigMsmqTransport transportCfg = new ConfigMsmqTransport();
transportCfg.Configure(config);
transportCfg.IsTransactional(true);
transportCfg.PurgeOnStartup(false);

// Setting the Unicast Bus
ConfigUnicastBus unicastCfg = new ConfigUnicastBus();
unicastCfg.Configure(config);
unicastCfg.ImpersonateSender(true);
unicastCfg.LoadMessageHandlers();

// Creating the Bus
IStartableBus startableBus = config.CreateBus();

// Staring the Bus
Bus = startableBus.Start();

Digging further into the details we can slice the MSMQ configuration using the following code.

IComponentConfig<MsmqTransport> transportCfg = config.Configurer.ConfigureComponent<MsmqTransport>(ComponentCallModelEnum.Singleton);
MsmqTransportConfig msmqTransportCfg = Configure.GetConfigSection<MsmqTransportConfig>();
if (msmqTransportCfg != null)
{
    transportCfg.ConfigureProperty(t => t.InputQueue, msmqTransportCfg.InputQueue);
    transportCfg.ConfigureProperty(t => t.NumberOfWorkerThreads, msmqTransportCfg.NumberOfWorkerThreads);
    transportCfg.ConfigureProperty(t => t.ErrorQueue, msmqTransportCfg.ErrorQueue);
    transportCfg.ConfigureProperty(t => t.MaxRetries, msmqTransportCfg.MaxRetries);
    transportCfg.ConfigureProperty(t => t.IsTransactional, true);
    transportCfg.ConfigureProperty(t => t.PurgeOnStartup, false);
}

The Unicast settings can be further broken into the following code

IComponentConfig<UnicastBus> unicastCfg = config.Configurer.ConfigureComponent<UnicastBus>(ComponentCallModelEnum.Singleton);
Type authType = Configure.TypesToScan.Where(t => typeof(IAuthorizeSubscriptions).IsAssignableFrom(t) && !t.IsInterface).FirstOrDefault();
if (authType != null)
    config.Configurer.ConfigureComponent(authType, ComponentCallModelEnum.Singleton);
Configure.TypesToScan.Where(t => typeof(IMessageModule).IsAssignableFrom(t) && !t.IsInterface).ToList().ForEach(
        type => config.Configurer.ConfigureComponent(type, ComponentCallModelEnum.Singleton)
    );
UnicastBusConfig unicastBusCfg = Configure.GetConfigSection<UnicastBusConfig>();
if (unicastBusCfg != null)
{
    Hashtable assembliesToEndpoints = new Hashtable();
    Configure.TypesToScan.Where(t => typeof(IMessage).IsAssignableFrom(t)).ToList().ForEach(
            t => assembliesToEndpoints[t.Assembly.GetName().Name] = string.Empty
        );

    foreach (MessageEndpointMapping mapping in unicastBusCfg.MessageEndpointMappings)
        assembliesToEndpoints[mapping.Messages] = mapping.Endpoint;

    unicastCfg.ConfigureProperty(ub => ub.DistributorControlAddress, unicastBusCfg.DistributorControlAddress);
    unicastCfg.ConfigureProperty(ub => ub.DistributorDataAddress, unicastBusCfg.DistributorDataAddress);
    unicastCfg.ConfigureProperty(ub => ub.ForwardReceivedMessagesTo, unicastBusCfg.ForwardReceivedMessagesTo);
    unicastCfg.ConfigureProperty(ub => ub.MessageOwners, assembliesToEndpoints);
    unicastCfg.ConfigureProperty(ub => ub.ImpersonateSender, true);

    List<Type> handlers = new List<Type>();

    foreach (Type t in Configure.TypesToScan)
        if (IsMessageHandler(t))
        {
            config.Configurer.ConfigureComponent(t, ComponentCallModelEnum.Singlecall);
            handlers.Add(t);
        }

    unicastCfg.ConfigureProperty(ub => ub.MessageHandlerTypes, handlers);
}

Helper methods I used in this example

/// <summary>
/// Returns true if the given type is a message handler.
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static bool IsMessageHandler(Type t)
{
    if (t.IsAbstract)
        return false;

    if (typeof(ISaga).IsAssignableFrom(t))
        return false;

    foreach (Type interfaceType in t.GetInterfaces())
    {
        Type messageType = GetMessageTypeFromMessageHandler(interfaceType);
        if (messageType != null)
            return true;
    }

    return false;
}

/// <summary>
/// Returns the message type handled by the given message handler type.
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static Type GetMessageTypeFromMessageHandler(Type t)
{
    if (t.IsGenericType)
    {
        Type[] args = t.GetGenericArguments();
        if (args.Length != 1)
            return null;

        if (!typeof(IMessage).IsAssignableFrom(args[0]))
            return null;

        Type handlerType = typeof(IMessageHandler<>).MakeGenericType(args[0]);
        if (handlerType.IsAssignableFrom(t))
            return args[0];
    }

    return null;
}
About these ads

1 Comment »

  1. […] Manual NServiceBus Configuration – Johnllao continues to explore the NServiceBus, this time he takes a peek at configuring the bus manually. […]

    Pingback by NServiceBus Weekly: #9 — October 27, 2010 @ 3:27 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Shocking Blue Green Theme. Create a free website or blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: