How to build a Babel fish in NServiceBus

This post is part of a series describing the improvements in NServiceBus 6.

I'll admit it: I'm a huge fan of The Hitchhiker's Guide to the Galaxy. I've voted for Zaphod Beeblebrox in more than one election and had a cat in college named The Ravenous Bugblatter Beast (Rav, for short). True to her name, she was an adept and ruthless hunter of cockroaches.

One of the more clever beasts in the book is the Babel fish, a small leech-like creature that, when inserted into your ear, allows you to communicate with any other creature in the universe in any language. It feeds on brain wave energy, and no matter what language is spoken to you, it is automatically converted into one you understand.

Try this at home kids!
Fish Bowl Fish Tank Aquarium Goldfish Jump by audiencestack.com, reused via CC by 2.0 license

If you've done any significant amount of systems integration in your career, this may sound familiar. As your system grows and integrates with more and more applications, it needs to understand more and more formats. Initially, it understands JSON natively. Later, through a merger, it has to accept input from an accounting system that exports only in XML. Then the company purchases an HR system that speaks some proprietary format: say, the binary language of moisture vaporators.

Adding support for new formats to a system can be a challenge as time goes on. If you don't plan ahead, you can end up with a lot of custom code sprinkled throughout your application, increasing the cost of maintenance.

So with NServiceBus 6, we set out to make this process easier.

Building a better Babel fish

In NServiceBus 6, endpoints can be easily configured to support multiple message deserializers. In this example, we register both a JSON and an XML deserializer on an endpoint:

var salesEndpointConfiguration = new EndpointConfiguration("SalesEndpoint");

// setup the primary serializer and deserializer
salesEndpointConfiguration.UseSerialization<JsonSerializer>();

// setup additional deserializer
salesEndpointConfiguration.AddDeserializer<XmlSerializer>();

With this configuration, an endpoint can receive messages in either JSON or XML format and they will get processed in the same way.

The support for multiple message deserializers in NServiceBus 6 is really just an expression of the robustness principle, also known as Postel's Law: Be conservative in what you send, be liberal in what you accept. In the example above, our endpoint can accept messages serialized either with JSON or XML. As you can see, we could easily add support for additional formats using endpointConfiguration.AddDeserializer<T>().

How does it work?

Each message serializer contains an identifying value called Content-Type. When messages are serialized, the Content-Type is included with the message so that receiving endpoints can identify how a message was serialized. By registering a deserializer on our receiving endpoints, the Content-Type of each incoming message is matched to the correct deserializer for that message.

By default, .UseSerialization<T>() will configure both a serializer and a deserializer for that NServiceBus endpoint. Enabling additional deserializers for an endpoint is done via the AddDeserializer<T>() method on the EndpointConfiguration, as we saw above. This method can be called multiple times---once for each additional deserializer you want to add. Presto! Instant Babel fish.

In NServiceBus 6, support for multiple deserializers is a first class citizen, but you can still make it work in NServiceBus 5 by customizing the message pipeline. A full code sample showing how to do this is available in our documentation.

The sample also shows how to specify a serializer based on the message type. This can be useful in scenarios where you have no control over the format that is accepted by an external system.

Other formats

While we've highlighted the built-in XML and JSON deserializers because these formats are the most common, there are several others you could use, depending on the needs of your project. Protocol Buffers, ZeroFormatter, and Message Pack are three that are focused on speed. These are external deserializers created by the community, and they allow you to quickly add support for one of these formats with only a call to AddDeserializer<T>().

For cases where none of the built-in serializers meet your exact requirements, such as a proprietary binary format, you can even implement your own custom serializer. Check out our customer serializer sample for more information.

Summary

NServiceBus 6 simplifies support for multiple deserialization types. Come and see how easy it is to put a Babel fish in your ear - Download NServiceBus 6 now.


About the authors: Hadi Eskandari and Kyle Baley are engineers at Particular Software. One of them is an avid photographer and the other likes playing show tunes on the piano, but they aren't saying which is which.