2
votes

I'm looking for a way to publish events from our new NServiceBus 6 endpoint environment to an older v4 endpoint environment. To make matters more interesting, the v6 is using JSON and the v4 is using XML.

  • Do I need to simply add a mutator on the incoming v4 endpoint?
  • How do I convert the JSON message to an XML message? In the above mentioned mutator?
  • Do I need to add any specific v4 message headers on the outgoing event message?

I'm using MSMQ as the underlying transport layer.

1
v4 already supports multiple serializers docs.particular.net/nservicebus/serialization/?version=core_4 Why not switch the v4 endpoint to Json as well? Or do you still have senders that send in Xml to that endpoint? If yes then what drove you to switch to Json in v6?Daniel Marbach
Our switch to v6 and JSON is fueled by a redesign of our entire system and replacing parts, 1 at a time. JSON was chosen because this is what we use in our communication on our REST endpoints, Java endpoints, ...Bjorn Bailleul
I will try to come up with something in a short timeframe. In the meantime have you tried using newtonsoft.com/json/help/html/ConvertingJSONandXML.htm ?Daniel Marbach

1 Answers

1
votes

Potentially the simplest way to move forward is to write a custom serializer definition. The following example assumes the default XmlSerializer and JsonSerializer available in NServiceBus v6 are used.

Write a custom serializer definition

public class CustomJsonSerializer : SerializationDefinition
{
    public override Func<IMessageMapper, IMessageSerializer> Configure(ReadOnlySettings settings)
    {
        var xmlSerializerDefinition = new XmlSerializer();
        var xmlSerializerFactory = xmlSerializerDefinition.Configure(settings);

        var jsonSerializerDefinition = new JsonSerializer();
        var jsonSerializerFactory = jsonSerializerDefinition.Configure(settings);
        return mapper => new DecoratorSerializer(xmlSerializerFactory(mapper), jsonSerializerFactory(mapper));
    }
}

Write a serializer decorator that has custom logic to forward message types to the XmlSerializer if they are targetted towards the V4 endpoint.

class DecoratorSerializer : IMessageSerializer
{
    IMessageSerializer xmlSerializer;
    IMessageSerializer jsonSerializer;

    public DecoratorSerializer(IMessageSerializer xmlSerializer, IMessageSerializer jsonSerializer)
    {
        this.xmlSerializer = xmlSerializer;
        this.jsonSerializer = jsonSerializer;
    }

    public void Serialize(object message, Stream stream)
    {
        if (message.GetType() == typeof(MyMessage))
        {
            xmlSerializer.Serialize(message, stream);
        }
        else
        {
            jsonSerializer.Serialize(message, stream);
        }
    }

    public object[] Deserialize(Stream stream, IList<Type> messageTypes = null)
    {
        return jsonSerializer.Deserialize(stream, messageTypes);
    }

    public string ContentType
    {
        get { return jsonSerializer.ContentType; }
    }
}

use the CustomSerializer like the following

endpointConfiguration.UseSerializer<CustomJsonSerializer>();

A working sample can be found on this github repo. The sample uses commands but the approach should also work for PubSub. The only caveat is that a specific message type will always use one format. So it is not possible to publish the same event once in Xml and for other publishes in Json.