As we mentioned before, in order to provide a more convenient approach to handle our exceptions in BizTalk, we would need to write some custom code and define the patterns our development team should follow to use them. Over time this has been done by many teams around the world, but now there's no need to reinvent the wheel as this is provided by the ESB Toolkit.
The whole exception handling feature in the ESB Toolkit is built around the fault message concept.
A fault message is a special type of message that contains all the information about the failure that happened while processing at some point in our ESB. It's the canonical representation of a failure in the ESB, and contains all the relevant information about the fault and its schema is Microsoft.Practices.ESB.ExceptionHandling.Schemas.Reporting.FaultMessage
.
Failed messages can come from three different sources, and so they need to be normalized so any downstream components know how to handle them and the data they contain.
These are the already known failed messages generated by the Failed Messages Routing feature, which have the following properties added to their context:
FailureCode
FailureCategory
Description
MessageType
ReceivePortName
InboundTransportLocation
SendPortName
OutboundTransportLocation
ErrorType
RoutingFailureReportID
These are instantiated using the Microsoft.Practices.ESB.ExceptionHandling.ExceptionMgmt.CreateFaultMessage
method of the API within an exception handling block in an orchestration. This generates a new BizTalk message whose schema is Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults.FaultMessage
. The message has the following parts:
Application
: The name of the application where the fault happenedDateTime
: The UTC moment in time when the fault happenedDescription
: The description of the exception that caused the faultErrorType
: The type of faultMachineName
: The name of the server where the fault actually happenedScope
: The Scope
shape that contains the current exception handlerServiceName
: The service where the message failed (orchestration name)ServiceInstanceID
: The GUID of the service instance within BizTalk where the fault happenedFaultCategory
: The category of the faultFaultCode
: The code that identifies the specific type of faultFaultSeverity
: The severity of the fault (defined by the Microsoft.Practices.ESB.ExceptionHandling.FaultSeverity
enumeration)FaultDescription
: The description we want to give to the actual fault, that might be different from the exception messageMicrosoft.Practices.ESB.ExceptionHandling.ExceptionMgmt.AddMessage
method we can add the message or messages that were being processed when the exception happened. Those are added as additional parts to the fault message.In the following diagram, we can see the exception handling block of the EAIProcess.odx
sample orchestration included in the Exception Handling sample solution from the ESB Toolkit. On that block, the standard pattern to handle exceptions is followed and likewise can be replicated in your own orchestrations:
CreateFaultMessage
to instantiate the message. The destination message variable has to be of a multipart message type whose body part type is Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults.FaultMessage
.FaultCategory
, FaultCode
, FaultSeverity
, and FaultDescription
properties.These faults are received right away from external applications that might call the ESB Exceptions Service. This service just exposes the Microsoft.Practices.ESB.ExceptionHandling.Schemas.Reporting.FaultMessage
canonical schema, so the callers provide all the relevant information about the fault. We will explain more about the fault canonical schema in the next section, and about the ESB Exceptions Service by the end of the chapter.
As we mentioned earlier, this is the schema any fault message is converted to in order to homogenize the structure of the faults despite of where they were generated. The information is just pulled from the incoming fault message and populated into the following fragments of the message:
Application
Description
ErrorType
FailureCategory
FaultCode
FaultDescription
FaultSeverity
Scope
ServiceInstanceID
ServiceName
MachineName
DateTime
ControlBit
MessageID
ActivityIdentity
NACK
: Set to true
if the fault was caused by a NACK
FaultGenerator
: The type of service where the fault happened (for example, Messaging or Orchestration)ContentType
MessageName
RoutingURL
MessageContext
MessageID
InterchangeID
MessageType
MessageData
We will see later in this chapter how this transformation into the fault canonical form is undertaken by the Exception Encoder pipeline component.
The API exposes through the ESB.ExceptionHandling
assembly the methods required to deal with fault messages. Those methods are:
CreateFaultMessage
: Creates an ESB fault message as an XLANGMessage
instance with all the properties and data described in the previous section. It's meant to be used within an orchestration exception handling block.Note that the usage of the CreateFaultMessage
method outside of an exception handling block is not supported and will make your orchestration get into an endless loop and making the CPU go to 100 percent on the corresponding host instance process. If you really need to do it, the best option to do so without having to actually get into modifying the ESB Toolkit code is to throw your own exception when needed and keep using the method within an Exception Handling block.
We shouldn't consider approaches that imply disassembling and modifying the ESB Toolkit binaries, as that would break the software license.
AddMessage
: Takes as parameters two XLANGMessage
instances; the first is a newly-created ESB fault message, and the second is any existing message instance in the orchestration. The method persists the existing message instance and its message context properties into the fault message and makes it available for retrieval using the GetMessage
method. It's meant to be used within an orchestration exception handling block.SetException
: Takes as parameters an ESB fault message as an XLANGMessage
instance and Exception
as an Object
instance. The method persists the exception into the existing fault message and makes it available for retrieval using the GetException
method. It's meant to be used within an orchestration exception handling block.GetMessage
: Takes as parameters an ESB fault message as an XLANGMessage
instance and the (String) name of the message previously added to the fault message (in the exception handler of the originating orchestration shape). Returns an XLANGMessage
instance that matches the message name and that contains all the original context properties, including any custom promoted properties.GetMessages
: Takes as the single parameter an ESB fault message as an XLANGMessage
instance. Returns a MessageCollection
instance populated with all the XLANGMessage
instances previously added to the fault message (in the exception handler of the originating orchestration shape). Each XLANGMessage
instance contains all the original context properties, including any custom promoted properties.GetException
: Takes as the single parameter a fault message as an XLANGMessage
instance. Returns the System.Exception
object previously added to the fault message (in the exception handler of the originating orchestration shape).Earlier in the chapter we saw how to produce a fault message by means of the API. The counterpart of that process would be consuming the fault message in an orchestration or a port that subscribes to that fault message.
The ESB Toolkit includes a send port named ALL.Exceptions
that processes fault messages produced in any of the three ways mentioned before (messaging failure, orchestration exception handling or ESB Exceptions Service). The filter of that send port is quite simple, but we could create our own fault message subscribers, with more granular filters if required.
The ESB Toolkit includes a re-usable pipeline component, named ESB Exception Encoder, that can be used in our solution to process fault messages received by a send port and normalize them into the fault canonical form we described earlier in the chapter.
This pipeline component is used by the ESB Fault Processor pipeline, which is also included in the ESB Toolkit. This send pipeline also uses the ESB Dispatcher and ESB BAM Tracker pipeline components to prepare the fault messages to be published into the ESBExceptionDb
database. Finally, this pipeline is used by the ALL.Exceptions
send port to actually send those faults into that database. We will describe now the role played by each of the pipeline components used in the ESB Fault Processor pipeline.
This pipeline component has the duty of turning fault messages generated in three different ways (messaging failure, orchestration exception handling, or ESB Exceptions Service) into the fault canonical form, homogenizing their information and structure.
For fault messages generated in an orchestration or submitted by means of the ESB Exceptions Service, the component enriches and serializes all fault message properties, XLANG messages, context properties, and System.Exception
information into an XML message.
For fault messages coming from the Failed Message Routing executed in a messaging interaction, the component enriches the data by adding the application name and other ambient properties. It also applies the schema namespace to the outbound XML message content.
This pipeline component has three properties that can be configured on it:
FaultDocumentNamespace
. Defined the namespace of the fault message schema. By default it is http://schemas.microsoft.biztalk.practices.esb.com/exceptionhandling
but can be changed if we create our own custom outbound namespace for the persisted messages.ProcessingInstruction
: The ESB Toolkit includes a sample InfoPath
form where the fault messages can be viewed. In order to be displayed in the InfoPath
form, the fault messages XML has to include an InfoPath
processing instruction. The default processing instruction to be used with this sample form is the one shown as follows, but we can use our own to use our own InfoPath
forms:<?mso-infoPathSolution solutionVersion="1.0.0.346" productVersion="11.0.6565" PIVersion="1.0.0.0" href=file:///\localhostpublishMicrosoft.Practices.ESB.ExceptionHandling.InfoPath.Reporting.xsn name="urn:schemas-microsoft-com:office:infopath: Microsoft-Practices-ESB-ExceptionHandling-InfoPath-Reporting: http---schemas-microsoft-biztalk-practices-esb-com-exceptionhandling" language="en-us" ?><?mso-application progid="InfoPath.Document"?>
EscapeCDATA
: Any CDATA sections in the messages attached to the fault are escaped if this property is set to true
. This will allow InfoPath
to display them correctly.This pipeline component can be included in our own pipelines, by adding it to the Encode stage of them.
As we described in Chapter 2, Itinerary Services, this component can be used to capture fault messages information into our BAM database. The fields that are published as part of the corresponding activity record are Application
, ErrorType
, DateTime
, FailureCategory
, Description
, FaultCode
, FaultDescription
, FaultGenerator
, FaultSeverity
, MachineName
, Scope
, ServiceInstanceID
, ServiceName
, and MessageID
. The MessageID
field becomes the activity ID.
Through the component's properties, we can enable/disable the component (by means of the Enabled
property) or define a custom namespace for the fault messages (defined on the FaultDocumentNamespace
property), so the component can extract the data from our custom schemas.
The ALL.Exceptions
port delivers the fault messages to the ESBExceptionDb
database through the SQL adapter. The SQL adapter needs to receive a message in the form of an updategram, so it knows how to make the corresponding operations in SQL. The updategram structure used to insert faults information into the ESBExceptionsDb
is defined by the ExceptionSql.xsd
schema.
In consequence, our canonical form faults need to be transformed into that updategram. This is achieved by using the ESB Dispatcher component, with its MapName
property set to the corresponding map included in the ESB Toolkit:
Microsoft.Practices.ESB.ExceptionHandling.Maps.FaultMessage_to_ExceptionSql, Microsoft.Practices.ESB.ExceptionHandling.Maps, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c2c8b2b87f54180a
We can implement our own orchestrations subscribing to fault messages to make any processing that might be required (for example, it could orchestrate the interaction with our production issues case management system and our TFS bugs repository).
Using the Exception Handling API, we can access the messages that were being processed as well as the exception that originally caused the fault. With that information and the rest of the fault message properties, our exception handler can implement the process defined by the solution design of our operation's model.
In the following image, we can see a similar approach, where the process is as follows:
3.144.48.204