Looping around Message Elements
I had loads of fun a few weeks back with coming up with some options inside BizTalk on how to separate multiple elements inside a Message for individual processing.
e.g: Retrieving all of the items individually in this Order message
<Order>
<Items>
<Item Code=”ITEM001” Price=”23.00” Qty=1>
<Item Code=”ITEM002” Price=”23.00” Qty=1>
<Item Code=”ITEM003” Price=”23.00” Qty=1>
</Items>
</Order
Now, BizTalk has the ability to “shred” these recurring elements into subsequent messages which is very cool – you simply define a Envelope Schema which in this case would just encompass the <Order> and <Items> element, and also define a Body Schema that would define the Item elements. Typically you would reference the Item schema from the Element as an unbounded child of the Items Node.
To enable the “shredding” to work you need to set two properties on the Envelope Schema:
- Click on the Schema Element of your Envelope Schema in the BizTalk Editor and set the Envelope Property to Yes
- Click on the Root element of your Envelope Schema ( <Order> in the example above), and set the “Body XPath” property to point at the node above your repeating elements (<Items> in this case>
You can then create a Custom Pipeline and drag on the XML Disassembler (is it just me that always gets the Assembler/Disassembler the wrong way round J). Click on the Dissasember component and view the properties pane, Point the Envelope schema at the appropriate schema and point the Document Schema at the Item schema in this case.
If you need to have promoted properties in the Body/Document Schema let me know – it’s not straight forward right now.
Any messages now flowing through this pipeline will be “shredded”, n Item Messages will arrive inside the MessageBox ready to be consumed – all this with no code! You do however “loose” the original message in this context which may or may not be a problem – sometimes there is some data in the “Envelope” section of each message, it could be that the split messages need to have that data to aid with the processing. In this case I think you might be able to use an Inbound Map on your Receive Port to transform the message to add the elements – need to try this though as I’m not sure if the Map is run first or not.
This works a treat, but what happens if one of these <Item> elements is malformed or has some problem with it? Well in this case the Pipeline is going to thrown an exception and you’ll end up not getting any <Item> messages created, now this in some cases might be reasonable (if you’ve defined and agreed a schema and have no requirement to make best endeavors with processing the message).
However if you want more control over the splitting and any errors that might occur you end up with an Orchestration solution. So – How do you “loop” around multiple elements of a BizTalk Message in an Orchestration?
Based on some internal material I managed to do this by utilising a XmlNodeList variable that took the result of a xpath statement in a Expression shape, retrieved a Enumerator by using the GetEnumerator method on the XmlNodeLIst and iterating around this inside BizTalk using a Loop shape, each iteration cast the Element to a BizTalk Message variable which was then sent via a Direct port back to the MessageBox for further processing. This worked great (and I have detailed steps on doing this if anyone wants it) but all of this has to be done inside an Atomic scope as the XmlNodeList and IEnumerator types are not Serializable.
However a very observant customer spotted that this solution didn’t fit their requirements, they needed to loop around all the recurring elements, assigning each one to a BizTalk Message and doing stuff – this had to be done within an atomic scope and therefore they couldn’t handle any exceptions that might be thrown by their .NET component or by BizTalk itself if one of the recurring element was malformed, so if something bad happened the Atomic scope would be rolled back and any Messages “sent” to the Direct port would not be committed to the MessageBox leaving us in the same situation as the pipeline solution.
Much head scratching and discussion with a colleague later we came up with a much nicer solution that allows exceptions to be caught so you can effectively loop around all elements “skipping” bad ones and avoiding Atomic scopes completely!. Basically we use the xpath function exposed by the Orchestration runtime to “count” the number of elements in the message, we then loop around each of these again using the xpath function to retrieve the message and cast it to a Message.
The xpath built-in function is very powerful and most people don’t seem to know about it – you can read up on it here
Dead simple when you see it – but it was hard to get there! Here’s the sample to save you the pain!
Comments
Anonymous
September 02, 2004
I've had problems with this, and ended up just mapping the documents to another schema with the promoted properties to work around the issue. So how do you do it??Anonymous
September 03, 2004
Can you drop me a mail please? (via the Contact hyperlink on the top left)Anonymous
September 14, 2004
This is a very elegant implementation of my Splitter pattern: http://www.eaipatterns.com/Sequencer.htmlAnonymous
October 10, 2004
<a href="http://blogs.msdn.com/darrenj/archive/2004/08/30/222614.aspx">Looping around Message Elements</a> - this is another fine approach to split messages in BTS. Also, Darren Jefford explains how to loop in message in BTS orchestration. Take a look atAnonymous
July 19, 2005
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.Anonymous
August 19, 2005
One of the fairly common issue that most Biztalk designers face is the issue of Debatching and then Batching...Anonymous
August 19, 2005
One of the fairly common issue that most Biztalk designers...Anonymous
August 19, 2005
&nbsp;
One of the fairly common issue that most Biztalk designers face is the issue of Debatching and...Anonymous
August 19, 2005
One of the fairly common issue that most Biztalk designers face is the issue of Debatching and then Batching...Anonymous
August 22, 2006
Working with XPath inside Orchestrations is a powerful and simple feature of BizTalk 2004. The help guideAnonymous
May 07, 2007
PingBack from http://techlifeme.wordpress.com/2005/03/10/debatching-and-batching-in-biztalk-2004/Anonymous
August 14, 2007
The comment has been removedAnonymous
August 15, 2007
Please ignore my previous post. I had a namespace issue.Anonymous
August 11, 2008
The comment has been removedAnonymous
September 21, 2008
Working with XPath inside Orchestrations is a powerful and simple feature of BizTalk 2004. The help guideAnonymous
February 12, 2009
So I've been working on this and I've run into a snag. If the "Order" message has a namesapce defined (as good biztalk messages do, ie uri:MyOrders) then the Item message doesn't contain the namespace when you assign it using Xpath. If you then try to send the Item message, you end up getting an error about not being able to determin message type by "Item" Has anyone found a way around this?Anonymous
February 12, 2009
I found this blog, http://blogs.digitaldeposit.net/saravana/post/2006/12/18/Message-Debatching-inside-Biztalk-Orchestration-with-TargetNamespace.aspx I'm going to check it out and see if it works for me.Anonymous
March 23, 2009
The comment has been removedAnonymous
May 26, 2009
PingBack from http://castironbakeware.info/story.php?title=darren-jefford-looping-around-message-elementsAnonymous
February 19, 2010
Hi, Hi I'm working with a flat file that has several records which needs to be debatched to multiple output file. The questio is how we can aggregate the result of individual messages to multiple files and not only one based on a special code inside each record in the input message. What I mean that I have the input message with several messges, each message has a customer code, I want to group all messages relevant to customer 1 in output file 1, messages relevant tocustomer 2 to output file 2 and so on. So if I have n messages in my input, then individual elements should be debatched and aggregated in several files. If the n messages represent 10 messages, 2 of which are for cust1, 3 for cust 2, 3 forcust 3, 2 for cust 4, then then 4 output files should be produced by the process.Anonymous
March 11, 2010
Hi, I am trying to download the sample but it seems the link is not good. can you please send me the sample code, thanks salam.elias at free.fr