Here’s one for you. Last week I encountered a particularly tricky multi-part mapping scenario. I had to build a destination message that contained groupings from the two source messages. Each record in the first source message created a destination node, and each record in the second source message created a destination node directly beneath the related first source record. To make matters tougher, every destination record has an attribute containing a sequential number. So out of this …
<source1>
<Node1><Node1>
<Node2></Node2>
</source1>
<source2>
<NodeRelatedToNode1></NodeRelatedToNode1>
<NodeRelatedToNode1></NodeRelatedToNode1>
<NodeRelatedToNode2></NodeRelatedToNode2>
</source2>
The destination was supposed to look like this …
<destination>
<Node1 page=”1″><Node1>
<NodeRelatedToNode1 page=”2″></NodeRelatedToNode1>
<NodeRelatedToNode1 page=”3″></NodeRelatedToNode1>
<Node2 page=”4″></Node2>
<NodeRelatedToNode2 page=”5″></NodeRelatedToNode2>
</destination>
The grouping part wasn’t too tough, just used a Scripting functoid with the XSLT Call Template and a little hand written XSL. The hard part was creating the sequential “page” numbers. Those familiar with XSLT know that the “variables” in XSLT are basically constants, so you can’t create a variable and increment it. I considered building some sort of recursion to get my incremented number, but in the end, decided to call a custom .NET component from my map’s XSLT. I built a C# component that had a member variable, and a method called “GetNext()” which incremented and then returned the next sequential number. I then set my map’s Custom Extension XML to an XML document referencing my custom component. Now in my XSLT Call Template I could get the next “page” number each time I built a destination node. Neat!
See here for an example of doing this.
Here’s where a “quirk” was introduced. When I deployed this map, and ran multiple documents through it, the first document had it’s paging correct (e.g. pages 1-5), but the next messages had the wrong values (e.g. 6-10, 11-16, etc). What was happening was that somehow this custom C# component was being shared! The “increment” kept counting on each orchestration call! My C# component wasn’t built as a “static” object, and I assumed that the scope of each custom object was the individual map (or orchestration) instance.
I still have no idea why this happened, but to ensure it wouldn’t keep happening, I added a method to the custom component called “Reset()” which set the counter to 0. Then at the top of the map I call out to that method to ensure that each map starts its counter at 0.
Thoughts as to why this happens? Wild stuff.
Technorati Tags: BizTalk
Hi Richard,
This happens because static .NET components “live” in handler’s context: in our case in BizTalk host instance or IIS if the map runs in SOAP receive location. Unfortunately your solution with Reset() function may cause problems if you have several instances of the same orchestration running simultaneously.
Sorry for bad news :-).
I’d try to solve this problem with xslt-only approach. Here is one of the options:
number(substring(local-name(), 5))])”/>
number(substring(local-name(), 18))])”/>
Obviously I don’t know your task and this maybe not what you need, but I hope this helps.
Good luck.
Oleg.
Well, xslt was “destroyed” in the previos post. Sorry.
Hey Oleg,
Thanks for the post. But class/method ISN’T static. That’s why I assumed it would be stateful only to a given map (or calling orchestration).
Richard – alternative -> could you consider a Custom Functoid that internally uses the beloved c# that you need?
xslt super fast though 🙂
Nice one.
Hi Richard,
It is strange to know that this is happening for non static variables. can you please share a snippet so that i can regenerate this shared scenario.
This arcticle is uprooting my basics 🙂
Hi there. Unfortunately, this was quite a while ago, and I don’t have the original code sitting around anymore. Hopefully there’s enough of a description here if you’d like to re-create it!