The ESB Exception Management Portal has made it a whole lot easier to drive exception handling and alerting within BizTalk applications however it does come at a price when you’re dealing with exceptions encountered on send ports. In order to route a failed message to the ESB Portal one must turn on routing for failed messages on the send port. While this results in the failed message being routed to the ESB Exception database along with the exception details, it also results in the messaging instance being terminated. This makes sense if the intention is to use the ESB Exception Management Portal for message resubmission however the out of the box sample portal contains many constraints that make this tedious (or impossible for context heavy messaging solutions) without extending the portal itself.
I was recently asked to implement exception handling for a solution that involves orchestrations that send out a message in a fire and forget fashion to the message box using direct binding which then get routed to a send port where it would get mapped and run through a flat file pipeline before being written to the file system. Retries were enabled on the send port and it was not envisioned that there would be problems on this send port unless there was a massive infrastructure failure in which case all the messaging instances would fail once retries were exhausted.
The customer was already using the ESB Portal for alerting on other BizTalk applications however none of those required resubmission or resumption of failed instances whereas this application did require these features. Routing the aforementioned exceptions to the ESB Portal would result in a very tedious resubmission cycle as the messages would have to be resubmitted one at a time, and because this is a very context heavy solution the ESB Portal’s resubmission feature would need to be extended to resubmit certain context properties as well as the message body. However disabling failed routing would mean that we couldn’t take advantage of the exception notification functionality which is part of the ESB stack and since we didn’t have access to SCOM or any other monitoring software this could mean that the problem might go unrecognized for a prolonged period of time delaying the isolation and resolution of the problem’s root cause.
After doing some research I managed to implement a pattern utilizing delivery notifications that allowed me to achieve my design goals (as below) without making any major changes to my existing application.
- Use direct binding within the orchestration on the logical send port
- Send out the message to the message box in a fire and forget fashion on the one-way logical port as the orchestration needs to carry on with further processing without waiting for an acknowledgement that the message was delivered
- Utilize BizTalk’s out of the box retry functionality on the send port
- Make use of the ESB Exception Portal and Notification service to surface and raise alerts for the exceptions
- Use the BizTalk Administration console to resume failed messaging instances on send ports
In order to implement this I had to whip up an orchestration which receives a message via direct binding, the activating receive shape having the below filters. The very fact that there is a component that subscribes to an acknowledgement (in this case very specifically a negative acknowledgement and very specifically from the send port named SendPort) means that the send port will now start generating acknowledgements of that specific type.
Doing this makes the orchestration subscribe to all negative acknowledgements generated by the send port named “SendPort”. The activating receive shape should receive a message which is of type System.XML.XMLDocument (I referred to this message as nACK in my orchestration).
I also added references to Microsoft.Practices.ESB.ExceptionHandling (at C:\Program Files (x86)\Microsoft BizTalk ESB Toolkit 2.1\Bin\Microsoft.Practices.ESB.ExceptionHandling.dll on my PC) and Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults (C:\Program Files (x86)\Microsoft BizTalk ESB Toolkit 2.1\Bin\Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults.dll) to my orchestration project. I then created a multi part message type who’s body was of type Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults.FaultMessage and created a message called eSBFault which is of this multi part message type.
Now we need to work on extracting the fault message. If you actually inspect a NACK message you will see that it is just a SOAPEnvelope message as below.
Next up I extracted the error message into an orchestration variable (faultMessage which is a string) by pasting the below into an orchestration expression shape.
faultMessage = xpath(nACK.Body, “string(/*[local-name()=’Envelope’ and namespace-uri()=’http://schemas.xmlsoap.org/soap/envelope/’%5D/*%5Blocal-name()=’Body’ and namespace-uri()=’http://schemas.xmlsoap.org/soap/envelope/’%5D/*%5Blocal-name()=’Fault’ and namespace-uri()=’http://schemas.xmlsoap.org/soap/envelope/’%5D/*%5Blocal-name()=’detail’ and namespace-uri()=”]/*[local-name()=’NACK’ and namespace-uri()=’http://schema.microsoft.com/BizTalk/2003/NACKMessage.xsd’%5D/*%5Blocal-name()=’ErrorDescription’ and namespace-uri()=”])”);
Now that we have the error message extracted I created another expression shape within a scope which throws a new System.Exception with the faultMessage as the exception message (code would look like – throw new System.Exception(faultMessage);”).
Next step is to create an exception block in the scope that catches a System.Exception. Now we want to construct our eSBFault message so create a construct shape for this message and drag in a message assignment shape. The code should look like the below.
Note the use of the BTS.AckOwnerID context property which allows us to expose the send port’s messaging instance ID which will help BizTalk support specialists identify the failed messaging instance. Also note that the message we are attaching to the fault is the NACK message as we do not have access to the original message that was sent to the send port (this is one weakness with this design pattern but the message is visible within the BizTalk Administration Console and this might suit your purposes just fine as it did mine).
Now we just need to send the eSBFault message to the message box with direct binding and it will be automatically routed to the ESB Exception database from which you can set up alerts. The orchestration should look somewhat like the below.
With the above implemented the NACKs will now be routed to the ESB Exception database and surfaced in the ESB Exception Management Portal as below, and you will be able to search for the suspended message instances within the BizTalk Administration Console and resume them once the root cause of the problem has been rectified.
If anyone out there knows other good exception handling patterns making use of the ESB Portal then I would definitely be keen to be told about them.
EDIT – I have now added a second part to this blog as myself and a colleague found ways to improve on this pattern (the above will still be relevant if you need the orchestration for additional processing before sending a message to the ESB Portal). Take a look at Part 2 here.