The Exception Handling API

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 fault message concept

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.

Fault messages originated by the messaging runtime

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

Fault messages explicitly instantiated in code

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:

  • Automatic fault properties: This schema defines the following properties for the fault message that are auto populated when the message is created:
    • Application: The name of the application where the fault happened
    • DateTime: The UTC moment in time when the fault happened
    • Description: The description of the exception that caused the fault
    • ErrorType: The type of fault
    • MachineName: The name of the server where the fault actually happened
    • Scope: The Scope shape that contains the current exception handler
    • ServiceName: The service where the message failed (orchestration name)
    • ServiceInstanceID: The GUID of the service instance within BizTalk where the fault happened
  • Explicit fault properties: Some more properties that have to be added explicitly in the code after the message is created. The values set in those will depend on our solution error definitions:
    • FaultCategory: The category of the fault
    • FaultCode: The code that identifies the specific type of fault
    • FaultSeverity: 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 message

    Note

    Note that leaving any of the fault properties with a null value will cause the serialization of the message to fail.

  • The exception: The exception that caused the fault itself gets automatically serialized into the fault message.
  • Attached messages: Using the Microsoft.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:

  1. Construct the fault message:
    • Use the 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.
    • Populate the FaultCategory, FaultCode, FaultSeverity, and FaultDescription properties.
    • Attach any messages that are relevant to the processing where the fault happened.
  2. Send the fault message to the message box through a direct bound send port, so any downstream subscribers process it. That port has to send messages of the multipart message type mentioned earlier.
    Fault messages explicitly instantiated in code

Fault messages published by other systems through the ESB Exceptions Service

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.

The fault canonical schema

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:

  • Header: This fragment contains the basic properties of the fault (some of those already described before in the chapter):
    • 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)
  • Exception Object: Is the serialized representation of the exception that caused the fault.
  • Messages: Contains any messages attached to the fault. This section includes the following properties of each message:
    • 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.

Exception Handling API main methods

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

    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).

Consuming fault messages

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.

Consuming fault messages

The ESB Fault Processor pipeline

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.

ESB Exception Encoder component

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.

ESB BAM Tracker component

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.

ESB Dispatcher

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.

Note

Note that the ALL.Exceptions port uses the legacy SQL Adapter, not the WCF-SQL Adapter.

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

Consuming a fault in an orchestration

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:

  1. We receive the fault message.
  2. We retrieve the messages attached to the fault.
  3. We construct a message for our production issues case management system and send it through.
  4. We wait to receive the result of the evaluation of the case.
    • If the case is evaluated within our defined SLA (Service Level Agreement, that could be set to 8 hours, and needless to say it shouldn't be hardcoded in a constant as a good coding practice), we check if the evaluation stated that the fault was caused by a bug in the solution.
    • If we have a bug, we create the corresponding TFS web services request and send it through to create the bug in TFS.
    • If it was not a bug, but caused by some invalid data in the message, the original message is sent to be repaired by the operations team.
    • If the SLA expires, the case is escalated by notifying it to the escalation manager.
    Consuming a fault in an orchestration
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.48.204