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:
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 hereDead simple when you see it – but it was hard to get there! Here’s the sample to save you the pain!