BizTalk Server – How to Route Failed Messages to ESB on Send Ports where Delivery Notification is Enabled
The ESB Toolkit 2.1 Exception Handling Framework provides the ability to easily report and and alert on both routed failed messages (where Failed Message Routing is enabled on a Receive or Send Port), as well as ESBFaults created from exceptions within an Orchestration.
However, if you try routing failed messages on a Send Port that is bound to a Logical Port that has Delivery Notification enabled, you’ll get a Send Port failure with the following exception:
We’re expecting the routed failed message to be picked up by the All.Exceptions ESB Send Port (which subscribes to routed failed messages and ESBFaults and inserts them into the EsbExceptionDb), and from the error message, it’s clear that this Send Port is indeed subscribing to the message. But the exception never makes it into the database, and we get this routing failure. So at first it’s not clear what published message this error is referring to.
I knew that enabling Deliver Notification (in the logical Send Port defined in the Orchestration) was playing a part…
Taking a look at the failed message’s context properties sheds light on the issue…
The AckRequired context property is still set to true on the routed failed message that is picked up by the All.Exceptions ESB Send Port. This property is set to true whenever Delivery Notification is enabled, so that the Orchestration can subscribe to the resulting Ack or Nack message generated by the Send Port, and thus know whether the message was successfully delivered or not.
However, if there is a failure on that Send Port with failed message routing enabled, BizTalk sets the ErrorReport context properties (with error information) and routes the message. However, that routed failed message also retains all of its original context properties values, including the AckRequired property.
Therefore, when the All.Exceptions ESB Send Port processes the failed message and inserts it into EsbExceptionDb, it sees that AckRequired is true, and produces an Ack/Nack message and publishes it to the MessageBox. But because there are no subscribers to this Ack/Nacks coming from All.Exceptions, a routing failure occurs, and the Send Port performs a rollback of the original transaction (which inserted the failed message into the EsbExceptionDb), and suspends with the message due to no subscriber being found.
The solution is a simple addition to the All.Exceptions ESB Send Port filter. Add the following filter condition:
BTS.AckType Exists And
Adding this filter has the All.Exceptions Send Port subscribe to those same Ack/NAck messages it produces. But don’t worry, it doesn’t try to insert the resulting Ack/NAck into EsbExceptionDb. Instead, this Send Port simply ignores or discards the Ack/NAck message.