Friday, July 1, 2011

NServiceBus - Part 2

Continuing writing down my findings getting NServiceBus up and running.

Overal structure, simple:


There are two config sections that are important regarding NServiceBus

* MsmqTransportConfig
* UnicastBusConfig

MsmqTransportConfig


This section have information about the messages going in to the current process.

UnicastBusConfig


This section is used to say where a message should be sent.

Example:

The following section says that a specific message should be sent to a queue named testqueue on the 10.21.50.11 machine.


<UnicastBusConfig>
<MessageEndpointMappings>
<add Messages="NServiceBusDemo.SomeMessage, NServiceBusDemo"
Endpoint="testqueue@10.21.50.11"/>
</MessageEndpointMappings>
</UnicastBusConfig>


The following section says that all messages in the NServiceBusDemo assembly should be sent to the queue name testqueue on the local machine.


<UnicastBusConfig>
<MessageEndpointMappings>
<add Messages="NServiceBusDemo" Endpoint="testqueue"/>
</MessageEndpointMappings>
</UnicastBusConfig>


Message Format



This class is used as the message for this example


[Serializable]
public class SomeMessage : IMessage
{
public string Text;
}


By default there are two formatters available for serializing the messages to MSMQ. Binary and Xml. For both serializers a Label is set on the Message (MSMQ) with the following data:


<CorrId></CorrId><WinIdName>NO\mteinum</WinIdName>


The ResponseQueue on the Message is set to the inputqueue defined in MsmqTransportConfig

For my example:

DIRECT=OS:MORTEN\private$\NServiceBusDemoInputQueue


The body is the output from the XML.MessageSerializer:


<?xml version="1.0"?>
<Messages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://tempuri.net/NServiceBusDemo">
<SomeMessage>
<Text>FooBar</Text>
</SomeMessage>
</Messages>

If we are sending two messages, one of SomeMessage and another of type AnotherMessage, the serialized stream will look like:

<?xml version="1.0"?>
<Messages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://tempuri.net/NServiceBusDemo">
<SomeMessage>
<Text>Hello World!</Text>
</SomeMessage>
<AnotherMessage>
<Text>Hello World!</Text>
</AnotherMessage>
</Messages>


Custom formatter


SOAP ...? :) Is it possible? sure :)

First we need to create a serializer class implementing the NServiceBus.Serialization.IMessageSerializer interface.

And since we want a SOAP formatted message we will use the formatter from the System.Runtime.Serialization.Formatters.Soap namespace.

And the implementation:


public class SoapMessageSerializer : IMessageSerializer
{
private readonly SoapFormatter _formatter;

public SoapMessageSerializer()
{
_formatter = new SoapFormatter
{
AssemblyFormat = FormatterAssemblyStyle.Simple,
TypeFormat = FormatterTypeStyle.TypesWhenNeeded
};
}

public void Serialize(IMessage[] messages, Stream stream)
{
_formatter.Serialize(stream, messages);
}

public IMessage[] Deserialize(Stream stream)
{
return (IMessage[])_formatter.Deserialize(stream);
}
}


We then need to configure the bus to use this, and we then need an extension class:


public static class ConfigureSoapSerializer
{
public static Configure SoapSerializer(this Configure config)
{
config.Configurer.ConfigureComponent(
typeof(SoapMessageSerializer),
ComponentCallModelEnum.Singleton);

return config;
}
}


We can then start the bus using this extension method


var bus = Configure.With()
.Log4Net()
.StructureMapBuilder()
.SoapSerializer()
.MsmqTransport()
.UnicastBus()
.ImpersonateSender(false)
.CreateBus()
.Start();

bus.Send(new SomeMessage { Text = "Hello World!" });


And the message on the queue:


<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<SOAP-ENC:Array SOAP-ENC:arrayType="a1:IMessage[1]"
xmlns:a1="http://schemas.microsoft.com/clr/nsassem/NServiceBus/NServiceBus">
<item href="#ref-3" />
</SOAP-ENC:Array>
<a2:SomeMessage id="ref-3"
xmlns:a2="http://schemas.microsoft.com/clr/nsassem/NServiceBusDemo/NServiceBusDemo">
<Text id="ref-5">Hello World!
</a2:SomeMessage>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>


Happy coding!

No comments:

Post a Comment