Wednesday, December 15, 2010

VDUNY Slidedeck: Introduction to NServiceBus

Here are the slides I delivered for the VDUNY group, it was a lot of fun and thanks again to all who showed up despite the bad weather.

Thursday, December 9, 2010

VDUNY Intro to NServiceBus Talk December 14th

I'll be giving an introduction to NSB for the Visual Developers of Upstate New York this month. You can find the details here: http://www.vduny.org/futmeet.asp

Sunday, November 28, 2010

New Series Announcement: NServiceBus 3.0

My apologies for the long hiatus, I was trying to figure out where to go next after doing the "Getting Started" series. I think I've pretty much gotten through the basics with NServiceBus. After posting on SO and not getting an answer as to what the new features will be in NSB 3.0, I decided I'll take the time to dissect it myself. I guess I had forgotten this is a very DIY framework so I'll do my best to "discover" the new features. So my next post will be the first in a series about NSB 3. See you soon!

Sunday, November 7, 2010

Getting Started with NServiceBus Part 9: Horizontal Scaling with the Distributor

A single thread NServiceBus instance can handle quite of bit of messages. We're talking around 30 messages/second or roughly 2.5 million messages a day. It may be the case that if you need more throughput you can ramp up the number of threads NSB uses. If you would rather not do that and keep it single threaded but still scale out you can do so with the built-in Distributor process.  Check out the first slide at the end of the post for the general message flow.

Fundamentally the Distributor is comprised of at least 3 processes. The first is the Distributor process itself which holds onto the entire set of work that the Workers will operate upon. The reason the Distributor holds the work is so that if one of the Workers goes down, it can shift that work over to the other Worker(s). The other 2 processes are Worker processes that do the actual work and also report their status back to the Distributor. At its core the Distributor receives work from some other process and then dishes out the work based on the current status of the Workers.

The workflow is controlled by a few internal queues to the Distributor itself. The Distributor has a Control, Storage, and Data(work) queue. The Control queue is where the Workers will put their Ready messages. The Storage queue keeps track of the addresses of the Workers and is used to determine which Worker is available next for work. The Data queue keeps the set of work. All of these settings are kept in the app.config of the Distributor process.

    
    
    
    
    
    
    
    
    
    
     
    
    
    
    
Once the Distributor is configured we must tell each Worker how to communicate with the Distributor.

    
    
  
Once we have everything configured the workflow is a multi-step process that goes like this:

  1. A Worker starts up and places a Ready message on the Distributor's Control queue.  This message is read and pushes a message on the Storage queue to indicate that we have an available Worker.
  2. Step 1 is repeated for all Worker that start up.
  3. A Client issuing the work sends a message to the Data queue.
  4. The message is read from the Data queue and the Distributor pops the next available Worker from the Storage queue
  5. The message is then forwarded to the Worker and the Worker handles the message.
  6. Once the Worker is done it sends a Ready message back to the Control queue to signify that it is ready for more work.
  7. If the first Worker is still working as more work comes in, the next available Worker gets the next message.  If all Workers are busy, then the Distributor queues up the messages in the Data queue.
Check out the second slide in the deck at the end of the post to have a visual of the flow.

The Worker message Handlers are written just like any old NSB handler.  The only other missing component is that you will need to send the Distributor some work.  When you fire up all the processes you can send messages to the Distributor and watch the work load balance.  Since the Distributor holds all the work you may want to make the Distributor highly available and put it into a cluster.

I have a full working sample on github: https://github.com/afyles/Blog/tree/master/NServiceBusExplorer/. All you need to do is fire up the Distributor and the 2 Workers in the Workers folder under the Source directory.

Thursday, November 4, 2010

Powershell: Reading Messages from MSMQ

I'm throwing this out there since I couldn't find anything good online. We have admins that need to quickly look at messages in queues and the built-in tooling just isn't pretty to look at. Slap this PS code into a script file and you should be ready to rock!

param([string]$qname)

if ( [System.String]::IsNullOrEmpty($qname) )
{
    write-host "You must provide a queue name"
    exit
}

[Reflection.Assembly]::LoadWithPartialName("System.Messaging") | out-null

$q = new-object System.Messaging.MessageQueue($qname)

$msgs = $q.GetAllMessages()

foreach ( $msg in $msgs )
{
    $msg.BodyStream.Position = 0
    $sr = new-object System.IO.StreamReader( $msg.BodyStream )
    $sr.ReadToEnd()
    $input = read-host -prompt "Enter n for the next message, q to quit"
    
    if ( $input -eq "q" )
    {
        exit
    }
}

Monday, November 1, 2010

Getting Started with NServiceBus Part 8: Message Versioning

So now you've gone live with your first system based on NSB. Time goes by and you have a new requirement to add some data to a published event. How will we provide backwards compatibility? How will we upgrade? What if legacy subscribers don't care about the new information? Luckily for us NSB handles this given we modeled our messages as interfaces, giving us an inheritance structure we can use to our advantage. This article will how how easily this can be done.

Let's begin given our current message:
public interface IProductUpdatedEvent : IProductChangedEvent
    {
    }
    public interface IProductChangedEvent : IEvent
    {
        Int32 ProductNumber { get; set; }
        String Name { get; set; }
        String Description { get; set; }       
    }
Now let's say we want to add a new field to our event. We create the new event in a different namespace so we can use the same interface name and add our new field after we implement the old interface:
public interface IProductUpdatedEvent : Messages.IProductUpdatedEvent
    {
        Int32 DepartmentNumber { get; set; }
    }
So now we have two distinct messages that have different data sets. This means our legacy clients can continue to receive the legacy message and our new clients can receive the new message. Here is an example of a handler pointing to the new message type:
public class EventMessageHandler : IMessageHandler<Messages.New.IProductUpdatedEvent>
    {
        private static ILog log = LogManager.GetLogger(typeof(EventMessageHandler));

        public void Handle(Messages.New.IProductUpdatedEvent message)
        {
            log.Debug(String.Format("{0} Event Received for Product {1}: {2} : {3}", message.GetType().UnderlyingSystemType.Name, message.ProductNumber, message.Name, message.DepartmentNumber));
        }
    }
The rest of our Subscribers remain the same. All that is left is to update the Publisher to publish the new event. In the example code there is a Windows Forms app(UI) that pushes all events to a common Publisher endpoint. See the Documentation directory for a diagram. In the example all we have to do is add the new field and publish the new event.
Messages.New.IProductUpdatedEvent pu = new Messages.New.ProductUpdatedMessage
            {
                ProductNumber = Int32.Parse(textBoxUpdateID.Text),
                Description = textBoxUpdateDesc.Text,
                Name = textBoxUpdateName.Text,
                EventId = Guid.NewGuid(),
                Time = DateTime.Now,                
                DepartmentNumber = 10
            };

            FireEvent(pu);
If you pull down the sample and look in the PubSub directory, fire up the BusServer, UI, Subscriber1, and Subscriber3 projects. From the UI simple type in second group box and hit the "Update" button. This will send the new message to the "BusServer" Publisher endpoint which will do the actual Bus.Publish(). From there you will see Subscriber1 receive the legacy event and Subscriber3 receive the new event with the new data.

NSB allows us to gracefully support new message types and uphold backwards compatibility. We were able to introduce new data and rely upon inheritance to handle the rest. Full code can be found here: http://github.com/afyles/Blog/tree/master/NServiceBusExplorer/

Monday, October 18, 2010

Getting Started with NServiceBus Part 7: Custom Performance Counters

Out of the box, NSB gives you a performance counter that tells you hold old the oldest message in the queue is. This gives you an idea as to how long messages are sitting in the queue. We decided to add a couple of new counters to tell us some other things about our performance.

The first one is what is the average processing time for a message? This is the time from when the message was pulled off the queue until the time the transaction completes. What this won't give us is granularity in determining which message handlers are moving slowly. Since most installations will have only a single or small amount of message handlers, this should be good enough for us.

The second counter is how many failures do I have per second? This is important since NSB has built-in retry logic. We have no visibility to failures unless we look at the log as processing occurs or waiting until the message moves to the error queue. We wanted to see quickly if we were processing slowing due to a lot of errors.

To get this going we can create a new profile similar to the NServiceBus.PerformanceCounters profile in NSB. First we create some classes to represent out monitoring:
    public class Monitoring : IProfile { }
    public class InstallMonitoring : IProfile { }
We have to have 2 profiles, one for running the counters and one for installing the counters. We'll cover the installation first. The first thing we need to do is remove the counters and reinstall them if they exist.
        public void ProfileActivated()
        {
            Logger.Debug("Starting installation of  monitoring");

            if (PerformanceCounterCategory.Exists(CategoryName))
            {
                Logger.Warn(String.Format("Category {0} already exists, going to delete it first", CategoryName));
                PerformanceCounterCategory.Delete(CategoryName);
            }

            CounterCreationDataCollection counterData = new CounterCreationDataCollection();

            counterData.AddRange(this.InstallAverageMessageProcessTimeCounter());
            counterData.AddRange(this.InstalledFailedMessageProcessingCounter());

            PerformanceCounterCategory.Create(CategoryName, "NServiceBus Monitoring", PerformanceCounterCategoryType.MultiInstance, counterData);

        }
Once we've ditched the counter we rebuild it by creating some counter data. I'll show one of the installs. To calculate the average time of something we need to do two things. We need to increment the time and also increment the basis of the event. The basis must be added after the average timer(you'll get an error if you don't).
        private CounterCreationDataCollection InstallAverageMessageProcessTimeCounter()
        {
            Logger.Debug("Starting installation of average process time monitoring");

            CounterCreationDataCollection counterData = new CounterCreationDataCollection();

            CounterCreationData avgTime = new CounterCreationData(AvgProcessTimeCounterName, 
                "Avg message processing time", 
                PerformanceCounterType.AverageTimer32);

            counterData.Add(avgTime);

            CounterCreationData avgBase = new CounterCreationData(AvgProcessTimeBaseCounterName, 
                "Avg message processing time base", 
                PerformanceCounterType.AverageBase);

            counterData.Add(avgBase);

            Logger.Debug("Installation of average processing time monitoring successful.");

            return counterData;
        }
Now that we have our counters installed, we need to create the profile to actual post to the counters. When your profile is activated, we'll tie into 2 key events in the NSB runtime, "StartedMessageProcessing" and "FinishedMessageProcessing". In doing so we can calculate the time that has elapsed and update our basis. We'll use a simple StopWatch to keep track of it all.
        private void MonitorAverageMessageProcessTime()
        {
            PerformanceCounter avgProcessTimeCounter = null;
            PerformanceCounter avgProcessTimeBaseCounter = null;
            Stopwatch watch = null;

            try
            {
                avgProcessTimeCounter = new PerformanceCounter(CategoryName, AvgProcessTimeCounterName, Program.EndpointId, false);
                avgProcessTimeBaseCounter = new PerformanceCounter(CategoryName, AvgProcessTimeBaseCounterName, Program.EndpointId, false);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException("NServiceBus monitoring is not set up correctly. Running this process with the flag NServiceBus.InstallMonitoring should fix the problem.", e);
            }

            GenericHost.ConfigurationComplete +=
                (o, e) =>
                {
                    ITransport transport = Configure.Instance.Builder.Build<ITransport>();
                    transport.StartedMessageProcessing += (s, ea) => { watch = Stopwatch.StartNew(); };
                    transport.FinishedMessageProcessing +=
                        (s, ea) =>
                        {
                            watch.Stop();
                            avgProcessTimeCounter.IncrementBy(watch.ElapsedTicks);
                            avgProcessTimeBaseCounter.Increment();
                        };
                };
        }
Please note that since we are posting to a counter for each message this will somewhat degrade the performance. All we have to do now is run our process once with the "InstallMonitoring" profile to install the counters and then again with the "Monitoring" profile to post to the counters. You must have the process running before you see anything in PerfMon. When you fire PerfMon up, you should see something like this:

Since we installed the counters as Multi-Instance you should see multiple entries for each process running.  I have a simple Request/Response sample that I used to test this out.  Once you get sample running you can send a bunch of messages and start to see some data:

Sweet!  Now we have some additional ways we can monitor NSB.  As always, code can be found here: http://github.com/afyles/Blog/tree/master/NServiceBusExplorer/  Take a look at the "Profiles" project and the "RequestResponse" projects.

Friday, October 8, 2010

Getting Started with NServiceBus Part 6: MVC Music Store Saga(Workflow)

Last time were able to wire up the OrderAccepted event and publish to a single Shipping Subscriber.  This time around we are going to cast our net wider and include a Billing Subscriber.  This Subscriber will handle looking up the payment instrument for the order and then authorize that payment.  This presents a problem for our Shipping Subscriber as we cannot ship the product until we know the customer can pay for it.

NSB handles this situation quite well by implementing Sagas or workflow.  With a Saga we can tell the Shipping Subscriber to wait for the payment authorization to complete before picking and shipping the order.  NSB handles this by allowing us to store the state of the workflow in persistent storage(Saga Persister).  Since this is handled for us, all we need to do is reconcile the state of the workflow and mark it complete when we are done.

Let us begin by introducing a new entity, PaymentInstrument.  The easiest thing to do is create the table in the local DB and update the model from there.
Next we'll create the message that the Shipping Subscriber will receive once the payment has been authorized or rejected.
    public interface IAuthorizePaymentEvent : IEvent
    {
        Int32 OrderId { get; set; }
        Boolean Authorized { get; set; }
    }
In this message we simply tie back to the Order and send a flag giving us the status of the authorization. To complete the Billing Subscriber we create a new project and configure the endpoint AsA_Server and point to our Publisher, the Music Store command handler input queue. We need to add another endpoint to the config since we will be sending the Shipping Subscriber the IAuthroizePaymentEvent message. The mappings are as follows:

    
      
      
      
    
  
All we have left is to complete the handler for the published IOrderAcceptedEvent. In this handler we'll look up the user name on the order and the total. Based on this information we'll grab the payment instrument for the user and do some simple validation. Upon completion we'll send a message over to the Shipping Subscriber so it can continue the workflow.
      public void Handle(IOrderAcceptedEvent message)
      {
            MusicStoreEntities storeDB = new MusicStoreEntities();

            var order = storeDB.Orders.Single(o => o.OrderId == message.OrderId);

            var paymentInstrument = storeDB.PaymentInstruments.Single(pi => pi.UserName == order.Username);

            var authorizedEvent = this.Bus.CreateInstance<IAuthorizePaymentEvent>(p => p.OrderId = order.OrderId);

            // authorize the card...
            if (order.Total < 100)
                authorizedEvent.Authorized = true;
            else
                authorizedEvent.Authorized = false;

            this.Bus.Send(authorizedEvent);

        }
    }
Now we have a Billing Subscriber that is authorizing payment instruments and sending messages to our Shipping Subscriber. Now we have to do the work to make the Shipping Subscriber wait for the authorization. Let's begin by defining the data or state that we'd like to keep track of. At a bare minimum we need to keep track of the OrderId, the status of the payment authorization, and the status of the order(have we picked all the product?). NSB will also impose a few extra fields upon us as we implement the IContainSagaData interface.
    public class ShippingSagaData : IContainSagaData
    {
        public virtual Guid Id{ get; set; }
        public virtual String OriginalMessageId { get; set; }
        public virtual String Originator { get; set; }
        public virtual Boolean PaymentAuthorized { get; set; }
        public virtual Int32 OrderId { get; set; }
        public virtual Boolean OrderPicked { get; set; }
    }
Note that all the properties are marked as virtual. NSB uses NHibernate to store the Saga so we must give NH access to our properties. If you run the code without this it will complain. When implementing a Saga in NSB, your Saga becomes the handler and distributor of many messages. NSB needs to know how to start the Saga, which messages to handle, and what kind of data to store. The class definition says it all:
public class ShippingSaga : Saga<ShippingSagaData>,
        IAmStartedByMessages<IOrderAcceptedEvent>,
        IHandleMessages<IAuthorizePaymentEvent>,
        IHandleMessages<IOrderPickedEvent>
There is a new message here that we didn't have before. We need to know when we have completed picking the product from our shelves so we've introduced the IOrderPickedEvent.
    public interface IOrderPickedEvent : IEvent
    {
        Int32 ShippingNoteId { get; set; }
        Int32 OrderId { get; set; }
    }
The first thing we have to do is tell NSB how to look up our Saga. In other works, what makes a Saga unique? In our case we link everything up by OrderId. To make sure everything is unique we map all the message OrderIds to the Saga data OrderId.
        public override void ConfigureHowToFindSaga()
        {
            base.ConfigureMapping<IOrderAcceptedEvent>(s => s.OrderId, e => e.OrderId);
            base.ConfigureMapping<IAuthorizePaymentEvent>(s => s.OrderId, e => e.OrderId);
            base.ConfigureMapping<IOrderPickedEvent>(s => s.OrderId, e => e.OrderId);
        }
All of this is based off of the Order being accepted so our Saga starts by handling that event. We'll default some Saga data and then kick of the picking process.
        public void Handle(IOrderAcceptedEvent message)
        {
            base.Data.PaymentAuthorized = false;
            base.Data.OrderId = message.OrderId;
            base.Bus.SendLocal<IPickOrderCommand>( p => p.OrderId = message.OrderId);
        }
The interesting thing here is the Bus.SendLocal() method. What this does is put a message on the current endpoint's queue. We send a message to ourselves to kick of the pick process. The handler for this was detailed last time as we checked our inventory positions for the product and created ship notes. While we are picking the product, the payment is being authorized. If the payment comes back unauthorized we'll simply restock the order. Once we have picked the order we can check to see if we can let the order out the door.
        public void Handle(IOrderPickedEvent message)
        {
            base.Data.OrderPicked = true;
            this.TryComplete();
        }

        private void TryComplete()
        {
            if (base.Data.OrderPicked && Data.PaymentAuthorized)
                MarkAsComplete();
        }
The MarkAsComplete() method tells the NSB infrastructure that this Saga is over and we can ditch the state. We also need to call the TryComplete() method if the authorization comes in:
        public void Handle(IAuthorizePaymentEvent message)
        {
            base.Data.PaymentAuthorized = message.Authorized;
            this.TryComplete();
        }
We've completed our Saga except for one part. Normally we would only wait for an payment instrument authorization for so long. In our Saga we can request a timeout. When a timeout is requested, a message is sent to another endpoint that watches the clock for us. When time is up, the external endpoint sends us a message back. In this example we aren't requesting a timeout which means we will wait forever for an authorization. Normally we wouldn't do this and we'd have to run the Timeout Manager process that comes with NSB. To keep it simple I left it out this time. We still have to implement the Timeout() method, and in our case we'll simply kill the Saga for a timeout.
        public override void Timeout(object state)
        {
            MarkAsComplete();
        }
We've come a long way, we now have a music store that accepts Orders durably, handles payment authorization, picks the product, and creates shipping notes for the shipping dock. As always, code can be found at github: http://github.com/afyles/Blog

Monday, October 4, 2010

Monitoring NServiceBus: Performance Counters Starting Point

We are starting to look at monitoring NServiceBus internally and we're starting with PerfMon in our test and cert environments. I've come up with short list of suggested counters to look at and thought I'd share then with everyone.  I'm also working on a set of custom counters for NSB that I'll be posting shortly on top of the one built in counter.

.NET CLR Exceptions(NServiceBus.Host)\# of Exceps Thrown / sec
     o This will tell you if the app is throwing tons of exceptions, this is important as NSB will retry under
exception scenarios and therefore you may be unaware that your app is blowing up

.NET CLR Memory(NServiceBus.Host)\# of Pinned Objects
     o The number of objects GC can't move back into memory(leak or locked up thread)

.NET CLR Memory(NServiceBus.Host)\% Time in GC
     o How long it takes to do a GC, this will tell us if our memory footprint is too big or out of control for some reason

Distributed Transaction Coordinator\Transactions/sec
     o How many transactions is DTC pumping out

MSMQ Queue(Computer Queues)\Messages in Queue
     o How many messages are in your NSB input queue

MSMQ Queue(info-dev11\private$\nservicebus_error)\Messages in Queue
     o How many messages are in the error queue

MSMQ Service\Incoming Messages/sec
     o Number of messages coming in, tells us if we are getting overloaded

MSMQ Service\Outgoing Messages/sec
     o Number of messages going out, are we sending messages fast enough

NServiceBus\*
     o Critical Time - how old is the oldest message in the queue? This tells us we are processing messages slowly

Friday, October 1, 2010

Enabling NServiceBus Performance Counters

First you must install the counters using the Runner.exe tool. The next thing you need to do is add the "NServiceBus.PerformanceCounters" profile to your install. Without this you will not see any instances in PerfMon.

Tuesday, September 21, 2010

Unit Testing NSB with VS2010, .NET 4.0, and MSTest

Unit testing NSB can be done without NUnit. For those of you using MSTest, you will have to download the latest trunk and compile NSB yourself to get this to work. Otherwise you will get a bunch of TypeAccessExceptions amongst others. The big difference on the trunk is that the Rhino Mocks reference has been pulled out which I think was causing the issue.

Sunday, September 19, 2010

Getting Started with NServiceBus Part 5: MVC Music Store Basic Pub/Sub

To recap, thus far we've implemented a basic Command/Query Segregation pattern in the ASP.NET MVC Music Store application.  This has decoupled us from the UI for performing important operations which include allowing users to shop and place orders.

Now we are going to expand upon our application to provide the facility to ship products.  The way we'll do this is by publishing a message when an Order has been accepted.  Publishing a message is fundamentally different than sending a message.  When you publish a message it is intended to be received by multiple parties.  Also you must be aware that there can only be one logical Publisher.  If you have multiple Publishers publishing the same message, then the system does not know who to listen to.  In our example we'll initially only have one Subscriber, the Shipping service.  The Shipping service will handle updating inventory and creating shipping notes for the shipping department.  In future installments we'll add more Subscribers to our Order Accepted message.

To get started we have to enhance our data model a bit so we have some place to store our inventory and our shipping notes.  I found the hard way that it is significantly easier to update the database and then the model when using the Entity Framework.  That being said, we'll add the new tables to the database and then update the model:
We start with our table of inventory positions, which tells us how much of the product we have on hand and how much we need to order.  When an order comes in, we'll check this table to see if we have the product, and if we do we'll add that to the Shipped Quantity on our shipping note.  If we don't have the product, we'll put it on back order on our note.

The first thing we need to do is modify our Music Store command handler to become a Publisher.  This is a change to our EndpointConfig.cs which previously was configured AsA_Server.  We'll change this to be configured AsA_Publisher.  So what does this do for us?  First and foremost it tells the endpoint to expect to receive not only the messages we've defined, but also subscription messages.  When a Subscriber starts up, it will put a subscription message into the Publishers input queue, the SAME queue it is currently handling commands upon.  The AsA_Publisher configuration also configures NSB to handle things like how to store the subscription messages.  For the Lite profile, subscriptions are held in memory, for Integration the messages are stored in a queue, and for Production the messages are stored in a database(leveraging NHibernate). Below is our small tweak to the endpoint configuration:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server
    {
    }
The next thing we need to do is actually publish the message. To accomplish this, we'll modify the PlaceOrderHandler to publish a message after it has successfully saved the order. The message we'll publish is the IOrderAcceptedEvent message:
public interface IOrderAcceptedEvent : IEvent
    {
        Int32 OrderId { get; set; }
    }
This message has been added to our public schema project(Messages.csproj). All we pass along here is the order id. We can look up the Order on the other side when we go to ship the product, so there is no need to publish the entire Order. There may be a reason to publish the entire order in the future, especially if there exists components that don't have a way to query for Orders. Note that I'm using the naming convention of provided an "Event" suffix. This is so that I can easily know what is an Event versus what is a Command(namespacing would also do).

Now we have a message to publish, we can update our IPlaceOrderHandler. The first thing we need to do is add a public property of type IBus so that NSB will inject a reference to the bus into our handler. After we have the reference, at the end of the handler we call Bus.Publish and provide an instance of the message using an Action:
public class IPlaceOrderHandler : IHandleMessages<IPlaceOrderCommand>
    {
        public IBus Bus { get; set; }

        public void Handle(IPlaceOrderCommand message)
        {
            MusicStoreEntities storeDB = new MusicStoreEntities();

            var order = new MvcMusicStore.Models.Order();

            order.Username = message.UserId;
            order.OrderDate = DateTime.Now;
            order.OrderId = message.OrderId;

            // Save Order
            storeDB.AddToOrders(order);
            storeDB.SaveChanges();

            //Process the order
            var cart = new ShoppingCart(message.CartId);

            cart.CreateOrder(order);

            this.Bus.Publish<IOrderAcceptedEvent>( o => o.OrderId = order.OrderId);
        }
    }
Now we have our handler publishing messages out to the bus for all subscribers. Next we'll build up our Shipping Subscriber. Add a new project and configure the endpoint AsA_Server just like our original command handler. Next we'll take a look at how we reference the Publisher. We need to know where to drop off our subscription messages. In our subscription message is the Subscriber address along with some other endpoint information. By giving our address to the Publisher, it knows where to push published messages to. To achieve this we add a reference to the Publisher in our app.config:


  
    
      
      
    
  
The overall pub/sub semantics goes something like this:

  1. Publisher starts up and loads subscriptions from storage(memory, queue, or DB)
  2. Subscriber starts up and sends a subscription message to the Publisher.  If the Publisher already has stored the subscription, it gets ignored.  If it does not have the subscription, store the message.
  3. Publisher makes a call to Bus.Publish.
  4. Publisher looks to see who is subscribed to that message.  It creates a message for each Subscriber and puts it on its outbound queue(this is an internal queue to MSMQ that you don't see unless it is sending the machine to another machine)
  5. MSMQ takes over and pushes the messages to their destination queues.  
  6. If the subscriber is up and running it will receive the message and call the appropriate handler.  If not, the message remains in the subscriber input queue.
Please note that if you have a lot of Subscribers and their queues are down, the messages will build up on the Publishers' outbound queue so you will have to size your storage appropriately.
The last thing we need to do is implement the logic for the Shipping service. We will hydrate the order from the order id in the message and then check our inventory. If we have the product, we ship it, otherwise we back order it. From there our processing is complete and we have a full implementation of Pub/Sub:
public class ShippingHandler : IHandleMessages<IOrderAcceptedEvent>
    {
        #region IMessageHandler<IOrderAcceptedEvent> Members

        public void Handle(IOrderAcceptedEvent message)
        {
            MusicStoreEntities storeDB = new MusicStoreEntities();

            var order = storeDB.Orders.Single(o => o.OrderId == message.OrderId);

            var shipNote = new ShippingNote
            { 
                FirstName = order.FirstName,
                LastName = order.LastName,
                Address = order.Address,
                City = order.City,
                State = order.State,
                PostalCode = order.PostalCode
            };

            foreach (var detail in order.OrderDetails)
            {
                var inventoryPosition = storeDB.InventoryPositions.Single(p => p.Album.AlbumId == detail.AlbumId);

                if (inventoryPosition.BalanceOnHand >= detail.Quantity)
                {
                    inventoryPosition.BalanceOnHand -= detail.Quantity;
                    shipNote.ShippedQuantity += detail.Quantity;
                }
                else
                {
                    shipNote.BackOrderQuantity = detail.Quantity - shipNote.ShippedQuantity;
                }
            }

            storeDB.AddToShippingNotes(shipNote);

            storeDB.SaveChanges();

        }

        #endregion
    }
Code is at github

Wednesday, September 8, 2010

Fix It! Where did my project startup settings go?

One thing you'll notice pretty quickly when using NSB and source control is that your Debug settings get lost once you check-in.

This is because these settings are in the $project.user file and not part of the actual $project.csproj file.  To fix this, simply add the properties to a PropertyGroup in your project file:


    Program
    $(ProjectDir)$(OutputPath)NServiceBus.Host.exe
    NServiceBus.Integration
 

Tuesday, September 7, 2010

Fix It! NServiceBus Host Crashes with TNS-less Oracle Connections

Come to find out if you are connecting to Oracle with a TNS-less connection, DTC gets all nutty and crashes your NSB host. The fix is to use TNS. This may not be ideal for some, but for most cases the abstraction layer from the application is nice.

Monday, September 6, 2010

Getting Started with NServiceBus Part 4: Handling Messages

Last time we plugged NSB into the Music Store web app and configured a one way method communication to the server. From there, we'll pick up the messages and start processing them on the server side. The first bit of setup we need to do is to create a new class library and add a reference to our Messages assembly and also all of the NSB assemblies.

First we'll add an configuration file and new class named "EndpointConfig" to handle all of our configuration needs. Let's start with the app.config. In the app config we'll need to configure how clients will send us messages by using the MsmqTransportConfig section. Since we'll be interacting with the Music Store database, we'll need connection strings as well. Here is the app.config:
  
    
The MsmqTransportConfig section defines four main properties. The InputQueue property tells our web app where to put the messages. The ErrorQueue property is where our messages will go if they cannot be processed after the configured amount of retries. The number of retries is configured using the MaxRetries property. The NumberOfWorkerThreads specifies how many threads will be spun up to read messages from the queue and process them. Initially you should start with one and ramp the threads up from there if necessary.

The next piece of the configuration puzzle is the EndpointConfig class. This class will get picked up by NSB at startup and will be used to instruct NSB how to configure the end point.
    public class EndpointConfig : IConfigureThisEndpoint, AsA_Server
    {
    }
The IConfigureThisEndpoint is an interface that marks the class for NSB to pick up during configuration. The AsA_Server interface tells NSB to configure an endpoint that is transactional and that does not purge messages. Now that we have NSB configured, we can start getting into the message handlers.

In order to handle messages, you must implement the IHandleMessages<T> interface. T in this case will be the interface your message type is based upon. Let's check out the AddToCartHandler:
 public class AddToCartHandler : IHandleMessages
    {
        public void Handle(IAddToCartCommand message)
        {
            MusicStoreEntities storeDB = new MusicStoreEntities();

            // Retrieve the album from the database
            var addedAlbum = storeDB.Albums
                .Single(album => album.AlbumId == message.AlbumId);

            // Add it to the shopping cart
            var cart = new ShoppingCart( message.CartId );

            cart.AddToCart(addedAlbum);
        }
    }
Note that the method is void since we are processing the messages in a completely different app domain that the web site. Once the interface has been implemented, it is straight .NET programming from there. We do the same for the PlaceOrderHandler:
public void Handle(IPlaceOrderCommand message)
        {
            MusicStoreEntities storeDB = new MusicStoreEntities();

            var order = new MvcMusicStore.Models.Order();

            order.Username = message.UserId;
            order.OrderDate = DateTime.Now;
            order.OrderId = message.OrderId;

            // Save Order
            storeDB.AddToOrders(order);
            storeDB.SaveChanges();

            //Process the order
            var cart = new ShoppingCart(message.CartId);

            cart.CreateOrder(order);
        }
Note that we are taking the order id from the client. This is because we must show the user the order id right after they have ordered on the client side. We have to modify the underlying data model in order to accommodate this requirement. Simply edit the Order and Order Details tables in the models so that their ids are not generated by the database. Lastly, to get our server up and running we need to edit the Debug properties of the project. First build the project and then set the Debug session to start using an external program. Point to the generic host that comes with NSB, NServiceBus.Host.exe(in the bin directory).

Now we can start adding things to our cart and placing orders from the UI. What you'll notice right away is that when we add things to the cart, it shows us the cart. Under normal conditions(Request/Response design) this would be ok, but our album may not have been saved to the database yet. Therefore we need to change the UI so that it shows the album from the client side instead of the server side. We can do this by creating a new action and showing everything client side:
public ActionResult AddedItemToCart(int id)
        {
            var cart = ShoppingCart.GetCart(this.HttpContext);

            // Retrieve the album from the database
            var addedAlbum = storeDB.Albums
                .Single(album => album.AlbumId == id);

            // Set up our ViewModel
            var viewModel = new ShoppingCartViewModel
            {
                CartItems = new System.Collections.Generic.List(),
                CartTotal = cart.GetTotal() + addedAlbum.Price
            };

            viewModel.CartItems.Add(new Cart { Album = addedAlbum, AlbumId = addedAlbum.AlbumId, Count = 1 });

            return View(viewModel);
        }
All we have to do now is redirect to our new action instead of the old one(Index):
// Go back to the main store page for more shopping
return RedirectToAction("AddedItemToCart", new { id = addedAlbum.AlbumId } );
You'll also note that you may get an error when placing an order. The Music Store immediately validates against the database that your order is there. This is now an unnecessary step because via messaging we are guaranteeing the delivery of the order. All we need to do is simply comment out all the validation code:
public ActionResult Complete(int id)
        {
            //// Validate customer owns this order
            //bool isValid = storeDB.Orders.Any(
            //    o => o.OrderId == id &&
            //    o.Username == User.Identity.Name);

            //if (isValid)
            //{
            //    return View(id);
            //}
            //else
            //{
            //    return View("Error");
            //}

            return View(id);
        }
Now with our minor tweaks to the UI we have fully implemented NSB in our Music Store application. We can guarantee that our users will be able to shop and place orders even if our database is down. This becomes increasingly important especially for those big spenders, we don't want to have to tell them to start all over and that we lost their order.

Full code can be found here

Wednesday, August 25, 2010

Getting Started with NServiceBus Part 3: Putting Messages on the Bus

Last time we analyzed the Music Store code to come up with a schema for our messages. The next order of business is to modify the Music Store code to put messages on the bus. In order to do this we must first edit our web.config file to configure NSB. First you have to add the custom config section:
Next we add that section to create an Endpoint Mapping. What this does is tell the bus that the given Endpoint will be accepting messages defined in our schema assembly.

    
      
    
  
In our case the Endpoint is the address to the queue that will be accepting our messages. If you want at this point you can create this as a local, private, transactional MSMQ queue. Also be sure to have the Distributed Transaction Coordinator service up and running. Now that we have configured our Endpoint, we have to bootstrap NServiceBus and keep it going for the duration of our ASP.NET application. We can do this in the Global.asax.cs file using NSB's fluent configuration:
protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterRoutes(RouteTable.Routes);

            Bus = NServiceBus.Configure.WithWeb()
                .Log4Net()
                .DefaultBuilder()
                .XmlSerializer()
                .MsmqTransport()
                    .IsTransactional(false)
                    .PurgeOnStartup(false)
                .UnicastBus()
                    .ImpersonateSender(false)
                .CreateBus()
                .Start();
        }
I'll explain each configuration item bit by bit:

  • WithWeb - tells NSB to scan a web directory instead of a regular one
  • Log4Net - next configure Log4Net for logging
  • DefaultBuilder - use the default IoC container
  • XmlSerializer - serialize objects using XML
  • MsmqTransport - configure MSMQ as our transportation protocol
  • IsTransactional(false) - we don't want to hang a web app up in transactions, so turn this off
  • PurgeOnStartup(false) - since there is no queue for us to purge, turn this off
  • UnicastBus - configure our bus to send single point to point messages
  • ImpersonateSender(false) - turn off impersonation
  • CreateBus() - tell the IoC to create an instance of the bus
  • Start() - bootstrap the bus

Now that we've bootstrapped, NSB we can get on to sending messages. Our first message will be used to add something to a cart in the database. We head to the the ShoppingCartController.AddToCart method and modify it to send a message instead of interacting directly with the database.

public ActionResult AddToCart(int id)
        {

            // Retrieve the album from the database
            var addedAlbum = storeDB.Albums
                .Single(album => album.AlbumId == id);

            // Add it to the shopping cart
            var cart = ShoppingCart.GetCart(this.HttpContext);
            
            //cart.AddToCart(addedAlbum);

            Helpers.ServiceAgent<IAddToCartCommand>.Send(
                c => 
                {
                    c.CartId = cart.GetCartId(this.HttpContext);
                    c.AlbumId = addedAlbum.AlbumId;
                });
           
            // Go back to the main store page for more shopping
            return RedirectToAction("Index");
        }
I've added a utility class to actually put the message on the bus using similar NSB semantics. I'm doing this so that I don't have an explicit reference to NSB in my Controller code. The utility is very simple:
public static class ServiceAgent<T> where T : ICommand
    {
        public static void Send(Action<T> messageConstructor)
        {
            if (null != messageConstructor)
                MvcApplication.Bus.Send<T>(messageConstructor);
        }
    }
We'll do the same thing for placing an order. We modify the code in CheckOutController.AddressAndPayment:
[HttpPost]
        public ActionResult AddressAndPayment(FormCollection values)
        {
            ...
                else
                {
                    //order.Username = User.Identity.Name;
                    //order.OrderDate = DateTime.Now;

                    //Save Order
                    //storeDB.AddToOrders(order);
                    //storeDB.SaveChanges();

                    //Process the order
                    var cart = ShoppingCart.GetCart(this.HttpContext);
                    //cart.CreateOrder(order);

                    Int32 syntheticId = Helpers.IdGenerator.Generate();

                    Helpers.ServiceAgent.Send(
                        c =>
                        {
                            c.OrderId = syntheticId;
                            c.CartId = cart.GetCartId(this.HttpContext);
                        });

                    
                    
                    return RedirectToAction("Complete", 
                        new { id = syntheticId });
                }
            ...
        }
Here we're using the same utility class to put a message on the bus. Note that I'm generating the Order Id on the client side. This application shows the order id back to the user after they have placed the order. In order to pull this off, we have to create the id client site. I've created another utility to generate the Order Id:
public static class IdGenerator
    {
        public static Int32 Generate()
        {
            byte[] buffer = Guid.NewGuid().ToByteArray();
            return BitConverter.ToInt32(buffer, 0);
        }
    }
Now if you fire up the client and try to add items to the cart, you won't see any data in the subsequent screen. This is because we haven't implemented the server side to our solution that handles the messages. When placing an order you should see and order id just like you normally would.

Next time we'll implement the message handlers and talk about how to host, configure, and run a NSB instance.

Code can be found HERE

Wednesday, August 18, 2010

Getting Started with NServiceBus Part 2: Music Store Schema

Now that we've identified our architecture, the next order of business is to identify what information will be shared within the system.  In our example we will be sending commands to the server to update shopping carts and to place orders.  We'll need two classes to house that information.  First we'll take a look into adding something to a cart by looking at the ShoppingCartController class.  We quickly find the add method:

 public ActionResult AddToCart(int id)
 {
          ...
            cart.AddToCart(addedAlbum);
          ...
 }

This leads us to the AddToCart method:

 public void AddToCart(Album album)
 {
            ...
            if (cartItem == null)
            {
                // Create a new cart item
                cartItem = new Cart
                {
                    AlbumId = album.AlbumId,
                    CartId = shoppingCartId,
                    Count = 1,
                    DateCreated = DateTime.Now
                };
                storeDB.AddToCarts(cartItem);
            }
            else
            {
                // Add one to the quantity
                cartItem.Count++;
            }

            // Save it
            storeDB.SaveChanges();
 }

We find that all we need is the id of the album and the id of the cart to add it to, and therefore we can define our command as:

public interface IAddToCartCommand : ICommand
{
        String CartId { get; set; }
        Int32 AlbumId { get; set; }
}

public interface ICommand : IMessage
{
}

In order to share the reference to the Cart class we have to pull the Models namespace into a separate assembly out of the uber assembly the sample ships with.  There are three major things to note in this code.

First of all in order to identify a message to the NServiceBus infrastructure, we must mark the message with the IMessage interface.  This is how NSB will wire messages to message handlers.

The second note is that we've created an intermediary interface.  We have done this so we can easily differentiate between commands and events.  Commands denote one-way, point to point communication between known parties.  Events denote one-way, one to many communication with potentially unknown parties.  The other way we differentiate the two is to change how the verb in the name is used.  Typically commands will tell the server to do something, ex. "AddToCart".  An event will let us know something happened in the past, ex. "ItemAddedToCart".

Lastly we always use interfaces to define our message schema.  If we do so then NSB can gracefully handle the versioning of messages for us.  This becomes very important when we change our messages and we have to maintain backwards compatibility.

Now we can look at placing an order.  The code for this is a bit strange as its broken up into two different transactions, one for the "header" and one for the details.  The first part is in the AddressAndPayment method in the CheckoutController class, and the second part is in the ShoppingCart class:

        public ActionResult AddressAndPayment(FormCollection values)
        {
            var order = new Order();
            ...
                    order.Username = User.Identity.Name;
                    order.OrderDate = DateTime.Now;

                    //Save Order
                    storeDB.AddToOrders(order);
                    storeDB.SaveChanges();

                    //Process the order
                    var cart = ShoppingCart.GetCart(this.HttpContext);
                    cart.CreateOrder(order);

                    return RedirectToAction("Complete",
                        new { id = order.OrderId });
               ...
        }


 public int CreateOrder(Order order)
 {
            ...
            var cartItems = GetCartItems();

             foreach (var cartItem in cartItems)
            {
                var orderDetails = new OrderDetail
                {
                    AlbumId = cartItem.AlbumId,
                    OrderId = order.OrderId,
                    UnitPrice = cartItem.Album.Price
                };

                storeDB.OrderDetails.AddObject(orderDetails);
                ...
            }

            //Save the order
            storeDB.SaveChanges();
            ...
            //Return the OrderId as a confirmation number
            return order.OrderId;
}

In order to preserve consistency in our database, we'll perform all these actions in a single transaction.  This way we don't get orders without their details.  Also by using durable messaging, we'll ensure that orders don't get lost.  Within the code, the Order is constructed from the ShoppingCart object.  Therefore, all we need is the id of the current cart, and we can look up the rest of the information server side(also reducing trips to the server):

public interface IPlaceOrderCommand : ICommand
{
        String CartId { get; set; }
}


In summary we've decided on how our schema is going to look so that we can now start putting these messages On the Bus!  Next time we'll change the store front to put messages on the bus.  Code can be found here

Saturday, August 14, 2010

NServiceBus for Admins Slide Deck

I've used this deck to introduce NSB to Admins and help them understand the key components of the infrastructure. The deck highlights what they will be responsible for and how to configure the infrastructure for NSB. There are a few slides that have imagery for the NSB site, so I attribute full credit to them for those slides.

Getting Started with NServiceBus Part 1: Analysis of ASP.NET MVC Music Store

In part one of our series we'll begin by analyzing the current state of our application.  I've chosen the ASP.NET MVC Music Store as my example as it has a very small feature set.  What we have is a very simple store front application where you can browse and purchase albums.  The application is your atypical web application that is entirely dependent on a Request/Response architecture.  There are a few places within the application where Request/Response may pose some challenges.

The Shopping Cart

Currently the application pushes a record to the database for each item in your cart.  As a user you really don't know this is happening until something goes wrong.  If for some reason the supporting database was no longer available, the user would not be able to add items to the cart.  Some may say that you have larger issues in that if the database is down, the whole site is down.  For our purposes let's pretend we cache all our static content on a CDN somewhere and we can still browse albums.  To keep our users filling there carts, we'll push a message to the server and update the database in a separate process altogether.

Checking Out

This feature works the same as the Shopping Cart, the user enters their information and their order is pushed to the database.  We have the same potential issue here, if we cannot accept orders our music store is not making us money.  We'd also hate to make a user who has a large order submit it all over again.  We're really concerned with 2 things here, making the customer happy and making sure the store is taking orders.  We'll take the same approach as above and push messages to the server and subsequently update the database.  Now the customers will be happy and we won't lose orders.

Architecture

To accomplish all of this we'll use NServiceBus to move messages to the server and process them.  We'll device a way to plug NSB into the ASP.NET runtime so we can send messages from the web application.  Next we'll create a NSB host on our server to handle the carts and the orders.

Summary

We'll found a couple of soft spots in our application where we can apply messaging to make the customer happy and keep the store running.  Next time we'll start to apply NSB to our solution and walk through the basics of configuring the web application to send messages.

Monday, August 9, 2010

NServiceBus - What did I just download?

I'm currently working on getting some teams in my organization On the Bus and I find myself often quickly explaining what you get when you download NSB.  It includes so much functionality that it helps to quickly dissect what is there.  I'm going to lay it out at a high level so we all know what's in there and where to go first.

Root Directory
The top level directory is pretty self explanatory, I'm going to jump right into the first level of directories and start the tour there.

Binaries

This directory contains the bare bones to run NSB.  The exe is the Generic Host provided with NSB.  This gives us a process to run NSB inside of.  The only other assemblies you really need to run basic NSB functionality is NServiceBus.Core, NServiceBus, and log4net.  The rest will depend on your use case.  The "containers" directory has the binaries for the container of your choice, you don't have to use the default container(Spring).  The "x64" directory has the x64 version of SQLite for testing purposes.

Docs

The "docs" directory has some slides and diagrams of some of the functionality included with NSB, more on these later.  It also has some common code snippets for Visual Studio.  Don't expect deep dive information in the slides, they are just pictures at this point.

Processes
The "processes" directory contains some NSB infrastructure that you'll need for certain NSB use cases.  
  • "distributor" - contains the background process for distributing load across many instances of NSB.  This process handles monitoring the work load and distributing the work to worker nodes.
  • "gateway" - contains the process that manages moving messages between disparate instances of NSB. This is especially useful if you have more that one data center.  You can move messages between sites using the gateway.
  • "proxy" - this process allows us to expose a single endpoint to several clients.  This is handy when you need to expose NSB through a firewall.
  • "timeout" - this process handles the watching of the clock for Sagas.  Sagas are analogous to long running workflows.  When using Sagas, you need something to keep a watch and wait up workflows when necessary.
Samples

  • "AsyncPages" - example of how to due asynchronous request/response on a web page using ASP.NET as your host process. 
  • "FullDuplex" - example of performing request/response in a non-web scenario
  • "GenericHost" - example of how the host provided with NSB works.  Via the concept of profiles we can manipulate the behaviour of the host.
  • "Manufacturing" - this example has a lot of stuff in it, including Pub/Sub, Sagas, interop with straight MSMQ, the included testing framework, message ordering, and more.  I found myself taking bits of this example and breaking it down into smaller examples.
  • "PubSub" - basic example of how to implement the Publish/Subscribe pattern in NSB.
  • "Versioning" - shows how that through interfaces, NSB allows us to gracefully version messages to consumers without breaking them.
  • "WcfIntegration" - shows off the OOTB support for exposing NSB as a HTTP/WCF service.  This becomes useful if you have to interact with another non-MSMQ system.
  • "WebServiceBridge" - hosts NSB from within ASP.NET again, only this time in a web service.  The web site in this sample using the service to bridge into NSB without knowing about NSB itself.
Tools
  • "MsmqUtils" - provides a program for you to run to validate your install of MSMQ and MSDTC.  This is a handy tool to make sure you start off on the right foot, I recommend running this right after you download NSB to avoid headaches.
  • "ReturnToSourceQueue.exe" - takes messages from a queue(typically an error queue) and pushes them back to the source queue.  This tool is very effective when you have a bunch of failures that you want to re-process.  I would make sure your SysAdmins know about this tool.
  • "UI.exe" - is a limited UI for managing NSB endpoints.
  • "XsdGenerator.exe" - this tool will generate an XSD file using an assembly of messages as input.  This is for the case where you don't want to directly distribute your messages assembly, but would rather have consumers build their own.

That pretty much covers it, there is a lot of stuff in here!  I'm hoping to next start talking about some of the use cases we've had to leverage NSB and get started on a demo project to walk through an application of NSB.




Installing NServiceBus Using the Network Service Account

Our defacto standard for Windows Services is to install under the "Network Service" account or "MachineName$". To get NSB to install under this account, I had to try several variations of the account name and finally it came down to using a fully qualified name:

nservicebus.host.exe /install /serviceName:"ServiceName" /displayName:"DisplayName" /userName:"NT AUTHORITY\Network Service" /password:""

Friday, August 6, 2010

Exposing NServiceBus as a REST(WCF) Endpoint


I recently had a situation where I wanted to expose NSB as a REST endpoint.  WCF hosting comes out of the box with NSB, but it defaults to an HTTP binding.  Normally it would be a problem to just add another endpoint via config, but when using the webHttpBinding in WCF we need the ability to decorate operations with some attributes which is not configurable in a config file.  Luckily for us, NSB gives us a simple extension point to wire in our own ServiceHost.  I started by creating my WCF contract:

[ServiceContract]
    public interface IProductCreatedRestService
    {
        [OperationContract]
        [WebInvoke(UriTemplate = "products", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
        void Create(ProductCreatedMessage message);
    }
Next up is the concrete implementation:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class ProductCreatedRestService : IProductCreatedRestService
    {
        private readonly IBus bus;

        public ProductCreatedRestService()
        {
            if ( null == this.bus )
                this.bus = Configure.Instance.Builder.Build<IBus>();
        }

        public void Create(ProductCreatedMessage message)
        {
            this.bus.Send(message);
        }
    }

 The big note here is that I'm building an instance of IBus using the NSB IoC container. An alternative would be to register the component at startup and let NSB property-inject IBus. The next thing I need to do is create and open up a WebServiceHost for my service. I do this via the IWantToRunAtStartup marker interface. NSB makes heavy use of the marker interface pattern. This allows it to identify certain classes via the IoC container. This interface let's us plugin our own custom code when NSB starts up and subsequently shuts down. Here is my startup class:

 public class RestServiceStartup : IWantToRunAtStartup
    {
        private WebServiceHost host;

        public void Run()
        {
            this.host = new WebServiceHost(typeof(ProductCreatedRestService));
            this.host.Open();
        }

        public void Stop()
        {
            if (null != this.host && this.host.State == System.ServiceModel.CommunicationState.Opened)
                this.host.Close();
        }
    }
My handler for the message is standard issue NSB fare:

 public void Handle(ProductCreatedMessage message)
        {
            // Normally you would do a Bus.Send here first
            if (message.ProductNumber == 1111)
                this.Bus.Return((Int32)CommandErrorCodes.Fail);
            else
                this.Bus.Return((Int32)CommandErrorCodes.Success);
        }
Now we can fire up our NSB instance and also jump into Fiddler to generate our request:





Seminal Post

Hey all the plan is to post some interesting things I've come across while working with NServiceBus.  I plan on launching a full on demo project in the very near future.  I need to find someplace to host my code(suggestions welcome) and also pick a pet project to modify.  I'm thinking of taking a bite from Ayende's plate and using the ASP.NET MVC sample project.  Stay tuned...