BizTalk and WCF, Consuming a WCF Service, Part 4 – Exception Handling
This is the last post in a four part series looking at BizTalk and WCF.
Here are the previous three posts:
In this final post, I will show how exception handling has been added to the RandomPresentService orchestration controlling our business process.
Some BizTalk Exception Considerations: 101 Course
Firstly, here is a quick brain dump of items that should be considered when thinking about handling exceptions in an orchestration:
- What are the customers requirements in regards to messages that fail inside BizTalk? Should alerting and/or logging be implemented so remedial action can be carried out and if so who should be the recipients of any such alerting? What steps should be carried out to recover from the error condition (what is the process)? Often the customer has only a vague idea here and some teasing out of requirements may be required.
- What is the impact if a particular process/action fails in your orchestration? Does this is invalidate subsequent previously successful actions? Should previously committed actions be rolled back therefore in a compensation block?
- What about business process type errors? Can these be handled without the need to jump to an exception condition? Preferably, business type errors that happen routinely (and are therefore not exceptional) should not be handled by throwing an exception but handled in the “body” of the orchestration.
- Do you need to handle any custom exceptions? Hopefully this is well documented in any service that needs to be consumed, for example.
Often error handling is forgotten until the very end of the development phase and is not instead considered at the start of a project – this is a mistake! Or alternatively, the customers requirements are not taken into consideration when building exception handling.
By thinking about exception handling at the start of a project, it can be “built in” to the solution. Also it allows time for discussions with the customer around how exceptions should be handled (in the analysis and design phase). It’s costly to implement exception handling logic retrospectively.
One of the big selling points in regards to BizTalk and another tenant of the platform is that it is “robust” and ensures “guaranteed message delivery”. In order to live up to these expectations it’s important that error conditions are handled in such a way that resubmission of failed messages is secured, with possibly multiple options for error recovery. These processes also need to be tested and well documented.
What Exceptions Need to Handled?
A concept that can be hard to determine is: what exceptions should my solution handle? By their very nature, exceptions are exceptional/rare so are a challenge to define and pin down.
It is a decision guided by some of the following factors:
- Experience – harnessed to try and make troubleshooting of “exceptional” type errors easier to investigate when the solution is running in Production.
- The needs of the customer.
- The type of exceptions that any called services could return.
This analysis will generate a list of exceptions that need to be handled.
As with any solution, the most specific exceptions should be handled first with the most general exception caught last.
And no doubt, not all exceptions will (or should) be catered for. They will generate a nasty runtime error that will require investigation using a tool like the Orchestration Debugger. This is where a good support team have a chance to shine :-).
Exception 1: PersistenceException
This is the first exception that I’m going to explicitly handle.
My friend and colleague Johann Cooper has written an excellent blog article about this exception.
Specifying direct binding on send ports in your orchestration is a good idea – this decouples physical send ports from the logical send ports specified in your orchestration. But this pattern can fail if the physical ports are ever unenlisted.
If physical ports are unenlisted, this removes any associated subscription and an exception of type Microsoft.XLANGs.BaseTypes.PersistenceException will manifest in the orchestration.
(You will also get a nonresumable “Routing Failure Report”, to help with troubleshooting the routing error).
So first up, I have modified the RandomPresentService orchestration like so:
- Added a non transactional scope shape around the send and receive shapes for the RandomPresentService WCF service.
- Added an exception block to the scope to handle the PersistenceException. This includes the creation of an ESB fault message (so the error will surface in the ESB exception management portal) and a suspend orchestration shape.
- Note the addition of looping: this ensures that the orchestration can be resumed in a valid state, since the RandomPresentService will be called again.
Exception 2: Handling SOAP Faults Returned from the RandomPresentService WCF Service
To handle any SOAP faults returned from the RandomPresentService service, I added a new fault type to the operation on the logical port in the orchestration designer (right click on the operation and select “New Fault Message”) and selected a message type of BTS.soap_envelope_1__2.Fault: this denotes that the fault should be wrapped in a SOAP version 1.2 fault:
The fault doesn’t need to be connected to a receive shape or anything like that – it can be left as is, and instead the fault can be handled by defining another exception block and selecting the SOAP fault as the “Exception Object Type”. When the fault is defined, it will subsequently be viewable in the “Exception Object Type” drop down, like so:
It’s important to handle SOAP faults: if not, this will cause an unhandled exception in your orchestration (due to an unexpected message type being returned) and it will not be possible to recover from this error by resuming the orchestration.
Also note that in order to extract the SOAP fault message, the orchestration XPath function can be used like this:
strFaultMsg = xpath(exSOAPFault, “string(/*[local-name()=’Fault’ and namespace-uri()=’http://schemas.xmlsoap.org/soap/envelope/’%5D/*%5Blocal-name()=’faultstring’ and namespace-uri()=”])”);
(Where strFaultMsg is of type System.String and exSOAPFault is of type Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults.FaultMessage).
Exception 3: Handling System.Exception – “Catch-all” Exception Blocks
The final exception block (that will be evaluated last by the orchestration engine) is a “catch all” block since it will handle exceptions of type System.Exception. Since all exceptions in .NET inherit from System.Exception, any errors, not previously handled explicitly by previous exception blocks, will be caught by this handler.
Also I have wrapped the entire orchestration in a global scope and specified one exception block for System.Exception to ensure than my default exception handling mechanism will be exercised.
So this concludes this four part series looking at BizTalk and WCF.
As is to be expected, WCF is interleaved tightly into the BizTalk framework and it is possible to leverage it heavily in your BizTalk solutions.
It’s been a journey looking at the creation of a WCF service; using the “out-of-the-box” BizTalk tooling to consume the service; building upon the artefacts created by the WCF Service Consuming Wizard; finally ending with this brief (!) look at implementing exception handling in the orchestration controlling the business process.
I hope it provides a good introduction to the subject!
(Both solutions are available under the terms of the MIT licence, a copy of which is included with each).