MassTransit Now Speaks XML By Default

Last night, I made a major update to the trunk of MassTransit that changes the default message format from binary to XML.

Since the first drop of MassTransit, the default format for messages was binary. This had several advantages, one being the ability to take any object and just use it as a message. The BinaryFormatter in .NET is pretty hard core about making sure that the object will come out the other end without any changes. The disadvantage of using binary as a message format is it makes it very difficult to interoperate with other systems. For this reason, we are embracing XML as the new default message format.

The road to XML was not easy. Many months ago when we opened up the endpoints to a configurable serialization format, we ran into some issues with our first attempt at XML. We used the .NET XmlSerializer at first, and found it to be too limited to meet our needs. There was no support for serializing dictionaries (which I would call a smell in your message contract anyway), and you had to register the type of every object being serialized in advance in order for it work properly. With all these problems, we continued to keep binary as the default with XML being experimental.

I started writing a new XML serializer from the ground up nearly a year ago. I went through a lot of approaches and just didn’t find something that I liked using .NET 2.0 as the framework. I looked at a more Google Protocol Buffers technique for a while, but found it a little cumbersome to deal with compared to just using XML. Then, a month or two ago, I started to seriously look at how we could do a solid XML serialization attempt again using the .NET 3.5 framework features. From that research, the current default XML serializer was founded.

Like many ORMs such as NHibernate, the use of the XML message serializer requires that the objects being serialized have a no-argument constructor. It can be protected to hide it from developers, but it must exist. Also, only properties are serialized as they represent the public contract that the message object is sharing. And the properties must be read/write so that the serializer can get and set the value of the property. Here is an example of one of our messages:

public class NewUserRegistered : 
	CorrelatedBy< Guid >
{
	public Guid CorrelationId { get; set; }
	public string Username { get; set; }
	public string Email { get; set; }
	public DateTime RegisteredAt { get; set; }
}

Since messages are DTOs (data transfer objects), I try to keep them clean and simple. They are pure data containers and are not meant to have any behavior associated with them. While I treat my messages as immutable, I don’t find I need to express that in the message class itself since it just tends to make the object more confusing. And quite honestly, there are better ways to express immutable message contracts, such as using interfaces.

The resulting XML for the above message looks like:

<?xml encoding="utf-8" version="1.0"?>
<x:XmlMessageEnvelope 
	xmlns:x="MassTransit.Serialization.XmlMessageEnvelope, MassTransit"
	xmlns:m="MassTransit.Tests.Serialization.NewUserRegistered, MassTransit.Tests" 
	xmlns:s="System.String, mscorlib" 
	xmlns:d="System.DateTime, mscorlib" 
	xmlns:g="System.Guid, mscorlib" 
	xmlns:i="System.Int32, mscorlib">
  <m:Message>
    <s:Username>billg</s:Username>
    <s:Email>billg@microsoft.com</s:Email>
    <d:RegisteredAt >2009-05-27T13:50:21.106875Z</d:RegisteredAt>
    <g:CorrelationId >acb709df-7e32-45e2-a48c-9c160091aa5d</g:CorrelationId>
  </m:Message>
  <s:SourceAddress >loopback://localhost/source</s:SourceAddress>
  <s:DestinationAddress >loopback://localhost/destination</s:DestinationAddress>
  <s:MessageType >MassTransit.Tests.Serialization.NewUserRegistered, MassTransit.Tests</s:MessageType>
</x:XmlMessageEnvelope>

Namespaces are created for each type of object that is serialized. This makes it fast and easy for the deserialization process to figure out what type to use when reading the value from the XML. It’s easy to look and see the actual data that belongs to the message, as well as the headers used by MassTransit.

I wanted to post this as quickly as possible after committing the changes to the trunk so I will wrap up. I’m pretty excited about having a nice, readable message format. Since finding MSMQ Studio, I’ve really wanted to improve the diagnosis story for looking at messages inside the queues. I think this is a solid move towards that goal and a great first steps towards interoperability with other systems.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Chris Patterson

Chris is a senior architect for RelayHealth, the connectivity business of the nation's leading healthcare services company. There he is responsible for the architecture and development of applications and services that accelerate care delivery by connecting patients, providers, pharmacies, and financial institutions. Previously, he led the development of a new content delivery platform for TV Guide, enabling the launch of a new entertainment network seen on thousands of cable television systems. In his spare time, Chris is an active open-source developer and a primary contributor to MassTransit, a distributed application framework for .NET. In 2009, he was awarded the Most Valuable Professional award by Microsoft for his technical community contributions.
This entry was posted in .net, masstransit, msmq. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Ghost

    What about DataContractSerializer?

  • http://sharpoverride.blogspot.com Mihai

    You can instantiate objects that don’t have a default no-argument constructure just try FormatterServices.GetUninitializedObject(type) ;)

  • http://www.lostechies.com/members/phatboyg/default.aspx Chris Patterson

    @Ghost: Boo!

    @Mihai: I had used that previously when I was working on the protocol buffers implementation, but something about it didn’t feel right, maybe in the area of static fields or something? I could be wrong, maybe I need to take a look at it again if I can’t find a valid constructor.

    I’m also going to add support for {get; private set;} properties when I get around to it, just to make it easy for those that want to programatically prevent other classes from modifying the property values.

  • Greg Banister

    As an better alternative to MSMQ Studio You should check out Queue Explorer from http://www.cogin.com/
    Now since messages are serialized to XML I can use Queue Explorer to Edit those messages while on the queue draging and droping the messages from queue to queue.