BizTalk: Sample: Error Handling

 

This sample shows the BizTalk features:

There are two big BizTalk artifacts where errors are
possible: orchestrations and ports.

Orchestrations are more customizable for error handling.
Ports handle errors in straightforward manner. Ports are not the place for diverse
logic.

Routing Failed Messages in ports

See the MSDN “Using Failed Message Routing” article with full description. Failed Message Routing is
a good feature which enables automatic error handling.  In short words, if there is an error in port
the original message is resubmitted to the MessageBox. The original message
context is erased; the ErrorReport context parameters are attached instead.

Here is how to turn on Failed Message Routing in Receive
Port:

Here is how to turn on Failed Message Routing in Send Port:



So, failed messages are resubmitted. What we should do with
these messages?

Of course we could catch the failed messages with any subscribers:
with Send ports or with Orchestrations. There is a difference in those
variants. Subscription filters on Send ports are configurable at run-time. Subscription
filters on Orchestrations are configurable only at design time, and
orchestration assembly redeployment is required. The second difference is, it
is easy to process the ErrorReport context in Orchestration, but hard to
implement in Send port, where custom pipeline component should be developed.

Catching Failed Messages with Send Port



Note: Send Port Filer
Values should be without quotes.

Catching Failed Messages with Orchestration



Note: Orchestration Filer
Values should be with quotes.

Handling Exceptions inside Orchestration

To handle exceptions orchestration get the Scope shape with
Exception handler blocks, with Compensation handler blocks, and several xLANG
operators. Compensation process is out of scope of this article.

Exception handlers catch the exceptions like catch C#
operators. That’s pretty much all we need.

If there is an error in Send or Receive port, port fires an
exception, and orchestration catches it.

Handling SOAP Fault messages inside Orchestration

Unfortunately the SOAP Faults are different from exceptions.

What is a SOAP Fault?

Let’s discuss it with an example. Client calls a Web-service.
For some reason WS fires an exception. This exception is serialized in special
SOAP Fault Message format and returned to the Client. Client proxy, which is
responsible for serializing requests and deserializing responses, deserializes
this SOAP Fault Message back to an exception. Client gets exception. Maybe this
exception is slightly different from original, but it feels as an original. It could be different because serialization->deserialization process is not unambiguous.

But BizTalk “proxy” does not deserialize the responses,
BizTalk deals with serialized messages in Xml format. Why deserialize if BizTalk internal message format is Xml.

Usual client calls the Web-service method (sends a request)
and gets a response or an exception. The exception serializing/deserializing is
hidden from client by the WCF infrastructure.

BizTalk sends an Xml request to the Web-service and gets an
Xml response or a SOAP Fault Message.

What is the difference?

The exception cannot be handled in Orchestration, because Orchestration
do not receive an exception on port but an unexpected message type (and
suspended orchestration instance):

Received unexpected
message type “http://schemas.xmlsoap.org/soap/envelope/#Fault” does not match
expected type http://GLD.Samples.ErrorHandling/EchoServiceWithFaultContract#EchoResponse

There are two variants in the Web-service consumption.

This is one Web-service:



This is second Web-service:



 There is a small difference in implementations. The second
one explicitly defines a FaultContract.

As a result, the BizTalk WCF Consume Wizard generates
different port types. The second one is with an additional ExceptionFault Fault Operation.


With respective Port shapes:



The second variant manages the SOAP Fault problem automaticaly. Now when we are creating an Exception
Handler block we see the new exception type for the SOAP Fault. All we need to do is to catch this exception.

What about the first variant? There should be some hand work:

  1. Create a new Multi-part Message Type. Choose for
    it from Schemas and the BTS.soap_envelope_1__1.Fault type (or 1__2 if the Web-service
    is using the SOAP 1.2 standard):
  2. Right-click the operation of the Port type and
    choose New Fault Message command.
    Use a new multi-part message type for it.
  3. Create a new Exception
    Handler block and choose an exception
    type of the BTS.soap_envelope_1__1.Fault. So we create a new port
    operation and this adds a new exception to drop-down list:



 

The Sample Inventory

Errors generation:

Errors processing:

The Sample Workflow

Errors generation:



WebServiceClient Orchestration is started by Start message then calls two Web-services: EchoService and EchoServiceWithFaultContract.

Depends of the Start message content, the first of the second Web-service throws an exception.

Exceptions are caught. The exception information is promoted in the context of an original message.


 
This message is sent to the MessageBox with Direct port.

Errors processing:

There are two workflows:

Get Fault Messages with Send Port

A special GLD.Samples.ErrorHandling.FaultMessages Send Port is subscribed to the Fault Messages. It
uses Filter for the ErrorReport.SendPortName parameter. In real life there
should be also Filters for the ErrorReport.ReceivePortName parameter for each
port which errors should be caught.

Now the Send Port stored all failed messages as files. The ErrorReport contex is lost.

Process Fault Messages with Orchestration and Web-service

An ErrorHandler Orchestration has the same Filter as a GLD.Samples.ErrorHandling.FaultMessages Send Port.

Orchestration creates an error report and sends it the ErrorProcessor Web-service, which
includes a real error processing like storing errors in database, firing the
events, etc. Now this Web-service is just stub.

Note:



So here the Orchestration “stores” all error information: the ErrorReport context and the original message.