Monday, March 12, 2012

MultiAppLauncher

The only way to handle repetitive tasks, are to automate them. After getting fed up starting n cmd consoles and n "Set Startup Projects - Multiple Startup Projects" in Visual Studio, it was time to do something, and this is the result.

This application is a small helper app I wrote for starting multiple NServiceBus services for a given profile. It will monitor the process status of the host and show it in the GUI

Features

  • Load and save the current application set to a xml file
  • Hides the console application from the taskbar
  • Double click an item in the list to bring the process to front
  • Kill all processes (from menu)
  • Modify profile for a given application (right click the application)

You can get the source from GitHub: https://github.com/mteinum/MultiAppLauncher

settings file

The application supports Drag & Drop so you can drag the NServiceBus.Host.exe file on the application and you we will be asked for a profile to be assigned.

The settings file for an applicationset is an array of filenames to execute, and a profile that will be passed as an argument.

<?xml version="1.0"?>
<SettingsDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <FileNames>
    <FileSettings>
      <Name>C:\dev\MyService1\bin\Debug\NServiceBus.Host.exe</Name>
      <Profile>NServiceBus.Lite</Profile>
    </FileSettings>
    ....
  </FileNames>
</SettingsDocument>

Shortcuts

CTRL+OOpen an application set file
CTRL+SSave the current configuration
CTRL+RStart all applications that are not running. If no rows are selected then all the applications will be started. If you do explicit selection, only those selected will be started.

Runtime

The application requires .NET 4.0 installed. http://www.microsoft.com/download/en/details.aspx?id=17851

Binaries

Latest version: https://github.com/mteinum/MultiAppLauncher/downloads

Saturday, March 10, 2012

NServiceBus 3.0 - SMTP Transport

NServiceBus 3.0 is fresh out of GitHub, and I'm wading through the code and testing out different concepts. You might learn something from this code (the code in this blog post ;), but its far from production stable.

SmtpClient

With NServiceBus 3.0 there is a FtpTransport that enable us to send/receive messages over FTP instead of MSMQ. RFC 2549 is not supported, but before we start with that, lets try something simpler: Send messages using SMTP.

Looking at the code for FtpMessageQueue, ISendMessages and IReceiveMessages are the interfaces that NServiceBus uses for sending and receiving TransportMessages.

.NET includes a SmtpClient, but no POP3 support, so we will now limit ourself to sending messages. Let's start.

The preferred way I like to host NServiceBus applications, are using the NServiceBus.Host.exe. This host has the concept of one input queue and one error queue. At the moment we will not process any input messages (in lack of an pop3 client), but we will send out messages.

Message

It could be a message that would launch a nuclear bomb, brew coffee or buy a movie ticket, but for the example let's use:

public class MyMessage : IMessage
{
  public string Foo;
  public string Bar;
}

IWantToRunAtStartup

There are various ways to interact with the Host, IWantToRunAtStartup is an interface you can decoracte a class with and it will be called at startup. We'll combine the marker interface IConfigureThisEndpoint and IWantCustomInitialization that will setup the smtptransport.

public class Runner :
             IConfigureThisEndpoint,
             IWantToRunAtStartup,
             IWantCustomInitialization
{
  public IBus Bus { get; set; }

  public void Run()
  {
    string line;

    while ((line = Console.ReadLine()) != null)
    {
      Bus.Send(new MyMessage { Bar = "bar", Foo = "foo" });
    }
  }

  public void Stop()
  {
  }

  public void Init()
  {
    Configure
     .With()
     .DefaultBuilder()
     .SmtpTransport()
     .UnicastBus()
     .SendOnly();
    }
}

App.config

The config file is the preferred place to put any configuration that will affect the application; connectionstrings, paths, ....

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="SmtpQueueConfig"
              type="SmtpTransport.SmtpQueueConfig, SmtpTransport" />
    <section name="UnicastBusConfig"
              type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core" />
    <section name="MessageForwardingInCaseOfFaultConfig"
              type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core" />
  </configSections>

  <MessageForwardingInCaseOfFaultConfig ErrorQueue="errors"/>

  <SmtpQueueConfig
      SmtpServer = "smtp.gmail.com"
      Port       = "587"
      EnableSsl  = "true"
      From       = "username@gmail.com"
      UserName   = "username@gmail.com"
      Password   = ""/>

  <UnicastBusConfig>
    <MessageEndpointMappings>
      <add Messages="SmtpTransport" Endpoint="username@gmail.com" />
    </MessageEndpointMappings>
  </UnicastBusConfig>

</configuration>

UnicastBusConfig and MessageForwardingInCaseOfFaultConfig is part of NServiceBus, SmtpQueueConfig is created by me and looks like:

public class SmtpQueueConfig : ConfigurationSection
{
  [ConfigurationProperty("SmtpServer", IsRequired = true)]
  public string SmtpServer
  {
    get { return this["SmtpServer"].ToString(); }
    set { this["SmtpServer"] = value; }
  }

  [ConfigurationProperty("Port", IsRequired = true)]
  public int Port
  {
    get { return (int)this["Port"]; }
    set { this["Port"] = value; }
  }

  [ConfigurationProperty("EnableSsl", IsRequired = true)]
  public bool EnableSsl
  {
    get { return (bool)this["EnableSsl"]; }
    set { this["EnableSsl"] = value; }
  }

  [ConfigurationProperty("From", IsRequired = true)]
  public string From
  {
    get { return this["From"].ToString(); }
    set { this["From"] = value; }
  }

  [ConfigurationProperty("UserName", IsRequired = true)]
  public string UserName
  {
    get { return this["UserName"].ToString(); }
    set { this["UserName"] = value; }
  }

  [ConfigurationProperty("Password", IsRequired = true)]
  public string Password
  {
    get { return this["Password"].ToString(); }
    set { this["Password"] = value; }
  }
}

No big surprises here. If you now goes back to the Init method of the Runner class you will see that we call .SmtpTransport() on the Configure class. This is an extension method:

public static class ConfigureSmtpQueue
{
  public static Configure SmtpTransport(this Configure config)
  {
    var smtpQueue = config.Configurer.ConfigureComponent<SmtpMessageQueue>(
                                 DependencyLifecycle.SingleInstance);
    var cfg = Configure.GetConfigSection<SmtpQueueConfig>();

    if (cfg != null)
    {
      smtpQueue.ConfigureProperty(t => t.SmtpServer, cfg.SmtpServer);
      smtpQueue.ConfigureProperty(t => t.Port, cfg.Port);
      smtpQueue.ConfigureProperty(t => t.EnableSsl, cfg.EnableSsl);
      smtpQueue.ConfigureProperty(t => t.From, cfg.From);
      smtpQueue.ConfigureProperty(t => t.UserName, cfg.UserName);
      smtpQueue.ConfigureProperty(t => t.Password, cfg.Password);
    }

    return config;
  }
}

It's the binding between the configuration and our transport class. Then finally:

SmtpMessageQueue

public class SmtpMessageQueue : ISendMessages, IReceiveMessages
{
  public string SmtpServer { get; set; }
  public int Port { get; set; }
  public bool EnableSsl { get; set; }
  public string From { get; set; }
  public string UserName { get; set; }
  public string Password { get; set; }

  public void Send(TransportMessage message, Address address)
  {
    using (var client = new SmtpClient(SmtpServer, Port))
    {
      client.EnableSsl = EnableSsl;
      client.Credentials = new NetworkCredential(UserName, Password);

      var serializer = new JavaScriptSerializer();

      var mailMessage = new MailMessage(From, address.ToString())
                        {
                          Subject = "NServiceBus TransportMessage",
                          Body = serializer.Serialize(CreateMailMetaData(message));
                        };

      mailMessage.Attachments.Add(
        new Attachment(
          new MemoryStream(message.Body),
          "body.bin",
          "application/octet-stream"));

          client.Send(mailMessage);
        }
    }

  private MailMetaData CreateMailMetaData(TransportMessage message)
  {
    return new MailMetaData
    {
      CorrelationId = message.CorrelationId,
      Id = message.Id,
      IdForCorrelation = message.IdForCorrelation,
      ReplyToAddress = message.ReplyToAddress.ToString(),
      TimeToBeReceived = message.TimeToBeReceived,
      Header = message.Headers.Select(
        x => new HeaderPair
             {
               Name = x.Key,
               Value = x.Value }).ToList()
      };
  }

  public void Init(Address address, bool transactional)
  {
    // TODO: add a pop3 client and poll for new messages
  }

  public bool HasMessage()
  {
    return false;
  }

  public TransportMessage Receive()
  {
    return null;
  }
}

public class MailMetaData
{
  public string CorrelationId;
  public string Id;
  public string IdForCorrelation;
  public string ReplyToAddress;
  public TimeSpan TimeToBeReceived;
  public List<HeaderPair> Header;
}

public class HeaderPair
{
  public string Name;
  public string Value;
}

Does it work? This is the email in gmail:

Yes! We'll fix the pop3 / receiver next week.

NServiceBus 3.0

The coolest thing happening on the software front in 2012. More info on Udi's blog:

http://www.udidahan.com/2012/03/08/nservicebus-3-0-released/

Get the binaries: http://www.nservicebus.com, or the sourcecode https://github.com/NServiceBus/NServiceBus

RunMeFirst.bat

Run this as Administrator

Still no sight of RFC 2549...

Sunday, February 26, 2012

Wednesday, July 6, 2011

NServiceBus - Single process, multiple input

My default NServiceBus will listen to one single MSMQ and dispatch incoming messages to handlers loaded by the bus. It's possible to run multiple threads for consuming messages from MSMQ. There is a problem with this. Say we have two services, one that updates a database, another service communicating with some "slow" hardware over telnet. If you now have one thread receiving messages and dispatch this to one of the two handlers the following can happen: You send 1000 telnet messages, and then a database update message. The issue now is that all of the telnet messages will be handeled before the database update message will be processed. Can you increase the number of workerthreads on the transport? For database messages, most likely. For the telnet messages that might not be the case.

The trick here is to have different queues for the telnet and database messages. And then we get the first problem, there can only be a single <MsmqTransportConfig/> in the application configuration file.

It is possible to create multiple instances in the application:


var bus = Configure.With....CreateBus().Start();


Here we will create an application with two input busses and one sender bus. We will do explicit type mapping for message routing and handlers.



But we need to tell the bus what queue to listen on. This can be done by implementing the IConfigurationSource. In our example:


sealed class MyConfigurationSource : IConfigurationSource
{
private readonly string _inputQueue;

public MyConfigurationSource(string inputQueue)
{
_inputQueue = inputQueue;
}

public T GetConfiguration<T>() where T : class
{
if (typeof(T) == typeof(MsmqTransportConfig))
return new MsmqTransportConfig
{
InputQueue = _inputQueue
} as T;

return ConfigurationManager.GetSection(typeof(T).Name) as T;
}
}


We can then add this to the construction phase of the bus:


private static void AddReceiverBus(
string inputQueue,
Type handler)
{
var types = typeof(UnicastBus).Assembly.GetTypes().Union(
new[] { handler });

Configure.With(types)
.CustomConfigurationSource(new MyConfigurationSource(inputQueue))
.StructureMapBuilder()
.XmlSerializer()
.MsmqTransport()
.IsTransactional(true)
.MsmqSubscriptionStorage()
.UnicastBus()
.ImpersonateSender(false)
.LoadMessageHandlers()
.CreateBus()
.Start();
}


With(types) tells NServiceBus what handlers to load. In this example a single type.

We can then create a new receiver bus listening at a given queue, with a given handler.


AddReceiverBus(
"SomeMessage.Input",
typeof(SomeMessageHandler));




AddMapping is an custom extension method that will tell the bus where a given messagetype should be sent. This is used for the "sender" bus


public static class MyMappingExtension
{
public static ConfigUnicastBus AddMapping(
this ConfigUnicastBus config,
Hashtable mapping)
{
config.RunCustomAction(() =>
Configure.Instance
.Configurer
.ConfigureProperty<UnicastBus>(
x => x.MessageOwners, mapping)
);

return config;
}
}


And the hashtable is populated this way:


var mapping = new Hashtable
{
{ typeof(SomeMessage).AssemblyQualifiedName, "SomeMessage.Input" },
{ typeof(AnotherMessage).AssemblyQualifiedName, "AnotherMessage.Input" }
};


The "sender" bus is almost the same as the receiver, but there are no handlers that will be loaded:


private static IBus CreateSenderBus(Hashtable mapping)
{
return Configure.With()
.StructureMapBuilder()
.XmlSerializer()
.MsmqTransport()
.IsTransactional(true)
.UnicastBus()
.ImpersonateSender(false)
.AddMapping(mapping)
.CreateBus()
.Start();
}

...

StructureMap.ObjectFactory.Inject(
CreateSenderBus(mapping));


We can now get the bus out of StructureMap and send a message


private static void SendMessageOnTheBus()
{
var bus = StructureMap.ObjectFactory.GetInstance<IBus>();

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


The message will then be routed to the SomeMessageHandler class and with this implementation it will be routed to AnotherMessageHandler. Take a second look at the code, this is a very nice way to upgrade your message format from A to B. You create a new class, move the logic from handler A to handler B, and make handler A translate message A to message B.


public class SomeMessageHandler : IHandleMessages<SomeMessage>
{
public void Handle(SomeMessage message)
{
var bus = StructureMap.ObjectFactory.GetInstance<IBus>();
bus.Send(new AnotherMessage { Text = message.Text });
}
}


... that will write the content to the logging framework.


public class AnotherMessageHandler : IMessageHandler<AnotherMessage>
{
private static readonly ILog Logger = LogManager.GetLogger(
typeof(AnotherMessageHandler));

public void Handle(AnotherMessage message)
{
Logger.DebugFormat("Message received: {0}", message.Text);
}
}




The code is also available on github:

https://github.com/mteinum/linq-enumerable

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!

Friday, June 10, 2011

Starting up with NServiceBus

After many years with a inhouse made API on top of MSMQ, its time to evaluate other frameworks that gives us more out of the box.

NServiceBus looks like a great candidate.

  • Easy install

  • Extensible

  • Strongly typed messages using generics

  • Support for unit testing


The first problem was to use the StructureMap container in a strong name solution. The NServiceBus.ObjectBuilder.StructureMap262.dll extension have no stong name so I had to decompile and assemble it again with a keypair.

This is done using ildasm/ilasm.

sn -k test.snk

ildasm NServiceBus.ObjectBuilder.StructureMap262.dll /out=NServiceBus.ObjectBuilder.StructureMap262.il

ilasm NServiceBus.ObjectBuilder.StructureMap262.il /dll /key=test.snk /output=NServiceBus.ObjectBuilder.StructureMap262-sn.dll


Then its over to programming.

Message
We define a message with some properties that are sent from the client to the handler/server/service

public class PingMessage : NServiceBus.IMessage
{
public string Text;
}


Handler
Then a handler to consume these messages:

public class PingMessageHandler : NServiceBus.IHandleMessages<PingMessage>
{
public ILog Logger = LogManager.GetLogger(typeof(PingMessageHandler));

public void Handle(PingMessage message)
{
Logger.Debug(message.Text);
}
}


Unit testing
Normally I would have made Logger static readonly but we want to access this in our unit test

[TestFixture]
public class PingMessageHandlerFixture
{
[Test]
public void SendMessage()
{
Test.Initialize(typeof(PingMessage).Assembly);
var logger = A.Fake<log4net.ILog>();

Test.Handler<PingMessageHandler>()
.WithExternalDependencies(x => x.Logger = logger)
.OnMessage<PingMessage>(x => x.Text = "hello world");

A.CallTo(() => logger.Debug("hello world")).MustHaveHappened();
}
}


And the test goes green!

Great start :)

References:
www.nservicebus.com
fakeiteasy