Geeks With Blogs

News View Michael Stephenson's profile on BizTalk Blog Doc View Michael Stephenson's profile on LinkedIn
Michael Stephenson keeping your feet on premise while your heads in the cloud
Written by: Michael Stephenson (http://geekswithblogs.net/michaelstephenson)
Background
A few posts ago I had a bit of a whinge about the limitation of a map for a response message in a request response port. The basic problem was I was returning a common schema based message to the port which needed to be mapped to a different format depending on which receive location associated with the port had initiated the process. The send side was fine in that you can send two different input messages which the port can then have two maps, 1 for each message type to map to the common schema.
The problem was on the response the input was the same in both cases so you couldn’t resolve which map to execute. See the below post for more details on this:
 
This made me to begin thinking about if we could execute the map from the pipeline rather than the port. The difference is that the pipeline is specific to the receive location and you wouldn’t have the problem of resolving the map then.
From another recent post about testing Maps I discussed how you could execute a map from C# code to help you test it. I then begun to put two and two together to see if it would make four. Or if BizTalk would have other ideas J
The Sample
If you would like to review the source code for this sample it is available from http://www.box.net/shared/u67o8btc8k
In the sample I will have a basic input message and a basic output message. The bog standard FirstName/Surname à FullName example.  The messages will be mapped with the map in the picture below:
I will then create a pipeline which will use the XmlDisassembler and the ExecuteMap pipeline component like in the below picture.

The pipeline component can be used in a receive or send pipeline and can be used in any stage except disassemble/assemble. The pipeline component has the properties which are displayed in the below picture:
The key properties are:
Assembly Name – This is the strong name of the assembly containing the map
Map Type Name – This is the full name of the type which represents the map. From the Visual Studio IED you can get this from the properties of your map
Output Message Schema Strong Name – This is required to set the correct context property value for the output message. This should be in the format of <Message Full Type Name, Assemble Strong Name> (eg: Acme.BizTalk.Samples.Schemas.OutputSchema, Acme.BizTalk.Samples.Schemas, Version=0.0.0.0, Culture=neutral, PublicKeyToken=PBRTYEFG124)
Output Message Type – This should be the normal message type to set the message type context property. This is in the format namespace#root element name (eg: http://acme.biztalk.samples.schemas#Person)
 
The Pipeline Component
The pipeline component needs to perform 3 key tasks:
1.       Copy the input message
2.       Execute the map
3.       Create the new message and context to return to the pipeline
The first thought you may have is “why do you need to copy the input message”?. Good question, the first time I did this I didn’t need to, but when I used the component in a pipeline which also contained a disassemble component I started to get a problem because when the map is executed the TransformBase object will dispose the input message stream which caused the Disassembler component to log an error. 
Im not really going to go through every line of code in this article, if you want to take a look at the pipeline component then download the sample. In the pipeline component I have made it easy to see what is going on by having 3 private methods which do the 3 actions I have listed above. 
 
Testing the Component
When it came to testing the pipeline component I have used the technique I mentioned in a previous article about how to test pipelines. The following code snippet shows how this test was written.
As you can see the test is pretty simple and does the following actions:
1.       Creates the input message
2.       Creates the pipeline in code which contains an instance of the
3.       Executes the pipeline
4.       Checks the output message is as expected in the mapped format
One final thing on the testing is you may also want to check the overridebuild.targets files which show that I am adding to the GAC the assemblies containing the pipeline component and also the BizTalk artifacts. This needs to be done in order for them to be used and tested.
 
Word of warning
In this sample I have only provided enough to show the pipeline component working (testing it with the Pipeline Component Test Library), I have used this in a sample BizTalk application which I may look to demonstrate at somepoint in the future so yes it can work. I have also focused on finding out if the concept will work so you will want to review the code and optimise some bits before you would use it. The main word of warning though is that I haven’t done anything with this in terms of performance or serious testing so if you plan to look at this technique then don’t forget to do that.
Summary
In summary for this article the answer is yes you can create a pipeline component which will execute a map and it can fit into BizTalk. I think there will be occasions when someone will want to do this and maybe this article can help.
Posted on Friday, May 9, 2008 9:15 PM BizTalk | Back to top


Comments on this post: Executing a map from a pipeline component

# re: Executing a map from a pipeline component
Requesting Gravatar...
You can have a look at this article.

http://biztalkcollections.blogspot.com/2008/02/maper-pipeline-component.html

With this component, u dont even need a biztalk map. XSLT is configured at run time in the receive pipeline. This will transform the incoming message to the desired outgoing message.
Left by Shankar on Dec 01, 2008 2:42 PM

# re: Executing a map from a pipeline component
Requesting Gravatar...
Looking at the pipeline component, it limits the message to 4k:

MemoryStream newMessage = new MemoryStream();
byte[] buffer = new byte[0x1000];

try
{
inputMessage.Read(buffer, 0, 0x1000);
MemoryStream tempStream = new MemoryStream();
tempStream.Write(buffer, 0, 0x1000);
tempStream.Seek(0, SeekOrigin.Begin);
...

A better option is:

MemoryStream ToMemoryStream (Stream input, bool closeInput)
{
try
{ // Read and write in
byte[] block = new byte [0x1000]; // blocks of 4K.
MemoryStream ms = new MemoryStream();
while (true)
{
int bytesRead = input.Read (block, 0, block.Length);
if (bytesRead == 0) return ms;
ms.Write (block, 0, bytesRead);
}
}
finally { if (closeInput) input.Close(); }
}

makes this pipeline more usefull.


Left by Nigel Sheldon on Jul 04, 2011 12:05 AM

Your comment:
 (will show your gravatar)


Copyright © Michael Stephenson | Powered by: GeeksWithBlogs.net