BizTalk rewinds the interchange if exception is throw in send pipeline
Found an very interesting problem today. It is about a scenario that,
- In the receive side, we disassemble an inbound interchange by wrapping FF disassembler component, perform some business logic
- In the send side, we wrap FF assemble component to serialize the message to text then call the middle tier, which will do the validation on the text. The middle tier may throw exception in some cases.
Natively, in the assemble stage, if the pipeline component throw an exception, the message is suspended (which is perfectly fine) However, we discover this weird problem, let’s say the interchange has messages 1,2,3,4,5, upon calling middle tier and get an exception, the 3rd message gets an error, the pipeline component throw the exception back to BizTalk. What we observe in the debug view is, the sequence BizTalk process is 1,2,3,4,5,1,2. For some weird reason, BizTalk is looping back again to the failed message until it realize the 3rd is an invalid message.
Interestingly, when we hookup the send pipeline with the file adapter, we actually see 4 messages, with 1 message (the 3rd one) suspended. However, again, in the debugview apparently BizTalk rewind back again and retried 1st and 2nd message but it does not deliver them to the adapter.This may not be a problem at all since the rewind of BizTalk does not produce duplicated message at endpoint. But for a large interchange, consider the failing one is the last message, this is a huge problem from performance perspective.
We also found when the adapter is set to be order deliver, the rewind behavior of BizTalk never happens. But problem for going this route is any message is going suspended none resumable state, which is unacceptable since we requires it to be resuamble.
So how to suspend a message without letting BizTalk rewind the interchange? Apparently throw an exception does not work. Initialilly we thought there got to be some properties to set to route an message to suspend queue. We tried MessageDestination and SuspendAsNoneResuamble. Both does not work. Until we finally find a workaround that, instead of throw an exception, create an empty message and return it to BizTalk. BizTalk will suspend that very message of the interchange, while on the other hand, never rewind back again.
I can’t explain why it works…