Friday 2 February 2018

Azure Service Bus - interoperable serialization

We had a problem where we were serializing a message to ASB but the Mulesoft client was failing to deserialize. It was performing a byte[] to string conversion.

The problem is that we are writing things like @ string 3http://schemas.microsoft.com/2003/10/Serialization/
on the wire, and the client’s Byte[] to string is serializing it back badly.

There are numerous discussions about interoperability.
There is a difference in behaviour between the ASB SDKs (nice!).
This article explains the solution if you want to write bytes directly to ASB.
Service Bus Explorer hides the problem. It doesn’t show the prefix bytes. If you read the binary bytes back they are there.
You can fix the problem by code in the subscriber , but this ignores the fact those bytes are still there. Subscriber fixes isn't very interoperable (after all does Java care about a
@ string 3http://schemas.microsoft.com/2003/10/Serialization/
?

Summary solution: you have to pass a stream for serialization. Anything else (string, byte array, object) and BrokeredMessage will apply a DataContractSerializer which will append the byte and schema declation beforehand.

This works:

var order = new SubmitOrder() { OrderRef = Guid.NewGuid().ToString() };
          
           var json = JsonConvert.SerializeObject(order);
           var data = Encoding.UTF8.GetBytes(json);
          
           using (var ms = new MemoryStream())
           {
                ms.Write(data, 0, data.Length);
               
                ms.Seek(0, SeekOrigin.Begin);
                BrokeredMessage msg = new BrokeredMessage(ms);
                msg.Label = order.OrderRef;
                sender.Send(msg);
           }

Converting to a string doesn’t work:
var order = new SubmitOrder() { OrderRef = Guid.NewGuid().ToString() };
          
           var json = JsonConvert.SerializeObject(order);
          
           BrokeredMessage msg = new BrokeredMessage(json);
           msg.Label = order.OrderRef;
           sender.Send(msg);

Nor does directly serializing the object:
var order = new SubmitOrder() { OrderRef = Guid.NewGuid().ToString() };
          
           BrokeredMessage msg = new BrokeredMessage(order);
           msg.Label = order.OrderRef;
           sender.Send(msg);



https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messages-payloads

The bad data looked like:
0x40 0x06 0x73 0x74 0x72 0x69 0x6e 0x67 0x08 0x33 0x68 0x74 0x74 0x70 0x3a 0x2f 0x2f 0x73 0x63 0x68 0x65 0x6d 0x61 0x73 0x2e 0x6d 0x69 0x63 0x72 0x6f 0x73 0x6f 0x66 0x74 0x2e 0x63 0x6f 0x6d 0x2f 0x32 0x30 0x30 0x33 0x2f 0x31 0x30 0x2f 0x53 0x65 0x72 0x69 0x61 0x6c 0x69 0x7a 0x61 0x74 0x69 0x6f 0x6e 0x2f 0x99 0x33 0x7b 0x22 0x4f 0x72 0x64 0x65 0x72 0x52 0x65 0x66 0x22 0x3a 0x22 0x39 0x33 0x38 0x61 0x65 0x32 0x32 0x62 0x2d 0x66 0x39 0x36 0x65 0x2d 0x34 0x37 0x65 0x32 0x2d 0x61 0x38 0x31 0x37 0x2d 0x31 0x64 0x31 0x30 0x63 0x31 0x62 0x61 0x35 0x61 0x61 0x35 0x22 0x7d

?@? ?s?t?r?i?n?g? ?3?h?t?t?p?:?/?/?s?c?h?e?m?a?s?.?m?i?c?r?o?s?o?f?t?.?c?o?m?/?2?0?0?3?/?1?0?/?S?e?r?i?a?l?i?z?a?t?i?o?n?/?™?3?{?"?O?r?d?e?r?R?e?f?"?:?"?9?3?8?a?e?2?2?b?-?f?9?6?e?-?4?7?e?2?-?a?8?1?7?-?1?d?1?0?c?1?b?a?5?a?a?5?"?}

The working data looked like:
0x7b 0x22 0x4f 0x72 0x64 0x65 0x72 0x52 0x65 0x66 0x22 0x3a 0x22 0x66 0x30 0x63 0x31 0x66 0x32 0x38 0x62 0x2d 0x63 0x35 0x33 0x64 0x2d 0x34 0x32 0x63 0x62 0x2d 0x39 0x65 0x31 0x37 0x2d 0x66 0x33 0x35 0x39 0x35 0x31 0x39 0x30 0x62 0x38 0x66 0x38 0x22 0x7d

?{?"?O?r?d?e?r?R?e?f?"?:?"?f?0?c?1?f?2?8?b?-?c?5?3?d?-?4?2?c?b?-?9?e?1?7?-?f?3?5?9?5?1?9?0?b?8?f?8?"?}

This link probably describes the problem the best and offers a solution.

No comments:

Post a Comment