BizTalk Server 2006 Failed Message Routing As a Blueprint
In BizTalk 2006, the
BizTalk product team tried to alleviate some of the issues that occurred
when application exceptions were generated in the messaging subsystem.
As mentioned earlier, the team introduced a new feature called Failed
Message Routing. For example, if the Enable routing on failed messages
check box option was enabled on either the BizTalk send or receive port
and a pipeline or routing failure occurred, then the BizTalk EPM would
do the following instead of suspending the message:
Create a cloned message and de-promote all the promoted properties.
Put an error description on the message context (e.g., "The Assembler component cannot load the schema named mySchema.xsd.").
Promote the failure-specific properties (e.g., ReceivePortName == "MyReceivePort", MessageType == "msgtype#mynamespace", FailureCode == "0x1824", etc.).
Try to publish this message.
Discard the original message if publishing succeeds.
Suspend the original message and generate NACK as usual if publishing fails because there is no subscription.
If you examine this feature
closely, you can see that it touches upon several of the common goals
that were previously defined. A similar feature, if created for use in
an orchestration, would provide a standard way to trap and report all
exceptions in a BizTalk environment.
For instance, consider the following scenario:
A user
submits an invoice to the system.During the course of processing the
invoice within an orchestration, the Business Rule Engine throws an
application exception because some piece of the data is incorrect. The
business process should catch the exception, send the offending message
to another person or system that can correct the message, and resubmit
the message for processing.
If a similar Failed Message Routing feature existed for orchestrations, perhaps it would work something like this:
The user creates a Fault message in the exception handler.
The
system puts an error description on the Fault message context (e.g.,
"The Business Rule Engine threw a divide/zero error processing the
LoanProcessing policy.").
The system promotes failure- and application-specific properties such as
Application (supplied by the developer)
Description (auto-populated—exception message)
ErrorType (auto-populated—exception type)
FailureCategory (supplied by the developer)
FailureCode (supplied by the developer)
FailureSeverity (supplied by the developer)
FailureDescription (supplied by the developer)
Scope (auto-populated—Scope shape of current exception handler)
ServiceName (auto-populated—orchestration name)
ServiceInstanceID (auto-populated—orchestration instance ID [GUID])
The system serializes the current Exception object into the Fault message.
The
user optionally adds current orchestration messages to the Fault
message, which are serialized and persisted (including their message
context properties), for example, AddMessage(FaultMsg, SomeMessage).
The user publishes the Fault message.
If publishing succeeds, orchestration or send port subscriptions can be deployed to process the Fault, rehydrating the Exception object as well as any added messages and message context properties.
If publishing succeeds, a global exception handler (send port) publishes the Fault message to a web portal.
Given this description
of a proposed Failed Message Routing feature for an orchestration, we'll
walk you through how you can provide a simple solution for the scenario
we just described.
This approach would look something like the following:
A developer is assigned responsibility for the recently deployed Financial Reporting BizTalk application.
A
new exception message arrives in the SharePoint-based exception
management portal indicating a data integrity issue with an
orchestration in the Financial Reporting BizTalk application.
The
developer is notified of the new exception either through his
subscription to the SharePoint application list or because the exception
exceeded a threshold predefined in BAM.
The
developer navigates to the SharePoint-based exception management portal
and examines the Fault message posted as well as the individual
orchestration messages and their context properties that were persisted.
The
developer determines that this will be a common error that will require
manual intervention and correction by the Finance team and resubmission
to the system.
The
developer creates and deploys an independent BizTalk orchestration
project that subscribes to the specific exception and application
information.
The
project is designed to retrieve the invalid message from the Fault
message, send the message to the Finance team for correction, and
correlate the corrected message back to the orchestration and resubmit.
A
week later, the developer navigates to the SharePoint-based exception
management portal to view that the application exception trends for
invalid messages have decreased dramatically since the deployment of his
solution.
A close examination
reveals obvious similarities between this proposed orchestration
functionality and the existing Failed Message Routing feature of BizTalk
Server 2006. In fact, if you were somehow able to incorporate this
feature, you would address the four design goals we discussed earlier in
the section, which we list again here for your convenience:
Standardize
how application exceptions are detected and caught in the BizTalk
environment, i.e., messaging and orchestration subsystems.
Provide common patterns that allow automated processes to react and manage application exceptions.
Provide a loosely coupled exception management pattern that facilitates reuse.
Develop
a common reporting paradigm of application exceptions and their
available message state that applies to any BizTalk subsystem.
Additionally, you could
use the same mechanism that would feed the exception metrics and portal
of your proposed solution to process all failed messages from the
messaging subsystem (provided Failed Message Routing is enabled). So
given the solution, we'll walk you through what it takes to develop it.
Failed Orchestration Routing API for BizTalk 2006
We'll show you
what the Failed Orchestration Routing API looks like when used to catch
an exception within an orchestration. First, you need to design a
simple orchestration that receives a message, does some processing, and
then simulates the generation of an exception within a Scope shape. Figure 3
depicts a simple orchestration named EAIProcess.Within this
orchestration, you have two messages available, one you receive that is
named ApprovedRequest, the other, DeniedRequest, that is created via a
map. Following the creation of the second message, you generate an
exception by dividing by zero by using the UnitPrice value located in
the incoming message. This orchestration would be like the one shown in Figure 3.
The orchestration in Figure 3
receives the ApprovedRequest message and executes a map to create the
DeniedRequest message. It then generates an exception by dividing by
zero. The EAIProcess sample resides with three projects within the
Msft.Samples.BizTalk.Exception- Management solution. These are listed in
Table 1.
Table 1 . List of Projects Within Exception Management Solution
Project Name | Description |
---|
BootCamp.Orchestration. Exception.Process | Contains
the EAIProcess orchestration schedule and references the
BootCamp.Orchestration.Exception.Schemas and Msft.Samples.
BizTalk.Exception.Schemas projects as well as the Msft.Samples.
BizTalk.Exception.dll assembly. |
BootCamp.Orchestration. Exception.Schemas | Contains the schemas and maps used by the EAIProcess orchestration. |
BootCamp.Orchestration. Exception.FaultHandler | Contains
two orchestrations (EAIGenericHandler, EAIProcessHandler) that
demonstrate strongly-typed and typeless options of using the Failed
Orchestration Routing API. Reference the
BootCamp.Orchestration.Exception.Schemas and Msft.Samples.
BizTalk.Exception.Schemas project as well as the Msft.Samples.
BizTalk.Exception.dll assembly. |
Add an exception handler to the Execution Scope shape and configure it to capture all System.Exceptions. Once the exception is generated, control will jump to the exception handler.
Within the exception handler, you need to follow a fairly simple methodology:
Add the ApprovedRequest message to the Fault message.
Add the DeniedRequest message to the Fault message.
Add the Exception object (caught by the exception handler) to the Fault message.
Publish the Fault message to the Messagebox.
So, how would you do this? By using an API to enable this functionality, which is embodied within the two projects listed in Table 2.
Table 2. Failed Orchestration Routing API Projects
Project Name | Description |
---|
Msft.Samples.BizTalk Exception | Contains all public methods for handling Fault-message processing within orchestrations. The public methods are CreateFaultMessage, AddMesssage, SetException, GetException, GetMessage, and GetMessages. This assembly must be registered in the local GAC. |
Msft.Samples.BizTalk. Exception.Schemas | Contains Fault message schema and system property schema. Deploys the BizTalk.Sample.ExceptionMgmt application container. |
The
Msft.Samples.BizTalk.Exception.Schemas project assembly must be
referenced by every BizTalk project that references or uses the Fault
message schema. It contains two schemas, one that defines an instance of
a Fault message (FaultMessage.xsd) and one that defines the property
schema (System-Properties.xsd). These must be deployed in the BizTalk
environment. The class outline is shown in Figure 4.
The
Msft.Samples.BizTalk.Exception.Schemas project must be referenced by all
BizTalk projects that need to create an instance of the Fault message
for publication. Many of the roperties have been promoted or defined as
distinguished properties.
For the developer, the
next step would be to define a Fault message using the FaultMessage.xsd
schema reference. Once the message variable is created (name it FaultMsg)
within the orchestration view window, an instance of it needs to be
created within the Exception Handler shape using the API exposed in the
Msft.Samples.BizTalk.Exception project.
Just as in the case of the
Msft.Samples.BizTalk.Exception.Schemas project, the Msft.
Samples.BizTalk.Exception project assembly must be referenced as well by
all BizTalk projects that need to use the API. The API exposes public
methods to create Fault messages, and manage and retrieve them for
processing, as described in Table 3.
Table 3. Public Failed Orchestration Routing API
Class.Method | Use Case | Description |
---|
ExceptionMgmt. CreateFaultMessage | Exception handler scope | public static XmlDocument CreateFaultMessage()
Accepts no arguments.
Returns an instance of the Fault message (XmlDocument),
populated with the current orchestration name and the orchestration
instance ID (GUID). |
ExceptionMgmt. AddMesssage | Exception handler scope | public static void AddMessage(XLANGMessage faultMsg, XLANGMessage message)
Accepts the created Fault message as the first argument. Accepts any
existing message instance within the orchestration as the second
argument. This method will persist the added message instance and its
message context properties into the Fault message and make it available
for later retrieval via the GetMessage() API. Returns void. |
ExceptionMgmt. SetException | Exception handler scope | public static void SetException(XLANGMessage faultMsg, Object exception) Accepts the created Fault message as the first argument. Accepts the existing Exception object caught within the exception handler as the second argument. This method will persist the Exception object into the Fault message and make it available for later retrieval via the GetException() API. Returns void. |
ExceptionMgmt. GetMessage | Subscriber/processor | public static XLANGMessage GetMessage (XLANGMessage faultMsg, string msgName)
Accepts the received (via subscription) Fault message as the first
argument. Accepts the name of the message previously added to the Fault
message from the originating Orchestration Exception Handler shape.
Returns the fully typed XLANGMessage that matches the msgName argument. The XLANGMessage will contain all original context properties, including custom promoted properties. |
ExceptionMgmt. GetMessages | Subscriber/processor | public static MessageCollection GetMessages (XLANGMessage faultMsg) Accepts the received (via subscription) Fault message as the argument. Returns a MessageCollection class populated with all
XLANGMessages previously added to the Fault message from the
originating Orchestration Exception Handler shape. The XLANGMessages
will contain all original context properties, including custom promoted
properties. |
ExceptionMgmt. GetException | Subscriber/processor | public static System.Exception GetException (XLANGMessage faultMsg) Accepts the received (via subscription) Fault message as the argument. Returns the System.Exception object previously added to the Fault message from the originating Orchestration Exception Handler shape. |
FaultSeverity | Exception handler scope and subscriber/processor | Exposes public properties simulating the following enumeration: enum FaultCodes { Information = 0, Warning = 1, Error = 2, Severe = 3, Critical = 4 } Used to either set or compare against the FaultSeverity value in the Fault message. |
MessageCollection | Subscriber/processor | Returned by the ExceptionMgmt.GetMessages API. This class derives from an ArrayList and implements an enumerator allowing MoveNext() operations. |
Using the APIs listed in Table 3,
you can add the following shapes to your exception handler and execute
the methodology previously discussed. Add the following to the
EAIProcess orchestration's exception handler:
Message Assignment shape enclosed within the Construct shape
Send shape (for Fault message)
Outbound Direct Bound Port (one-way) shape
Terminate shape
Send shape (for ApprovedRequest message)
Next, set the Construct shape to create a new Fault message. Name the Fault message variable FaultMsg.
Within the Message Assignment shape, add the following code:
// Create Fault exception message
FaultMsg.Body = Msft.Samples.BizTalk.Exception.ExceptionMgmt.CreateFaultMessage();
// Set Fault message properties
FaultMsg.Body.Application = "EAI Process Application";
FaultMsg.Body.FailureCategory = "MessageBuild";
FaultMsg.Body.FaultCode = "1001";
FaultMsg.Body.FaultDescription = "Some error occurred";
FaultMsg.Body.FaultSeverity = Msft.Samples.BizTalk.Exception.FaultSeverity.Severe;
FaultMsg.Body.Scope = "Execution Scope";
// Add each message you want to process later to the Fault message
Msft.Samples.BizTalk.Exception.ExceptionMgmt.AddMessage(FaultMsg,
ApprovedRequest);
Msft.Samples.BizTalk.Exception.ExceptionMgmt.AddMessage(FaultMsg,
DeniedRequest);
// Add the exception object you may want to inspect later to the Fault message
Msft.Samples.BizTalk.Exception.ExceptionMgmt.SetException(FaultMsg, _
sysExc);
Lastly, set the Message
property of the Send shape to use the FaultMsg message and connect the
Send shape with the Outbound Direct Bound Port. Once complete, the
orchestration should look like the one shown in Figure 5.
The orchestration described in Figure 5
receives the ApprovedRequest message and executes a map to create the
DeniedRequest message. Within the execution scope it generates an
exception by dividing by zero. An exception handler has been added to
the scope to build the Fault message, set the properties on it, and
publish it directly to the BizTalk Messagebox.