Wiki         Discussion Group         SourceForge Project         Community   
 
nServiceBus NServiceBus training - opens a new tab
 
       Overview Documentation Downloads Community Roadmap License
 

Documentation

Documentation - a work in progress

Like any open source framework, our documentation isn't that great.
It isn't actually that bad either. It's just not what you'd expect.

All the public classes and interfaces have XML documentation.
Extensive samples show how end-to-end communications work.

The overview gives architectural guidance on what to do when.
And below we've compiled a FAQ to help you hit the ground running.

And there's always the wiki for more information.
Enjoy...


Contents

FAQ

How's messaging different?

In regular communications between clients and servers, both machines need to be up and running, and so do the software processes. If either process or machine goes down, then communication cannot continue.

In non-durable messaging, processes can be up or down at any point in time. Sending a message involves putting it in an outgoing queue on the same machine. At the point, the sending process can go down and nothing bad will happen. The messaging infrastructure then tries to get that message to the target machine in collaboration with its counterpart on that machine. When that message arrives, if the process is down, the message just sits in a queue waiting. When the process comes up, it can process the message.

Durable messaging does all of the above but durably. When the message is put in the output queue, it's written to disk - so that even if the sender crashes at that point, the message won't be lost. When the message is transferred to the target machine, it is written to disk there (and then deleted from the sender's disk). That way, even if the target machine crashes at some point, the message won't be lost. In short, both machines need to be online at the same time just long enough to transfer the message safely, and no more than that.

How do I define a message?

public class MyMessage : IMessage { }

OR

public interface IMyMessage : IMessage { }


One of the advantages of using interfaces to define messages instead of classes is that you get "multiple inheritance" - one message can extend multiple other messages.

This is useful for solving a specific class of versioning problems.

Say that your business logic represents a state machine with states X and Y. When your system gets into state X, it publishes a message - EnteredStateX. When your system gets into state Y, it publishes a message - EnteredStateY. (For more information on how to publishe a message, see below)

In the next version of your system, you add a new state Z, which represents the co-existence of both X and Y. So, you define a message EnteredStateZ which inherits both EnteredStateX and EnteredStateY.

When your system publishes EnteredStateZ, clients subscribed to either (or both) EnteredStateX or EnteredStateY will be notified.

Without the ability to have a message extend multiple others, you'd have to use composition. This would prevent the infrastructure from knowing how to automatically route messages to pre-existing subscribers of the composed messages.

How do I specify store & forward for a message?

This is the default mode in version 2.0, but not in 1.9.

[Recoverable]
public class MyMessage : IMessage { }

How do I specify that I don't want a message to be written to disk?

This is the default mode in version 1.9, but not in 2.0.

[Express]
public class MyMessage : IMessage { }

How do I get old messages to be discarded?

[TimeToBeReceived(“00:01:00”)] // one minute
[Recoverable]
public class MyMessage { }

If a message wasn't able to be *received* by the target process in the given timeframe, including all time in queues and in transit, the message will be discarded.

How do I instantiate a message?

var msg = new MyMessage();

OR

var msg = Bus.CreateInstance<IMyMessage>();

How do I send a message?

Bus.Send(messageObject);

OR (Instantiate and send all at once):

Bus.Send<IMyMessage>( (m) => { m.Prop1 = v1; m.Prop2 = v2; });

How do I specify to which destination a message will be sent?

Configure destination for message type:
In <UnicastBusConfig>, under <MessageEndpointMappings>

<add Messages=“assembly” endpoint=“destination”>

OR

<add Messages=“type” endpoint=“destination”>

Destinations can be QueueName@ServerName, or just QueueName on the same machine.


You can also call: Bus.Send(string destination, params IMessage[] msgs);

though not recommended for application-level code.

How do I handle a message?

Write a class that implements IMessageHandler<T> where T is message type

public class H1 : IMessageHandler<MyMessage>
{
     public void Handle(MyMessage message)
     {
     }
}

How do I handle all kinds of messages

Write a handler for IMessage as follows:

public class H1 : IMessageHandler<IMessage>
{
     public void Handle(IMessage message)
     {
          // do something relevant for all messages
     }
}

How do I specify the order in which handlers are invoked?

If you're writing your own host:

NServiceBus.Configure.With()
     ...
     .UnicastBus()
          .LoadMessageHandlers(First<H1>.Then<H2>().AndThen<H3>().AndThen<H4>() //etc)
     ...

If you're using the generic host

public class EndpointConfig : IConfigureThisEndpoint, ISpecify.MessageHandlerOrdering
{
     public void SpecifyOrder(Order order)
     {
          order.Specify(First<H1>.Then<H2>().AndThen<H3>().AndThen<H4>() //etc);
     }
}

How do I get a reference to IBus in my message handler?

public class H1 : IMessageHandler<MyMessage>
{
     public IBus Bus { get; set; }

     public void Handle(MyMessage message)
     {
          // use Bus for something
     }
}

How do I get additional information about a message?

public class H1 : IMessageHandler<MyMessage>
{
     public IBus Bus { get; set; }

     public void Handle(MyMessage message)
     {
          // use Bus.CurrentMessageContext
          // contains Id, ReturnAddress, and Headers
     }
}

How do I reply to a request?

public class H1 : IMessageHandler<MyMessage>
{
     public IBus Bus { get; set; }

     public void Handle(MyMessage message)
     {
          Bus.Reply<MyResponse>();
          // can call reply multiple times
          // useful for "streaming" back a lot of data
     }
}

How do I call a web service?

Don't.

At least not from within a message handler doing business logic.

The reason for this has to do with fault tolerance. If the web service that you're calling is unavailable or slow, the call to the web service will likely blow up with an HttpTimeoutException. This becomes problematic when you call multiple web services and/or reply/send/publish messages as a part of the same method.

See below for how exceptions should be handled.

The recommended approach to integrating with an external web service is to put an adapter process between your business logic and the web service. Have your handler send a message to that adapter process which, in turn, invokes the web service.

How do I handle responses client-side?

Can handle like any regular message, have a class implement IMessageHandler<MyResponse>

Can register a callback when sending request:

Bus.Send(request).Register(asyncCallback, state)

Callback only fires on first response, then is cleaned up to prevent memory leaks. Doesn’t survive restarts – not suitable for server-side

How do I publish a message?

Bus.Publish(messageObject);

OR (Instantiate and publish all at once):

Bus.Publish<IMyMessage>( (m) => { m.Prop1 = v1; m.Prop2 = v2; });

How do I publish a message from a web app?

Don't.

When communicating from a web application to a back end process, don't Bus.Publish the message. Rather, Bus.Send it. Configure the destination that the message is sent to as described above in the section "How do I specify to which destination a message will be sent?".

How's publishing a message different from just sending it?

While the two may seem almost equivalent, they mean very different things. A lot of conventions have been set up in the infrastructure so that no additional configuration is needed to do either. Treating the two the same will make it difficult for you to have the routing infrastructure "just work".

When sending a message, nServiceBus assumes that you're a client sending a command or request of sorts to a server. When publishing a message, nServiceBus assumes that you're a server notifying previously subscribed parties about an event *that's already happened*.

In the case of sending a message, the sender is required to have a <MessageEndpointMapping> entry in its configuration specifying where the message should be sent to. In the case of publishing a message, the publisher is not expected to have that entry in its configuration. Subscribers are the ones that need to have that entry.

In short, it's the different meaning of the message that should guide you.

How do I subscribe to a message?

If you have a message handler for a message which is configured as belonging to a different endpoint (specified with a MessageEndpointMapping in your <UnicastBusConfig> section - see above), then the infrastructure will automatically subscribe to that message.

You can also choose to *not* have the infrastructure automatically subscribe by specifying ConfigUnicastBus.DoNotAutoSubscribe() in the fluent configuration API or by implementing IDontWant.ToSubscribeAutomatically when using the generic host (see below).

In order to manually subscribe to, and unsubscribe from a message, call

Bus.Subscribe<MyMessage>()

OR

Bus.Unsubscribe<MyMessage>()

How do I handle exceptions?

Don't.

NServiceBus has exception catching and handling logic of its own which surrounds all calls to user code. When an exception bubbles through to the NServiceBus infrastructure, it rolls back the transaction on a transactional endpoint, causing the message to be returned to the queue, and any messages that user code tried to send or publish to be undone as well.

At that point, NServiceBus will retry to handle that message a configurable number of times (default of 5) and if the message fails on every one of those retries, the message will then be moved to the configured error queue.

Administrators should monitor that error queue so that they can see when problems occur. The message in the error queue contains the source queue and machine so that the administrator can go see what's wrong with that node and possibly correct the problem (like bringing up a database that went down).

Once the administrator corrects the problem, they can use the ReturnToSourceQueue.exe tool to send the relevant message back to its original queue so that it can be processed again - this time successfully.

How do I expose an NServiceBus endpoint as a web service?

Inherit from NServiceBus.Webservice<TCommand, TErrorCode> as shown below. TCommand is the message type of the request and needs to implement IMessage. TErrorCode must be an enumerated type, and should represent the result of processing the command.

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
public class MyWebService : NServiceBus.Webservice<Command, ErrorCodes> { }

If you want to expose a web service which returns a response message rather than just an error code, the recommendation is to reconsider your design. For example, if you want to perform queries like GetCustomersByRegionRequest and CustomersByRegionResponse, that should not be implemented using messaging. See the topic of Command/Query Separation (CQS) for more information.



Connect with others in the NServiceBus community.

NServiceBus is managed and run by Udi Dahan.
Committers include Andreas Öhlund and Matt Burton.

All content on this site is licensed under the Creative Commons Attribution License.