Click here to Skip to main content
14,093,107 members
Click here to Skip to main content
Add your own
alternative version

Tagged as


9 bookmarked
Posted 7 Dec 2011
Licenced CPOL

Classic publisher-subscriber solution using BizTalk Server 2010 and ESB Toolkit 2.1

, 8 Dec 2011
Rate this:
Please Sign up or sign in to vote.
This article attempts to provide an alternative solution for the classic publisher-subscriber problem using ESB toolkit.

Are you New to BizTalk Enterprise Service Bus (ESB) 2.1 Toolkit?

If yes, please read up on my 'Hello World' to ESB article which takes you on an introductory route.

Case Study: A Simple Publisher-subscriber Scenario

Consider a scenario where a Contact information needs to be published to several subscribers. The problem is to send a contact update message to multiple subscribers. The classic way of solving this problem is to, have a message broker orchestration place several messages onto the message box. These messages would then be consumed by the Send port subscriptions or other orchestrations as deemed fit in the tailored solution.

In this article, I am trying to suggest a different solution using the ESB toolkit.


Consider a scenario where a custom contact update message needs to be sent to multiple subscribers. The subscribers here are two CRM systems. The idea is to first transform the message into a canonical form (like a generic contact). This canonical contact is then transformed into the respective CRM specific formats.

The Custom Contact Message

The Custom contact message is NOT in canonical form, this is the RAW XML received from the application. This message has to be transformed into a canonical form using a transformation map.


Understanding the Itinerary

What are the Advantages of Using an Itinerary in this Case?

  • A new subscriber can be added to the Itinerary without any modifications to the existing BizTalk deployment configuration.
  • The subscriber end points can be changed using the BRE rules.
  • The subscriber data formats (maps) can be changed using the BRE rules.


  1. ESB On-Ramp: An ESB on-ramp receives the message. This is the custom contact message which needs to be transformed into a canonical form.
  2. ESB Message Extender: This shape is used to transform the custom contact message into a canonical contact.
  3. ESB Orchestration Extender: This shape is used to process the canonical contact using an orchestration and dispatch it, using a list of subscribers. The resolvers list down the list of subscribers.
  4. ESB Off-Ramp Extender: The off ramp extender is used to archive the canonical message into the archive folder.
  5. ESB Off-Ramp: A BizTalk Server dynamic send port, which is also referred to as an ESB off-ramp is used to place the canonical message into the archive folder.

How are the Transformation Maps Located from the Itinerary?


The transformation maps are located using a BRE resolver policy from the Itinerary shape resolver configuration. The BRE policy would look like this, notice the maps fully qualified name.

BRE Policy : ContactCanonicalMap

If Context_Receive_Port_Name == "ContactInfo" and _
    Context_Receive_Location_name == "ContextLocation:FILE"
Set Transform_Type To "MyCustomerSchema.CustomerContact_To_ContactCanonical_Map, _
    MyCustomerSchema, Version=, Culture=neutral, PublicKeyToken=2710b190689828fa"

The BizTalk ESB Compatible 'Dispatcher' Orchestration

Step 1: Message Box Binding

A logical receive port, bound directly to the message box is required for receiving ESB messages. The Contact canonical message is received by the orchestration.

Step 2: Coding the Meat of the Orchestration

The Orchestration has been broken up into two sections for brevity. One for resolver processing and another for advancing the Itinerary.


// Itinerary - Initialize
itineraryWrapper = new Microsoft.Practices.ESB.Itinerary.SerializableItineraryWrapper();
itineraryStepWrapper = 
    new Microsoft.Practices.ESB.Itinerary.SerializableItineraryStepWrapper();

// Itinerary - Assign
itineraryWrapper.Itinerary = 
itineraryStepWrapper.ItineraryStep = itineraryWrapper.Itinerary.GetItineraryStep(InboundMsg);

// Itinerary - Extract
hasNextService = itineraryWrapper.Itinerary.HasNextService();
resolvers = itineraryStepWrapper.ItineraryStep.ResolverCollection;

// Resolver - Count
System.Diagnostics.Trace.WriteLine("Resolver count: " + 
System.Convert.ToString(resolvers.Count), eventSource);

Section 1: Iterate Through all the Resolvers

This is the most critical piece of the orchestration. The idea is to iterate through all the resolvers and assign the transformed message to the dynamic send port.


// Move to retrieve first resolver
resolver = resolvers.Current;

// Pass the resolver configuration to the Resolver mgr for resolution
resolverDictionary = 
    Microsoft.Practices.ESB.Resolver.ResolverMgr.Resolve(InboundMsg, resolver);

// set transport properties
transportLocation = resolverDictionary.Item("Resolver.TransportLocation");
transportType = resolverDictionary.Item("Resolver.TransportType");
mapType = resolverDictionary.Item("Resolver.TransformType");

Custom Logic: You can add custom piece of logic to determine suitable subscribers based on certain rules.

//Retrieve map type from resolution structure
mapCLRType = System.Type.GetType(mapType);
transform(OutboundMsg) = mapCLRType(InboundMsg);
OutboundMsg(*) = InboundMsg(*);

Microsoft.Practices.ESB.Adapter.AdapterMgr.SetEndpoint(resolverDictionary, OutboundMsg);
// Set delivery port address
RoutingDynamicPort(Microsoft.XLANGs.BaseTypes.Address) = transportLocation;
RoutingDynamicPort(Microsoft.XLANGs.BaseTypes.TransportType) = transportType;

Section 2: Advance the Itinerary to the Next Step

This operation shall send the message back to the Itinerary to perform additional steps. If the Itinerary has no other additional steps, the operation won't be executed.

OutboundMsg.Body = InboundMsg.Body;
OutboundMsg(*) = InboundMsg(*);

itineraryWrapper.Itinerary.Advance(OutboundMsg, itineraryStepWrapper.ItineraryStep);

System.Diagnostics.EventLog.WriteEntry(eventSource, "Message posted back to ESB.");

Step 3: Adding Entries in esb.config

Locate the esb.config under C:\Program Files (x86)\Microsoft BizTalk ESB Toolkit 2.1, find the XML tag itineraryServices and add the following:

    <itineraryservice id="cbd59fc2-e8e0-4d00-ad73-8590938911b2" stage="None" 

scope="Orchestration" type="ContactOperation.Dispatcher, ContactOperation, 
Version=, Culture=neutral, PublicKeyToken=2710b190689828fa" 

name="ContactOperation.Dispatcher" />

TakeAway: What are the Two Ways to Quickly Transform a Message using ESB Toolkit?

Using the Transform XLANG Keyword

//Retrieve map type from resolution structure
mapCLRType = System.Type.GetType(mapType);

//Executing a map using transform keyword
transform(OutboundMsg) = mapCLRType(InboundMsg);

NOTE: The 'mapCLRType' is a variable of type 'System.Type'.

Using the 'MapHelper.TransformMessage' API Call

transformedData = Microsoft.Practices.ESB.Transform.MapHelper.TransformMessage
    (InboundMsg.Body.OuterXml, MetadataMsg.Body.TransformationType);

NOTE: The 'transformedData' is a variable of type 'System.String'.

Some Points to Ponder

  • The use of Orchestrations within Itineraries is NOT recommended. The design of Itineraries does NOT encourage the use of orchestrations. Looking forward to suggestions for a better solution, which avoids the use of Orchestrations in Itineraries for the case presented in this article.
  • Any elegant design clearly depicts the end-to-end message flow processing, which is from the source to the destination. The Itineraries are one way of looking at it. By using Itineraries, we are modeling the message flow from end-to-end.
  • Every message flowing through the ESB would have an Itinerary attached to it.
  • The use of BRE resolvers enables the flexibility of maps used in the message flow process.

References for Further Reading


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Naveen Karamchetti
Architect AT&T Wi-Fi Services
United States United States
Naveen has done his Masters (M.S.) in Computer science, has started his career programming the mainframes and now has more than a decade of programming, development and design experience. Naveen has a sharp eye and keen observation skills. Naveen has worked for several companies and strived hard to build large scale business applications and bringing better solutions to the table.
Quite recently Naveen has built a fairly complex integration platform for a large bank. His hobbies include training, mentoring and research. Naveen spends his free time visiting National Parks nationwide.

Naveen has developed the BizTalk Control Center (BCC)

You may also be interested in...


Comments and Discussions

QuestionOrchetration Wrong!! Pin
estebanslipknot13-Nov-14 8:12
memberestebanslipknot13-Nov-14 8:12 
QuestionQueries related Section 1 and Section 2 of Dispatcher Odx. Pin
Dany(02)25-Jun-13 22:27
memberDany(02)25-Jun-13 22:27 
QuestionGetting error Routing Failure Pin
rbg727-Nov-12 20:25
memberrbg727-Nov-12 20:25 
QuestionOrchestration file empty Pin
diptiporwal28-May-12 19:23
memberdiptiporwal28-May-12 19:23 
AnswerRe: Orchestration file empty Pin
Naveen Karamchetti29-May-12 4:24
professionalNaveen Karamchetti29-May-12 4:24 
For now just code using the orchestration screen shots and the code in the article.
You will learn a lot. Smile | :)

Always be there....| MCSD.NET | Sun Certified...
GeneralRe: Orchestration file empty Pin
jagadishsw29-May-12 19:28
memberjagadishsw29-May-12 19:28 
QuestionWithout using orchestration extender Pin
diptiporwal27-May-12 19:24
memberdiptiporwal27-May-12 19:24 
GeneralMy vote of 5 Pin
hedidin8-Dec-11 14:16
professionalhedidin8-Dec-11 14:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web03 | 2.8.190518.1 | Last Updated 8 Dec 2011
Article Copyright 2011 by Naveen Karamchetti
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid