MS BRE Demystified – Part 1 Forward Chaining for optional XML Facts

Time to Read: 8 minutes

For past few months I have been working on a big project in my organization where we are using Microsoft Business Rules engine for the conditional evaluation of incoming payloads. There are few lessons that I have learnt along the way and I will present them as a part of a blog series centered around the Business Rules Engine.

I want to write this series as I find that the blog posts on BRE are really scarce and hard to find. I will document my learning in this series. Before begin, I would like to point out that the blog from Charles Young is a really good reading resource if you want to understand the nuances of BRE . The blog can be found at http://geekswithblogs.net/cyoung/Default.aspx . So without ado let us dive right into it.

A little about MS BRE

Microsoft Business Rules (MS BRE ) is a .Net compliant inference engine which helps developers write highly readable and semantically rich rules on .Net objects, XMLs and database tables. MS BRE works on the principle of production rule system.

A production rule system can be thought of as a series of rules each of which contains Conditions and Actions. When the conditions are evaluated to true, then the set of steps mentioned in the actions are executed. Now, one can think, why do I need to use the rule engine? I can code the steps as a complex branching logic containing if- else and switch case statements. Whilst that is true, this if-else logic poses two problems when the number of rules to be implemented is very big

  1. The bigger the number of rules, the complex the branching logic
  2. The branching logic enforces a strict “sequential” flow of information from one statement to another

If this is implemented as a part of a production rule system like MS BRE, then the developer only defines the rules as a collection of conditions and the actions. The developer need not worry about the order in which the rules get executed (though we can enforce some sense of order, more on it in future post). The rule engine at the time of the execution of the entire rules, creates a tree structure based upon the Rete(spelled “Ree-Tee”) algorithm( https://en.wikipedia.org/wiki/Rete_algorithm ). The data that is fed to the rule engine then passes through related nodes in this tree and produces the output at the end.

For MS BRE the processing of the message against the defined rules can be explained at a very high level as following steps

  1. At the time of the execution of the policy, the rule engine create a tree structure based upon the conditions provided in the rules. This tree is based on Rete algorithm
  2. Once the data(called facts )is fed to the engine, it evaluates the pertinent facts against the conditions in the constructed tree
  3. Once the fact passes the condition, it advances in the tree
  4. Once a fact passes all the conditions, the rules where all conditions are satisfied are updated in the agenda of the rule engine
  5. Once the agenda update is completed, the rules which were added to the agenda are fired and the actions defined in these rules are executed.
  6. Facts are removed from the rule engine working memory

In order to learn more about how the MS BRE works in detail, I would urge you to read the MSDN documentation at https://docs.microsoft.com/en-us/biztalk/core/rule-engine

What is Forward Chaining

In layman’s term, forward chaining can be defined as “Effects due to execution of one rule, changes the evaluation of another rule“. Though this is a very high level and incomplete definition of forward chaining, this will serve us for the time being.

Consider following simple rule system

Rule 1 : IF A == 10, Then B= 20

Rule 2: IF B == 10, Then A = 10

Let us say we provide the rule engine with following values A= 0 and B = 10.

Since A = 0, Rule 1 was never fired,

Since B = 10, Rule 2 was fired and the rule engine set the value of A = 10.

In this case ideally, as the Rule 2 sets the value of A to 10, Rule 1 should be fired. Meaning, the result of execution of action (setting A = 10) of Rule 2 should trigger the execution of Action(Setting B = 20) of Rule 1. This is forward chaining at a very level.

In case of MS BRE, forward chaining can achieved using the update and assert function provided with the engine. As the name suggest, update is used to update the value of the existing data(facts) that is already loaded in the working memory of the rule engine. Assert is used to load new data into the working memory of the rule engine. So let us apply this knowledge to the Rule system mentioned above

Rule 1: IF A == 10, Then B = 20,

Rule 2: IF B ==10, Then A = 10 and Update(A)

Again let us provide A = 0, B = 10 to the rule engine. The rule engine working memory now contains the value of A = 0 and B = 10.

Since A = 0, Rule 1 is not fired.

Since B = 10 , Rule 2 gets fired and sets A = 10. At the same time, using update function on A, the value of A is updated to 10 in the working memory of the rule engine. The rule engine now has A = 10, B = 10 in the working memory. This update triggers the rule engine to reevaluate all the rules which had conditions checking values of A(in this case Rule 1). So conditions in Rule 1 get evaluated to true and we get value of B = 20. Since there are no more update or assert encountered in the actions of the rules, the rule engine finishes the execution and final value we have are A = 10, B = 20

XML Facts and MS BRE

Let us now understand how MS BRE deals with a XML bases facts . Consider a simple XSD as shown below.

In XML world, the standard way to access and modify the values of the elements is to use the XPATH query language. In a traditional sense if I want to read value of fiedls A in the Req, I would access the element using Xpath

MS BRE also works with the XML facts using XPATHs but slightly in a different way. Following image shows the XPATH components generated for the Field A in the Req.

BRE Generated XPath Selector and XPath fields to access the value of filed A. If we look carefully, the Xpath Selector + Xpath Field gives us the complete xpath for the field A. The BRE does it with following intentions, when the XML facts are asserted into the working memory, BRE will assert all the facts that it finds under Req to the rules defined in our system. Thus to access all the values of fact A that are inserted, the BRE uses the XPath Field to narrow down. Charles Young has explained this phenomenon in a great detail at http://geekswithblogs.net/cyoung/archive/2006/09/02/90102.aspx I strongly urge you to read the blog. I am just scratching the surface here.

Forward Chaining

Now let us put our new found knowledge to test by defining the rule System we discussed while understanding the Forward chaining above. The rules are shown as below.

I am going to assert following XML message to the rule engine to test the rule system that we created.

BRE produces following out put

YAY!! Forward Chaining works!!

Houston We Have a Problem

All works good when both A and B are present in the input XML message that we fed to the rule engine. Let see what happens when we feed following XML to the rules engine

BRE crashes and gives following error

Why did this happen?? Let us think back to how the BRE uses XPaths , by breaking them into the XPathSelector and XPathField. Following images shows how the Rule 1 reads the field A from the request

It is expecting the field A which is read using XPath field be present in the XML message always. Hence when the filed is missing from the input, BRE engine threw an error.

Fixing the Problem

BRE comes with an in built predicate “exist” which can be used on the XML based facts. As the name suggests, the exist predicate checks the existence of the xpath in the document that was asserted to the BRE.

Let us drag the xpath of the field A from Facts Explorer and into our rule.

Following are our Rule 1 and Rule 2 respectively

Let us again feed following message to the rule engine.

BRE gives following output to us

Confusing isn’t it?? Why did the exist predicate not work with the xpath that we dragged and dropped from the schema?? If we examine the condition in the Rule 1 shared above, we see that the Xpath we are checking in the exist predicate is

But the XPath with which we are reading and equating the value of field A to 20 is

It is clear now that both of the XPaths are different and hence will be handled as two different nodes in the tree structure that the Rule engine will create.

Now as we understand this, what we need to do is modify the Xpath in the exist predicate. The modified Rules look as follows.

Now each of the condition in the Rule is pointing to the same Xpath. Hence, when the rule engine transforms these rules into the tree structure, it will create only one node for the Field A and one node For Field B.

Let us again feed following message to the Rule Engine and see what happens

Rule engine produces below output

Rule Engine did not produce any error and handled the scenario gracefully. No rules were fired but the engine did not exception out!!

This approach thus provides us a fail safe way to implement forward chaining on the optional elements in our xml payloads.

This wraps up my first post in the BRE series. In next post we will take a look at how we can execute the BRE policy from .NET code and how we can use the log4net to track the execution of the policy whenever required.

Till then have a good time!! Please share feedback

Programmer by profession, curious by nature.