Introduction to Dynamic Maps

If you have used maps in BizTalk, by now, you must know that maps are used to transform an XML message into another format. I do not intend to go into the details about BizTalk maps here, but in essence, a map is a transformation on your existing data to the output format you desire. In this article, I will illustrate an interesting feature called Dynamic Maps in BizTalk. If you are a C++ fan like me, you would be amazed at the power of polymorphism and how a call to a function, say Shape.Draw(), differs with each derived class of Shape like Arc, Square, or Circle. So I don't have to explain why dynamic mapping is important.

Quite often in BizTalk, you come across scenarios where you need to transform a message to an output format, which you can decide only after you know some information which is contained in the message itself, like destination recipient. This can be achieved by using maps in the ports itself, but as the number of parties grow and your exception handling requirements kick in, this route has some limitations. This is where dynamic mapping inside orchestrations make sense.

Scenario

For this exercise, I am building an orchestration which identifies the destination party and loads the corresponding map and sends the message to the intended recipient after the desired transformation. For this example, I have two parties ABC and XYZ.

A Bird's Eye View of the Steps

These are the steps for implementing our Dynamic Maps. I am assuming a working knowledge of BizTalk for the solution below, as the concept is what I intend to illustrate. You can skip these steps by downloading the source from above.

Create a BizTalk Project for Maps.

Create all Schemas and Maps.

Create an Orchestration Project.

Identify the party and load the Maps dynamically.

Set the Destination dynamically and route the message.

Deploy and GAC the DLL.

Testing.

Getting Down to Business ..

I have broken down the process into a series of logical steps.

Step 1: Creating your Schemas and Maps Project

You need to create a Schema and Maps project. I have all my maps and schemas in a project called Dynamic Maps. I have added three schemas to the project.

The Generic Schema (Common Input Schema)

ABC Schema (for my party ABC)

XYZ Schema (for my party XYZ)

The details of the three schemas are as below. The input schema comes in with some basic information. The output schemas differ for the two parties ABC and XYZ. The three schemas are shown below.

Right click on SubscriberInfo in the GenericSchema and do a Quick promotion. This will add a property schema to the BizTalk project.

Now we build the two maps. Both the maps use some basic information from the sources schema, and add some additional information on the output side. I have used the Time functoid to get the submission time.

Step 2: Signing the DLL with a Key

You need to have a strong name for this assembly to get it loaded in the toolbox. So create a strong name and sign it. Once you have the strong key generated, reference that in the Assembly Key file value in the project properties.

Step 3: Compile and deploy the Maps project

From project properties in the Solution Explorer window, deploy the project. Check in GAC to see if the DLL is deployed. Note down the public key token from the file properties in GAC.

Step 4: Build the Dynamic Maps orchestrations

Add a new BizTalk project OrchestrationForDynamicMaps. Create a new Orchestration and name it Orch_DynamicMaps. In the Orchestration View window, create the following variables and messages. Set the value as in the table below. Leave the rest of the values as their default values.

Message / Variable

Identifier

Type

Comments

Message

Generic_In

DynamicMaps.GenericInSchema

The incoming Message

Message

Message_Out

System.Xml.XmlDocument

The outgoing Message

Variable

SubscriberInformation

System.String

Promoted Subscriber Info

Variable

tMap

System.Type

The Map value

The orchestration built looks as in the figure below. The outline of steps is detailed below. You can download the source and follow the steps conceptually.

Add a Send port which sends out a message of type System.Xml, and use that to send the transformed file to your desired destination.

Compile and deploy the project.

Note: In essence, what we have done in the step above is to use the reflection feature in .NET and find the type of the Map. Then we use the variable and invoke the transformation by using the BizTalk internal keyword transform. BizTalk does all the hard work of loading the assembly dynamically for our use and unloading the assembly later, and all that plumbing that you otherwise need to write. Don't you love BizTalk now?

Step 5: Testing and Output

You can drop the two test files and you will get two different outputs for the same file based on changing the subscriber.

I have the inputs and outputs as below:

Input file for party ABC

Output for party ABC

Input file for party XYZ

Output for party XYZ

Step 8: A few notes on the output

The output is self explanatory, and you will notice that for identical inputs except for the party name, the output was different based on the maps used. We used a Time functoid to generate the time, and the other values came from fixed strings. And last but not the least, I confess, I am not 22 as the example file indicates or misleads, way older than that! My wife was quick to point that one out.

Points of Interest

Although in this example we have used a simple Decide shape to figure out which map to load, in real life implementations, this could be a database helper class which returns the name of the map assembly from a SQL database or a similar design. This design is useful since you can add more maps and systems even after the original system has gone live. This is possible because you can add a new subscriber into the database and have a new DLL with the corresponding schema and maps. This provides a loose-coupling which is highly desired in these scenarios.

Gotcha's

In the declaration of the variable tMap, I could not get it to be defined as System.Type from the dropdown. I had to open the .odx file in Notepad and set it manually after choosing a random type initially.

Exceptions

A very common exception would be:

Error in accessing the part data or one of its fragments.
The part or fragment may not exist in the database.

When this happens, make sure you have both the assemblies deployed and they are present in the GAC. Also check that the ports are created and the Receive port uses an XML transmit pipeline and the Send port uses a pass-through transmit pipeline. If that did not solve the problem, ping me at the BizTalk cafe forums. I would be glad to take a look.

History

Version 1.0 - March 20, 2006.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

Abhilash is from Kerala, South India. He is presently working as an Integration Consultant for many fortune 500 companies in his current role at Neudesic

Abhilash has been programming since he got his first PC, when they used to load BASIC using tapes. He got his first real PC in 1994 - a 286 with a 40 MB hard disk, 1 MB RAM, and a 5.25 " FDD with a HGA graphics card.

Pascal was his first favorite programming language. And he thought at one time that it was the greatest language. He never really got on to the Delphi wagon, but went with C++, and then progressively VC++ SDK, MFC, COM, and then eventually chose C# as his preferred language once .NET came along. With the emergence of SOA into mainstream, Abhilash chose BizTalk as his SOA realization tool of preference. He opines that BizTalk helps implement SOA; by so clearly separating the message and the underlying implementation, and connect apps purely based on contracts. This is what many classic technologies like IDL tried to do, but somewhere, the point got lost. BizTalk is his tool of choice for EAI. Abhilash has worked in various platforms including Win32,.NET,Linux, and Mainframes and has professional experience in embedded development and voice telephony.This helps him understand the EAI domain better.

His passions include programming, blogging ,cricket and chess. He likes to troll MS user groups and used to run a site www.biztalkcafe.com as a hobby. The site has a forum, so if you work with BizTalk server, he would like to hear about your experiences there.

I've setup everything which mentioned in this article but for the testing purpose should i have to create the receive port and send port manually configured and if so how the orchestration creation on the biztalk admin console??

The thing is I am able to generate the target schema for all except for the two phones. I am getting only one phone in target schema. I could not make loop on phone element in target schema.I could make loop on Childs element in target.

Can anyone throw idea on how to do this.

I want to make loop on phone element as each child has two phone elements.

You are successfully tried to crack the internals of biztalk transformation and calling Maps using reflection technic. Well done!!

There are ideal ways of deployment scenario's been already in the space using schema versions and assembly versions. In a modular deployment model artifacts are segregated in different projects with specific versions, Do you think this would get you more easier the job done than the versioning ?

Also i see lot of customizations folks trying in biztalk

1. Post message with out using the ReceivePort
2. Orchestration is designed to just call .NET class and all business condition is compiled in
different project
3. Dynamic mapping
4. Custom send ports in .NET

I feel this is absolutly fine anyone doing this reflection on development box.

But ***remember*** this would break your High availability and performance in the production, also you might not want to get the type loading exception instead of mapping exception.

I prefer versioning method gives more flexibility and ease of deployment. If you design your solution with Direct binding ports, you have multiple options to accomplish solution upgrade.

Hi, I am new to Biztalk
what is constrcut msgName{ } block, I understand the use of this, but there is no documents for this in MSDN!, is there any other keywords like construcr,transform?? bcoz I feel these are all very usefull for all the new comers!

It's interesting the way you present dynamic transformations using the transform() method in an orchestration expression shape. However, couldn't the same notion of dynamic transformations be accomplished via routing?

***Scenario A-No Orchestration Required for Dynamic Transformation: ***
Ultimately, the promoted property provided in your received message and used in the decision shape could have been routed to a Send Port that has a filter listening on that property. SendPort A would listen for 'ABC' and SendPort B would listen for 'XYZ'. Each send port would then apply their specific transformation in the Outbound Map setting of the Send Ports.

***Scenario B-Routing from values set in Orchestration: ***
Let's say the promoted property is set in the Orchestration after some sort of calculation or database lookup. You can still use an initializing correlation set to promote that property on a send shape which would dynamically resolve the appropriate Send Port to route to. The same Send Port Filters above would apply.

In both scenarios, the maps used are still decoupled from the calling orchestrations. Following the approach I've described does not require maintaining another repository for listing Map Types in a database or hard coded in an orchestration. The DBHelper you suggested would add unnecessary overhead to the BizTalk process. Additionally, updating the Map Types in another repository or hard coded in an Orchestration would introduce an additional maintenance point every time a new map deployment is made.

By using BizTalk Send Ports and setting Outbound Maps for dynamic transformations, maintaining map updates become easier and intuitive to track and administer.

Your example calls for setting the Send Ports to use the Pass-Thru Transmit Pipeline for the untyped raw XML being delivered from the Orchestration. The trade off is you lose the ability to track outbound messages by schemas and promoted properties in HAT or BAM. All of a sudden, some of the frills provided by BizTalk are compromised.

On the other hand, this article did introduce the BizTalk orchestration transform() method, which is a feature I was not aware of. At this point, I'd have to think really hard about when it's appropriate to use this method.

After writing this counter comment to your article, I still have to say thank you for taking the time to contribute to the BizTalk community. Hopefully my comments will help others to decide when it’s appropriate to use one approach over the other.

First of all thank you for an excellent and detailed feedback. It is these comments that I get which gives some joy after going through the pains of writing an artile.

As I mentioned in the second para of my introduction . This problem presented here CAN DEFINITELY be solved using maps in the send port approach and also having these send ports maybe part of a send group; so that the single file comes in; and gets transformed or not based on value of the available promoted property .This approach also has No overhead of a lookup table etc.

So the solution is an ideal approach except in certain cases

1.) You have some exception handling requirements
(In this case it is better to have it in the orchestration You would agree )

2.) Let us say You have a large number of parties who want to consume a file. maintianing 500 send ports added into a group is a Administration headache. Also the XLANG engine has to maintain and evaluate all that subscribtons even if only one party is interested in it. In the scenario above there will be only 6 (or how many ever adapters you have registerd ) subscriptions created and in effect the destination is set Dynamically.

And in both the scenarios mentioned above the transformation is not dynamic but it does provide loose coupling and grouping by the very nature of Biztalk plish subscribe underlying architecture. As you mentioned the selection of the right approach is often a judicial and careful trade-off

Once again thanks for your wonderful comments and insights David. Really appreciat it .

The thing is I am able to generate the target schema for all except for the two phones. I am getting only one phone in target schema. I could not make loop on phone element in target schema.I could make loop on Childs element in target.

Can anyone throw idea on how to do this.

I want to make loop on phone element as each child has two phone elements.