CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeff Lynch [MVP]

Everything E-Commerce!

Logical Message Splitting in BizTalk Server 2004

The Background:

If you’ve read any of my blog posts, you’ll know that the company I work for has implemented a system to process inbound customer purchase orders into our ERP system using BizTalk Server 2004’s Publish & Subscribe architecture as shown in Figure 1 below.


Figure 1: BizTalk’s Publish & Subscribe Architecture

The Problem:

I recently needed a means to split these inbound XML documents into multiple outbound documents where the number of outbound documents and the content of each document is determined by one of the fields in the inbound document. For lack of a better term I’m going to call this a “Logical Splitter” pattern. In this scenario, I need to split the inbound purchase order document into multiple outbound sales order documents, one for each different “RequestedDate” in the line item record as shown in Figures 2, 3 & 4 below. The tricky part is that the header information needs to be copied into each outbound document, the appropriate line items need to be copied and the footer information needs to be recalculated. Not a simple task to accomplish! 


Figure 2: The Inbound Order


Figure 3: One of the Outbound Orders


Figure 4: Another Outbound Order

If you’ve read many BizTalk blogs, you’ll know that BTS2004 can “debatch” messages using a wide variety of techniques as explained in Stephen Thomas’ excellent post and downloadable article. One of the most powerful and flexible of these methods is debatching using an orchestration as described in Darren Jefford’s blog. I’m going to use this technique along with some recently learned XSLT magic to accomplish this without using any external assemblies or custom pipeline components. To help simplify the development of this solution, I broke the problem down into two separate but related programming issues. This post explains how I accomplished the first and my next post will explain how I accomplished the second.

  • The first is how to write a map that reorganizes one document into a structure that could be “debatched” using standard BTS2004 debatching techniques.
  • The second is how to write an orchestration to implement this (logical splitting) debatching.

Using External XSLT in the BizTalk Mapper

Besides using functoids to create your maps, the BizTalk Mapper tool also allows you to use external XSLT by setting the “Custom XSLT Path” property as shown in Figure 1 below. This allows you to use XSLT that may not be possible to create using the standard functoids or the scripting functoid.


Figure 1: Setting the Custom XSLT Path property

I’ve got to admit in the past few years I hadn’t run into a situation that required me to use write any XSLT and frankly, my skills are severely lacking in this area. So I did what any resourceful developer would do, I asked for HELP! (Please note, this is not the same as asking for directions which of course, I would never do) The nice thing is, the XML/XSLT/XPATH user community is full of great blogs and really helpful folks. There are also some very good tools available on the market such as Altova’s XMLSpy and Progress Software’s Stylus Studio. As always, the folks in the microsoft.public.xml and microsoft.public.biztalk.general pitched in to help also.


Figure 2: The Inbound Schema


Figure 3: The Outbound Schema


Figure 4: XSLT Grouping

What we (I really can’t take much credit for this) came up with is the XSLT shown in Figure 2 above. The “key” (no pun intended) is the use of the XSLT key element and key() function along with the XSLT generate-id() function. These allow you to group XML elements based upon a key value in your document, in my case the “RequestedDate” field.

Using An Orchestration to Debatch


Figure 1: Map & Split Orchestration

I’m going to assume that you’ve created at least one simple orchestration before and skip the basics such as the “Receive” and “Send” shapes and inbound and outbound ports.

  1. Once you’ve received a message from a port, you need to construct a new message using the “Transform” shape as shown above. This shape enables you to map the fields from the existing message into the new message using the map created in my last post.



  2. Next use an “Expression” shape to assign values to variables used later in the orchestration. These variables are used to loop through the Order nodes in my mapped message and to create a new XmlDocument to hold the debatched messages.



  3. Next use the “Loop” shape to create a loop until the “Counter” variable is equal to the number of Order nodes present in the mapped message.



  4. After this comes the important step. Use another “Expression” shape to create the actual debatched messages and increment the loop counter. This is done using a simple XPath expression as shown below.



  5. The next step is to use a “Message Assignment” shape to assign the newly created message from the XmlDocument.



  6. The final step is to send the debatched message to an outbound port and run through the loop until complete.

This orchestration debatching technique is fairly simple, easy to understand and very flexible. It’s a great solution to the problem of logically splitting messages. Download the sample project using the link below and as always your comments and feedback are welcome.

DOWNLOAD: Logical Splitter Sample Project

Special thanks to Stephen Thomas for his assistance and support!

Special thanks to Jon Flanders at DevelopMentor for help in providing a work-around for a little BizTalk compilation bug related to using external XSLT stylesheets.


Published Jul 12 2005, 07:01 PM by jlynch
Filed under:

Comments

rsakalley said:

Jeff, Excellent and very informative.
# July 19, 2005 8:05 AM

Nathan said:

Jeff,

You mentioned "standard BTS2004 debatching techniques". What are these and where can I see an example.

Thanks,
Nathan
# August 9, 2005 10:01 AM

Michael G. Emmons said:

# September 28, 2005 3:55 PM

Nick said:

Great sample. It worked well for me. However, when I try to drop another file it stops at the loop, as if the counter is not resetting when the orch is finished. Any ideas? Thanks, Nick
# April 6, 2007 2:45 PM

jlynch said:

Nick,

The counter resets in the Expression shape as shown above. I've been using this code for several years and have processed thousands of xml documents through the orchestration without any issues. I'm not sure what would cause it to stall at the Loop shape.

Jeff

# April 6, 2007 6:07 PM

Bryce said:

Excellent sample, but I am having a problem. The message type on the debatched message seems to be set wrong in the assignment. I get the type I want plus #Record wich is the node name. Is there anyway to fix this?

Bryce

# April 25, 2007 2:05 PM

jlynch said:

Bryce,

I would have to see your schemas to see what is going wrong.

Jeff

# April 25, 2007 2:26 PM

Bryce said:

Thanks for the quick response!

I can send them to you, what email should I use?

Bryce

# April 25, 2007 2:40 PM

jlynch said:

If you can zip up your solution including the schemas, maps, orchestration and a sample instance I'll take a look over the weekend. You might try changing the node name from #Record to just Record and see what happens.

jtlynch@nospam.houston.rr.com - remove the nospam

Jeff

# April 25, 2007 4:00 PM

DBiZ said:

Great Example!! Do you recommend this approach for a large file with millions of records?
# May 22, 2007 2:29 PM

jlynch said:

I would recommend testing very carefully in the scenario since the orchestration is creating new XmlDocuments in memory.

Jeff

# May 22, 2007 5:21 PM

biztalknewbie said:

Great post. I have a similar scenario, but in my case I don't necessarily need to group distinct items. Instead I need to have the same header and footer, like your example, but, then take a collection in the middle of the schema, and send one message per item in the collection. You mentioned on step 1, "using the map created in my last post." Which post is that?
# June 6, 2007 8:25 PM

Rob M said:

Hi Jeff,

i have downloaded your sample and am having problems getting it to work in a different project. I have gone through and changed all the namespaces from BizTalk.Enthusiast.LogicalSplitter to CountryRoad.BizTalk.Retail.HOStoRETEKInterface. In both schemas, map and XSLT. When I run a Test Map. i receive a Output Validation Error - Root Element Is Missing. I'm at a loss as I have compared each document to your project that works successfully. I started by modifying your sample but have gone to basics (adding it to my project) to troubleshoot problem. the schemas validate successfully.

Any ideas

Thanks Rob

# July 2, 2007 2:42 AM

Nick said:

This split works great Jeff. I'm now trying to apply a file name to the output. The file name I want to use is located in a field called 'Tractor'. This field is promoted (in the single schema) and available to tab select when typing the script below in the message.

SingleRoute(FILE.ReceivedFileName) = SingleRoute.Order.Tractor + ".xml";

However, I'm not seeing any output when attempting to use the %SourceFileName% macro on the send port.

Any quick suggestions?

Thanks - Nick

# April 25, 2008 12:21 PM

Don said:

Thank you so much for sharing this, it was a HUGE help!! I am just getting started with Biztalk and simple, concise examples like this are perfect.

# April 25, 2008 2:59 PM

Nick said:

Please disregard my previous question. I was able to get to work with a little xpath (and some pain).

SingleRoute(FILE.ReceivedFileName) = (System.String)xpath(SingleRoute,"string(//Tractor/text())") + ".xml";

Thanks - Nick

# April 25, 2008 5:44 PM

jlynch said:

Nick,

I used to remember how to do this but it escapes me right now. Google "BizTalk File Naming" and see if you can find any posts by Stephen Thomas or any of the other BizTalk MVPs. I seem to remember a few posts discussing this several years ago.

Jeff

# April 26, 2008 1:05 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!

Our Sponsors

Free Tech Publications

This Blog

Syndication