Here's another reminder to myself when writing BizTalk Adapters: When creating a receive-side BizTalk adapter, you need to be extra careful about when you can release (clean up) a message part data stream.
There are two particular scenarios that I've seen cause trouble for adapters when trying to implement message suspension on submit failures:
1. You release the message part data streams too early. This mistake is very easy to make when using the base adapter in the BizTalk SDK, because it is not clear about when it is done processing a message. So what might happen is that you end up releasing the data streams after the failed submit batch is done, but before the suspension batch is committed, so that the messaging engine is left with a disposed stream in the middle of an operation.
Be careful about ensuring you're all clear before cleaning up after yourself.
2. Ensure that data streams are readable before suspending messages.
Another common error I've seen is using non-seekable streams as message part data streams. When you first submit a message from your adapter, and it fails, it's very likely that the data stream has been partially or completely consumed during submission (for example, by a disassembler component in the pipeline). If you have a non-seekable data stream, and you simply take the same failed message as is and submit it in a second batch to the suspend queue, it will fail, because the messaging engine cannot read the entire message contents anymore to save them.
So if you find yourself in this scenario, be prepared to recreate the data streams after the initial submission failed and before the second one.
Either of these problems can cause some really weird errors during processing including:
- The Messaging Engine received an error from transport adapter "XXX" when notifying the adapter with the BatchComplete event. Reason "Exception from HRESULT: 0x80C0169C".
- The transport batch from adapter "XXX" has been rejected by the messaging engine because the batch is empty. Contact the adapter provider to find out why the transport batch is empty.