February 25, 2016
When it comes to processing zero-byte messages, the built-in receive adapters in BizTalk Server are somewhat inconsistent (see this recent post by Mark Brimble for more information). However, it seems that most receive adapters do not successfully process messages without body content. For example, the File adapter will delete an empty file and kindly put a notification to that effect in the event log. The HTTP adapter will reject a POST request with no content and return a 500 “Internal Server” error. So it probably isn’t any real surprise that the Azure Service Bus Messaging adapter introduced in BizTalk Server 2013 also obstructs bodiless messages. The difference here though is that the message will be successfully received from the queue or topic (and therefore removed from Service Bus), but will immediately be suspended with an error like the following:
A message received by adapter “SB-Messaging” on receive location “SB-ReceivePort_Queue_SB” with URI “sb://<namespace>.servicebus.windows.net/TestQueue” is suspended.
Error details: There was a failure executing the receive pipeline: “Microsoft.BizTalk.DefaultPipelines.PassThruReceive, Microsoft.BizTalk.DefaultPipelines, Version=126.96.36.199, Culture=neutral, PublicKeyToken=31bf3856ad364e35” Source: “Pipeline ” Receive Port: “SB-ReceivePort” URI: “sb://<namespace>.servicebus.windows.net/TestQueue” Reason: The Messaging Engine encountered an error while reading the message stream.
You will also see another error message recorded in the event log:
The Messaging Engine received an error from transport adapter “SB-Messaging” when notifying the adapter with the BatchComplete event. Reason “Object reference not set to an instance of an object.”.
And if you have message body tracking enabled on the receive port, you will also see this error message in the event log:
There was a failure executing the receive pipeline: “Microsoft.BizTalk.DefaultPipelines.PassThruReceive, Microsoft.BizTalk.DefaultPipelines, Version=188.8.131.52, Culture=neutral, PublicKeyToken=31bf3856ad364e35” Source: “Pipeline ” Receive Port: “SB-ReceivePort” URI: “sb://<namespace>.servicebus.windows.net/TestQueue” Reason: Cannot access a disposed object.
Object name: ‘CEventingReadStream’.
In the case of file based adapters, it seems pointless enough to process a message with no content, which is possibly why BizTalk rejects these. However, unlike empty files which are unlikely to have any meaningful dynamic context information besides the file name, a Service Bus message comes with a number of Brokered Message properties which are automatically added to the BizTalk message context by the SB-Messaging receive adapter. Aside from several standard properties, Brokered Message publishers can introduce any number of custom properties (up to a limit of 64KB). The BizTalk SB-Messaging receive adapter even allows you to promote these properties to a custom namespace when it is published to the MessageBox. Sometimes, these properties are all that is required for the transaction, particularly if it is used as a notification. Remember that not all BizTalk messages have to be XML; they can contain any content, including binary – as long as BizTalk is not expected to process the content. The MSDN documentation for XLANG message also says that it can have “zero or more message parts”.
So what exactly happens when BizTalk pops a message with no body off of a Service Bus queue? To test this out, I did the following:
- Created a Service Bus namespace and test queue in Azure and noted the ACS credentials. (Note: BizTalk Server 2013 R2 now also supports Shared Access Signatures for authorisation)
- Created a Receive Port and an SB-Messaging receive location in BizTalk and configured it to receive messages off of the queue
- Created a FILE send port that subscribes to messages from the Receive Port created in the previous step (to prevent persistence exceptions due to no subscription)
- Created a small console app to send a blank message to the queue; note that this only takes a couple of lines of code when using the Microsoft Azure Service Bus package available via Nuget:
- Ran the console application and observed the resulting suspended message and event log entry. Note that the custom BrokeredMessage property was automatically placed in the message context:
Remember also that once a message makes it through a receive adapter, it travels through a pipeline. A custom pipeline might contain components that process the context data in a message. In a recent case, we wanted to receive a message off a Service Bus queue that contained a timestamp and a BAM Activity ID within the Brokered Message properties and use it to finalise the BAM record. Our custom pipeline would read the properties from the message, close the BAM record, and then dispose of the message (as there was no need to persist it from this point on). Curiously enough, the pipeline processing succeeded. However, we still saw the 2nd error mentioned above appearing in the event log. So this proves that the error occurs after the pipeline handles the empty message without issue (provided your pipeline doesn’t contain a disassembler or other component that relies on the presence of a message body).
We could have chosen to ignore the errors, since we know our mission was still being accomplished (BAM record closed, and message was popped off of the queue). However this would introduce noise within a monitoring solution like BizTalk360 and potentially cause confusion for the support team. In the end, since the integration platform was the publisher of the Brokered Message anyway, we chose to introduce some content in the message body which alleviated the issue. However, this isn’t a great story because:
- Message sizes in Service Bus are limited to 256KB, so you need to take precautions that messages don’t exceed this length, and
- Sometimes you are not the publisher of the message and won’t have the option to control the body content.
I suppose another solution would be to write a custom adapter based on the existing SB-Messaging adapter that would gracefully handle an empty message, perhaps something along the lines of Nino Crudele’s proposed changes to the custom file adapter included in the SDK. But that’s a task for another day when there’s time to spare.