views:

29

answers:

1

In trying to implement simple integration patterns with Biztalk ESB Toolkit 2.0, I'm facing a problem trying to resolve a Transformation Itinerary Service that occurs after an Orchestration.

I'm using the BRE Resolver to execute rules that need to inspect the Context Message Type property to determine the appropriate map to use. However, once the message reaches the step in the Itinerary associated with the Transformation Service, the map fails to execute.

From careful investigation, it appears that the message type is not supplied to the "Resolution" object that is used internally by the BRE resolver. Indeed, since the message leaving the preceding Orchestration is typed System.Xml.XmlDocument, the type of the message is "demoted" from the context.

By tracking rules engine execution, I can observe that the type of the message is indeed lost when reaching the BRE resolver. The type of the message is empty, whereas the strongly-typed of the document is Microsoft.XLANGs.BaseTypes.Any.

The Orchestration service that I use is taken straight from the samples that ship with ESB Toolkit 2.0.

Is there a way to perform Context-Based BRE resolution after an Orchestration in an Itinerary?

A: 

Answering my own question... in short, the key is to preverse the context of the original message and to promote the MessageType context property. In the following paragraphs, I reproduce a forthcoming post on my blog:

Orchestration Itinerary Service 101

After struggling to make this work and trying different solutions, I finally succeeded with a set of simple rules to follow. In this post, I would like to outline what constitutes a well-behaved ESB Toolkit 2.0-friendly orchestration that can be used as an Itinerary service and still take advantage of the Business Rules Engine Resolver for dynamic transformation based upon the context type of a message.

Context Subscription for an Itinerary Service

First, an orchestration designed to be used as an Itinerary service need to have a direct-bound logical port, linked to a receive shape that defines a ESB-friendly subscription like so:

Microsoft.Practices.ESB.Itinerary.Schemas.ServiceName == "MyCustomItineraryService" And
Microsoft.Practices.ESB.Itinerary.Schemas.ServiceState == "Pending" And
Microsoft.Practices.ESB.Itinerary.Schemas.ServiceType == "Orchestration"

The documentation does not mention this, but this makes it clear that the direct-bound port operations need to be mapped to messages of type System.Xml.XmlDocument. Indeed, if that is not the case, the orchestration will fail to be executed and a Routing Failure error message will be registered to the Message Box.

Incidentally, this means that the very type of a message does not enter into account at all. And this largely explains why, after execution of the orchestration, the Business Rules Engine resolver fails to determine the correct transformation.

Getting at the Itinerary

The following code in an Expression Shape at the beginning of the orchestration helps retrieve the current Itinerary step:

// Retrieve the current itinerary step.
itinerary.Itinerary = Microsoft.Practices.ESB.Itinerary.ItineraryOMFactory.Create(InboundMessage);
itineraryStep.ItineraryStep = itinerary.Itinerary.GetItineraryStep(InboundMessage);

Preserving the Context of the Original Message

Next, the context of the original message must be preserved (for the most part) at each step of the orchestration. This is of particular importance when having several intermediate construct shapes in the orchestration to carry out the specific scenario at hand.

OutboundMessage(*) = SourceMessage(*)

Notice that I wrote "for the most part" in the sentence above. In fact, as we'll see in a minute, the type of the resulting message need to be present in the context at the end of the orchestration. Most probably, this will be a different type than the original inbound message. And since assigning to the read-only BTS.MessageType property is not possible, this can be quite tricky to achieve sometimes.

You might have to resort to execute a custom pipeline inside the orchestration or other exotic techniques for this to be the case. Most of the times, however, the syntax shown above should work.

Advancing the Itinerary

The following very straightforward code must not be forgotten at the end of the orchestration:

itinerary.Itinerary.Advance(OutboundMessage, itineraryStep.ItineraryStep);

Promoting Context Properties

The documentation does not spell out quite cleary what exact steps must be followed, or even if properties need to be promoted from such an orchestration, but looking at the samples provided as source code, one can find that the following properties take part in the resolution mechanism:

Promoting Properties

However, in the scenario outlined in this post this is definitely not enough.

For context-based rules to work after the orchestration, the BTS.MessageType property need to be promoted as well. This can be easily achieved by initializing a correlation on the send shape at the end of the orchestration.

Message Type Correlation

And it works!

Promoting the message type in the context of the resulting message was what was missing in my original attempt. Once this was identified, the itinerary worked like a charm !

Rule Firing Log

Even though the solution might seem obvious after the fact, it sure would have helped me if I had known that earlier. I hope this post will help those hitting the same problem.

Maxime Labelle