Tag Archive: Business Rules Engine


About a month ago I announced the release of the beta installer for the BRE Pipeline Framework. Since then I have been hard at work trying to get the framework up to scratch with the goal towards starting to use it on new projects, and at the very least to use it to make POCs a lot quicker. I have added a lot of new features to make the framework easier to use, and made a lot of tweaks.

For those who don’t know too much about the framework, the whole idea is to remove the need to constantly write variations of pipeline components used to manipulate a message’s context or body along with all the deployment issues and complications that arise when changes are required for these components, and to instead use a pipeline component that allows for message manipulation logic to be encapsulated into the BRE (Business Rules Engine) so that developers are concentrating on logic instead of plumbing.  Further details on the framework are listed on the codeplex project page, and documentation detailing installation and usage is included on the codeplex project documentation page.

Details on some of the changes below (there are many more but these are the most important ones).

  • The BREPipelineFramework.SampleInstructions.ContextInstructions vocabulary now contains definitions that allow you to get and set context properties from all the out of the box BizTalk and EDI context properties through enumeration (ie. you don’t need to know the name/schema namespace of the properties, you just need to know the .NET namespace such as BTS, EDI, or SQL and can select the property from a drop down list).
  • The set type vocabulary definitions in the BREPipelineFramework.SampleInstructions.ContextInstructions vocabulary will now allow you to set values to context properties of any type (parameter on the method changed from string to object), not just strings.
  • It is now not possible to manipulate a BizTalk message in a rule condition, only in an action which makes the framework a whole lot safer to use.  Any errors encountered in the pipeline will result in the original message/context being reverted to.
  • The pipeline component now uses VirtualStream instead of MemoryStream to improve memory management for large messages.
  • Fixed bug in the GetXPathResult definition in the BREPipelineFramework.SampleInstructions.HelperInstructions whereby the stream position wasn’t being reset and thus the message body was being lost.
  • Added BizUnit based pipeline unit tests to provide a pretty good level of coverage for functions provided by the framework.
  • Comments made throughout the source code to make it easier to understand for those who want to dive into it and extend the framework with their own MetaInstructions and Instructions.

I encourage you to try to make use of the framework and give me any feedback that you have.  My belief is that the learning curve should not be too steep and that it has the potential to increase productivity and allow developers to turn around solutions a lot faster but I need the community’s help to qualify this.  Please post any feedback to the codeplex project discussion page.

To pique your interest, below is a screenshot of one of the rules used in the framework unit tests to give you an idea of what is possible with the framework (note the use of enumerations to choose the relevant context properties).

ExampleRule

I would like to announce that the BRE Pipeline Framework Codeplex project has just been made publicly available on Codeplex.

For the best part of the year I have been working on a context heavy BizTalk Server based integration project (which was not making use of the ESB Toolkit based itineraries) and after the first few months on the project and many pipeline components later I decided there had to be a better way to manage the logic that I wanted my pipelines to implement.

I investigated more flexible frameworks and the one I found most attractive was described on this blog post by Guo Ming Li.  It allowed you to execute as many context instructions as you wanted to.  I saw this as a great starting point but I really wanted to take this further, not limiting the requirements to simply being able to add hardcoded context properties.  I also wanted to be able to read context properties, or set context properties based on the result of an XPath statement, or to set the context properties based on  values read in from the SSO database.  I also wanted to be able to implement helper methods which I could use as part of my rule conditions so I could selectively apply actions.

Seeing that my wish list was just growing larger all the time, I decided that one of the design goals for the BRE Pipeline Framework is that it should be extensible, providing a base pipeline component and a framework and allowing developers to implement their own logic as long as they implement interfaces contained within the framework.  The full list of my design goals for this project are as below.

-Reduce the amount of time required to introduce new logic into a BizTalk pipeline.  Instead concentrate on capturing logic in reusable class libraries.
-Reduce the complexities surrounding the deployment of pipeline components.  Since logic is held in business rules and class libraries which the pipeline component doesn’t have any direct references to, the pipeline component will not need to be redeployed unless there are changes to the pipeline component itself (plumbing rather than logic).
-Promote the reuse of logic used within BizTalk pipelines rather than writing new pipeline components every time a slight variation of logic is required.
-Provide a simple design time experience (BRE) which encourages developers to use pipelines appropriately and makes it easier for analysts to understand the purpose of a pipeline.
-Provide an extensible framework that allows for developers to implement their relevant requirements if not catered for out of the box in the desired manner.

Take a look at the codeplex project page if this piques your interest as it contains a lot more detail, and let me know if you are interested in contributing at all as there is much work to be done.  I’ll leave you with a screenshot of an example BRE rule to give you an idea of what the framework is trying to achieve.

ExampleRule

While debugging a pipeline component that made use of a Business Rules Engine (BRE) policy I noticed some behavior that stopped me right in my tracks (funnily enough, I actually enjoy being surprised).  Said component was asserting a .NET object into the BRE policy which contained multiple rules, some calling on the same methods exposed by the object with exactly the same parameters.  My assumption has always been that the BRE would cache all the details about facts that are used in the rules, and when forming up it’s RETE algorithm it would reuse cached details rather than fetch them from the actual facts where possible.  This assumption turned out to incorrect.

Rather than badgering on about this, let’s illustrate this with a quick example.  I have a helper class which contains a string property called Name, an int called Counter, and a boolean called Match.  The get accessor for the Name property will increment the counter by one to make note that the get accessor has been called.  The class has a constructor which sets the Name property.  The project has been signed and the dll has been registered in the GAC to ensure that the BRE can work with this class.

Next I whipped up a very quick vocabulary with a definition called GetName and another called SetMatch.  Once the vocabulary was published I constructed a policy which contain multiple rules, each containing a condition that evaluates the GetName definition against constant values.  If the conditions for any of the rules are evaluated then the rule will use the SetMatch definition to set the Match boolean to true.

Next up I whipped up a console applicaiton which instantiates a helper object with a name of Jes and then asserts the helper object into the aforementioned policy.  After the policy executes it will write the Match boolean as well as the value of Counter (which will tell us how many times Name’s get accessor has been called) to the console.  Below is the code to call the policy.

When executing the policy one would expect Counter’s value to be 1 since GetName should result in the same value no matter how many times it is used as part of a condition.  However the output in the console looks like the below (note that there were four rules in the policy).

After doing some reading, it turns out that this behavior is specific to .NET based facts and can be overridden, however not too easily, and with some implications (which I imagine are quite unlikely in the majority of scenarios but are altogether possible).  The means to overriding this behaiour is through a setting called SideEffect which sits on a function level in a BRE policy.  This setting can’t be adjusted in the Business Rules Composer however.  The simplest way to update this setting is by exporting a policy to an XML file via the Business Rules Engine Deployment Wizard, updating the XML file, and then importing it back in (either remove the existing policy before importing or increment the version number in the file before importing it to ensure there is no clash).  Now you might be thinking that if you have to update this setting in such a roundabout way then surely Microsoft never intended for this setting to be changed and the implications are probably too dangerous, however Microsoft themselves suggest that this setting should be tweaked to achieve maximum performance for BRE policy execution (relevant section in the below screenshot) – http://msdn.microsoft.com/en-us/library/ee377076(v=bts.10).aspx.

As far as implications go, I would suggest having a read of http://geekswithblogs.net/cyoung/archive/2007/04/09/111169.aspx.  This is an absolutly fantastic post that goes into great depth detailing how the BRE works, and discusses the implications of the SideEffects property in details.  From what I gather, SideEffects is defaulted to true for .NET objects as it is always possible, especially in a multi-threaded application scenario, that the object might actually be manipulated in a seperate thread between condition evaluations and thus the results might be different each time a condition is evaluated.  Chances are that this is not going to be likely for the majority of use cases involving the BRE but I suggest understanding the implication for your specific case if you decide to manipulate the SideEffects property.

The property that needs to be updated in the policy extract XML file is as below (note that you will need to update the property for all the rules in your policy that you want to be able to take advantage of caching).

After updating the extract file and then deploying the updated policy to the rules engine, the console application now outputs the expected value for Counter.

In summary, if you are making use of BRE policies that make use of .NET class based facts (and I encourage you to do so when possible as there are performance benefits when using .NET class based facts rather than XML based facts), you should ask yourself whether your policy would benefit through the use of caching of fact details or not.  While it is possible that the gains might be quite minimal, it could make all the difference in a high throughput or low latency scenario and thus this property should not be overlooked.

If you are interested in playing with this, I have uploaded a copy of my sample solution to my Google Drive folder.  Remember that you will need to GAC the Helpers project and you will also need to import the Vocabulary and Policies (contained in the BRE Artifacts sub-folder) and deploy the policies (only deploy the relevant one that you want to test) before the console application will work.

%d bloggers like this: