Dealing with Exceptions In BizTalk Orchestrations

BizTalk Server 2004 has some basic built-in functionalities for dealing with stuff that can go wrong, for example retries on an adapter for which you can specify the retry delay and retry count. But in many cases when you’re working with custom components, mappers, etc. on an Orchestration, you want to be able to catch exceptions. BizTalk has a shape which you can use for this, but before we’re going to take a look at it, let’s think about what we want to do if something goes wrong. Suppose you want to create a message containing information about the exception and send that message to a send port, additionally we want to include the message that caused the exception. And of course it would be nice if all of this stuff would be reusable in other BizTalk projects.

First of all we need to define the schema of the message we want to send: create a new empty BizTalk project (ExceptionMessage) and add a new Schema to it (name it Exception for example). Let’s add three nodes that will contain some metadata: Description (xs:string), TimeStamp (xs:dateTime) and Orchestration (xs:string). Finally we need to add a node that will contain the originating message: add a Child Record node under the root node and name it Message. Remember we want this solution to be reusable, so we can’t define at this point which schema the Message node will have; we want it to accept every schema. This can be accomplished by inserting a Any Element node under the Message node and setting the Process Contents property to Skip (no validation) and the Namespace property to ##any (any namespace). The BizTalk project containing our schema needs to get deployed, so we need to give it a strong name and then we can deploy it.

In fact now we can already use the Exception schema in an Orchestration, but let’s make our life a little more easier by creating some helper library that will let us easily create new Exception messages. This library is just an ordinary Class Library project which we will use from an Orchestration. So in VS.NET create a new Class Library project (ExceptionUtilities for example) and add following two classes to it:
using System;
using System.Xml;
namespace ExceptionUtilities
{
 [Serializable]
 public class ExceptionInfo
 {
  string _description;
  DateTime _timeStamp;
  string _orchestration;
  string _message;

  public ExceptionInfo()
  { this.TimeStamp = DateTime.Now; }

  public string Description
  {
   get {return _description;}
   set {_description = value;}
  }
  public DateTime TimeStamp
  {
   get {return _timeStamp;}
   set {_timeStamp = value;}
  }
  public string Orchestration
  {
   get {return _orchestration;}
   set {_orchestration = value;}
  }
  public string Message
  {
   get {return _message;}
   set {_message = value;}
  }
 }

 public class ExceptionHelper
 {
  public static void SetExceptionMessage
   (ExceptionInfo exInfo, XmlDocument msg)
  {
   exInfo.Message = msg.OuterXml;
  }

  public static System.Xml.XmlDocument
   GetMessage(ExceptionInfo exInfo)
  {
   string xml = string.Format(
    "<ns0:Exception xmlns:ns0='http://ExceptionMessage.Exception'>" +
    "  <Description>{0}</Description>" +
    "  <TimeStamp>{1}</TimeStamp>" +
    "  <Orchestration>{2}</Orchestration>" +
    "  <Message>{3}</Message>" +
    "</ns0:Exception>"
    , exInfo.Description, XmlConvert.ToString(exInfo.TimeStamp),
    exInfo.Orchestration, exInfo.Message );

   XmlDocument doc = new XmlDocument();
   doc.LoadXml(xml);
   return doc;
  }
 }
}

The ExceptionInfo class is just data class, containing only the four properties that correspond with the four nodes of the Exception schema. Only one important thing: the class is decorated with the Serializable attribute. This is important, it allows BizTalk to serialize the contents of an instance of that class to disk if something really bad happens (e.g. immediate shutdown) when this class is used in an Orchestration. You don’t have to use the Serializable attribute, you could also set the transaction type property of the Orchestration to Atomic but this could have consequences later on. The ExceptionHelper class is the class that will do the work for us. The SetExceptionMessage will add the contents of an XmlDocument, which will be a message in a BizTalk Orchestration in our case, to an ExceptionInfo instance. (You could ask yourself why this method isn’t implemented on the ExceptionInfo class. The short answer is: the XmlDocument class is not serializable.) The GetMessage method finally will construct an XmlDocument based on an ExceptionInfo instance. Notice that both methods are declared a static, so we don't need an instance of the ExceptionHelper class, so we don't need to bother about serialization issues. The ExceptionUtilities library is finished, give it a strong name and deploy it to the GAC so BizTalk will be able to use it.

You can use the ExceptionUtilities library in an Orchestration like this:

  • A simple message is received that contains two integer values.
  • The Scope shape contains an Expression shape that divided these two values.
  • The Catch block catches the DivideByZeroException, constructs a decent message and sends that message to a port.

To create a Catch block for a Scope shape, just right click on the icon of a Scope shape on your Orchestration and choose New Exception Handler. In the properties you can specify what type of exception to catch. The “Construct ExceptionInfo” Expression shape contains following expression:
ExceptionInfo.Description = "Something went wrong...";
ExceptionInfo.Orchestration = "TestExceptions.odx";
ExceptionUtilities.ExceptionHelper.SetExceptionMessage
     (ExceptionInfo, ValuesMessage);
The Assign shape in the “Construct exMessage” shape contains this expression:
exMessage =
 ExceptionUtilities.ExceptionHelper.GetMessage(ExceptionInfo);

If we feed the Orchestration a message that would result in a DivideByZeroException, a descriptive message is constructed that contains all the information we need to solve the problem.

21 Comments

Comments have been disabled for this content.