Wednesday, May 28, 2014

BizTalk Rules Engine - Lessons Learned

If you are looking for a few hours to while away then the BizTalk Rules Engine will certainly occupy the time.  Hopefully this post might give you some hours back. This post is about using the BizTalk Rules Engine within an orchestration.  In my case I want to set Boolean values that can then be used in decision shapes within the orchestration.  The sort of thing would be "if IsCreateCase is true then do this, else do that".  A quick summary of the things I learnt is:
  1. Write the results of the BRE rule back into the message
  2. Keep your rules really simple
  3. Find a workaround for null nodes
  4. Put the Call Rules shape in a scope and add an exception handler
The easiest thing is to write the BRE rule results back into the message.  When you set up the Call Rules shape it asks for only two things, the name of the BRE policy and the input parameters.
In my case the input is an XML message and if you create an Action to write back to a node in the message, it will actually clone the message. 

For me it was a benefit to have these results within the message as it provided a means of checking the logic was correct. I created some xs:boolean elements in my message and set the default value to false.  That is key because the target element must exist within the message.  Now all I had to think about was writing the conditions that will evaluate to true.

During testing of the policy in the Business Rules Composer I soon realised that it is best to keep the rules really simple if you can.  That is because when testing it displays the name of the rule that was fired so it is easier to check if these are simple rules. 

My next problem was around the message instances.  I am comparing the value of two nodes (both called CreateCase) in the message but in some valid message instances one of the nodes can be completely absent.

In code you would of course check for the existence of the Before/CreateCase node before checking its value because otherwise you would get en exception with the first example message.  I thought that BRE would do this if I used a condition which checked for its existence, but I just could not get that to work.  No combination of logical AND and OR would do the trick. 

In frustration I gave up and used the map which transforms the external schema to my internal one to add the necessary elements as nulls. I blogged about creating a null node here. I used the logical existence operator ? with the logical not ! along with the Value Mapping functoid.  Having a null element for CreateCase made all the difference and simplified my rules even more. 

Having tested my rules thoroughly in the Business Rules Composer I published and deployed it to BizTalk.  In the orchestration I added the Call Rules shape within a scope and created an Exception Handler that trapped errors of type PolicyExecutionException (you need to add a reference to Microsoft.Rule.Engine.DLL).

In the end I am very pleased with the result.  One simple shape determines the logic that my message will follow through the orchestration.  If I have to amend the rules I can do so without redeploying the orchestration. Sweet.