Showing posts with label Biztalk 2006 R2. Show all posts
Showing posts with label Biztalk 2006 R2. Show all posts

Wednesday, August 06, 2008

BizTalk Business Rules Engine Handy functions in .NET

Working with the BizTalk 2006 R2 BRE api, I find myself going back to this code to start of as a base. These 2 functions get ALL of the versions of the policies or vocabularies.  If you want to work with only the latest, or the published ones, change the RulesStore.Filter enum to whatever your needs.

List of Policies

   1: public void GetPoliciesList()
   2: {
   3:     Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver breDriver =
   4:         new Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver();
   5:     Microsoft.RuleEngine.RuleStore breStore = breDriver.GetRuleStore();
   6:  
   7:     Microsoft.RuleEngine.RuleSetInfoCollection colPolInfo = null;
   8:     colPolInfo = breStore.GetRuleSets(RuleStore.Filter.All);
   9:     foreach (RuleSetInfo pInfo in colPolInfo)
  10:     {
  11:         Trace.WriteLine(string.Format("bts- Info = [{0}].v.{1}.{2}",
  12:             pInfo.Name, pInfo.MajorRevision, pInfo.MinorRevision));
  13:  
  14:         //get the policies to extract rules
  15:         Microsoft.RuleEngine.RuleSet pol = breStore.GetRuleSet(pInfo);
  16:         Trace.WriteLine(string.Format("bts- Count = [{0}]", pol.Rules.Count));
  17:     }
  18: }

This is how to get a list of all policies published on the BRE database.  Once you get all of the RuleSets, you can loop through each of them to retrieve the actual rules behind them.  Before getting to the rules, you need to get a RuleSet out of the RuleSetInfo.


List of Vocabularies



   1: public void GetVocabulariesList()
   2: {
   3:     Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver breDriver = 
   4:         new Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver();
   5:     Microsoft.RuleEngine.SqlRuleStore sqlRuleStore = (SqlRuleStore)breDriver.GetRuleStore();
   6:  
   7:     Microsoft.RuleEngine.VocabularyInfoCollection colVocInfo = null;
   8:     colVocInfo = sqlRuleStore.GetVocabularies(RuleStore.Filter.All);
   9:     foreach (VocabularyInfo vInfo in colVocInfo)
  10:     {
  11:         Trace.WriteLine(string.Format("bts- vInfo = [{0}].v.{1}.{2}",
  12:             vInfo.Name, vInfo.MajorRevision, vInfo.MinorRevision));
  13:  
  14:         //get the vocabulary to extract collection of definitions
  15:         Microsoft.RuleEngine.Vocabulary voc = sqlRuleStore.GetVocabulary(vInfo);
  16:         Trace.WriteLine(string.Format("bts- Count = [{0}]", voc.Definitions.Count));
  17:     }
  18: }

This is how to get a list of all vocabularies published on the BRE database.  If you need to see how to get to all of the definitions on a particular vocabulary, see my previous post: How to access BRE Vocabularies from .NET.


Noticed that there are some subtle differences in how you retrieve each piece of information.  For Policies you get a RuleStore while to get the Vocabularies you need to get a SQLRuleStore.


As usual, feedback is always welcome if you use this code.

Tuesday, July 29, 2008

Deploying Business Rules using C# in BizTalk 2006 R2

In one of my last project, I have been working extensively with the Business Rules Engine in BizTalk. This project contains some complex Federal/State/Company/ rules. Being a Health Management Care related project I have to deal with many issues like requirements, changing policies, rules scope to a certain type, etc.

Delivering this project took some time and effort.  Not only the requirements were *agile*, but trying to keep compliance with SOX laws was a challenge.  I can summarized all of the requirements to these 3:

Requirements:

  1. Policies have to be atomic (independent from changes to other policies)
  2. Versionning of policies and being able to execute ANY version, any time.
  3. Need to know which facts were used to determine an outcome.

For the main requirement, I have created a Master Rule that determine the outcome, then I've created several *supporting* rules that will help me determine which of the rules were evaluated. The versionning requirement was already implemented by the BRE in BizTalk.

a sample of this would be something like this:

image

It quickly became very obvious that I have to deal with lots of policies and vocabularies.  If you ever tried using the Rules Deployment Wizard, you will see that it only allows you to export a SINGLE policy at a time.  Having over 500+ policies and over 30+ vocabularies  was not going to work out.

I have found the DeployRules.exe application written by Sreedhar Pelluru from Microsoft.  Here is the original article.  I took his program and modified to meet my needs.  Since I was only testing a set of policies at a time (i.e. Federal policies only), this tool provide me the ability to only load those policies that were relevant to the type I was working on. 

I know I have learned a lot about the BRE api from reading his well documented code.  With his permission, I have posted his original work and the modifications done to it back to the community at http://www.codeplex.com/DeployRules.  Yes it is still a work in progress.

Hope this help someone out there.

Tuesday, July 08, 2008

Importing BRE Vocabulary with Multiple versions

If you ever tried merging all of the versions of a single vocabulary into one XML file, so that you can import it on a single task, you will find that even though the Rules Engine Deployment Wizard understand the file format, it has a huge limitation [Bug..?  ;) ].  It only imports the last version of a vocabulary into the Rules Engine.

image

A sample vocabulary with 2 versions.

image

When Exporting this vocabulary I can't export all versions at once.  I have to export a single version at a time.!!

However, on the import, you can import a file that can contain multiple versions on it:

image

Once you export all individual files, you can merged them into a single xml file.

The format of the merged exported vocabulary will be something like this:

<brl xmlns="http://schemas.microsoft.com/businessruleslanguage/2002">   

  • <vocabulary id="9ab458cc-427a-4cea-bb1d-224dd5f96d98" name="CustomerLevels" uri="" description="">
            <version major="1" minor="1" description="" modifiedby="awing" date="2008-07-07T23:22:33.401-04:00"/>
            <vocabularydefinition id="b36b276e-451d-4783-8a06-623823211f85" name="Silver" description="Silver Description">
                ....................
        </vocabulary>

   

  • <vocabulary id="2422362a-77c0-4d0f-b2aa-fe6c1fe1f1d7" name="CustomerLevels" uri="" description="">
           <version major="1" minor="0" description="" modifiedby="awing" date="2008-07-07T22:39:37.19-04:00"/>
            <vocabularydefinition id="ba912d07-f96d-49ac-a2c4-e619fcec027e" name="Silver" description="Silver Description">
                ........................
        </vocabulary>

</brl>

As you can see there you can add as many versions to this file as you want.  However, the ReDeployWiz.exe only publish and import the latest one.

Trying to figure out why this is the behavior, I used my good old friend Reflector. Bringing Reflector on the Rules Engine Deployment Wizard, I see that there is a call to the RuleSetDeploymentDriver namespace. This doImport method calls the driver.ImportAndPublishFileRuleStore to import and publish at the same time.

RuleSetDeploymentDriver

image

It seems that there is no way around this call.  It seems to be a limitation on the use of the tool.  This ImportAndPublishFileRuleStore seems to only work on a single version at a time.  If you split the versions into their own file, it can handle it. The down side of this, is that you need to make multiple calls for an import.  And let's face it, the whole nature of versioning the policies and vocabularies becomes very cumbersome when you have over 500+ rules with multiple versions in them [yes, my current project has over 500+ policies and over 30+ vocabularies]

To get around this limitation on the tool, you will have to write your own application to deploy/export all versions of a vocabulary.  To accomplish this you will need to to call the SqlRuleStore namespace instead of the RuleSetDeploymentDriver.  This namespace have the ADD method which contain several overloaded parameters. One of which it allows you to publish or not publish your vocabulary.

image

Here is my sample code to import ALL versions of a vocabulary in .NET code:

    1 private static int ImportVocabulary(string filename)
    2 {
    3     int result = 0;
    4     // FileRuleStore - gives access to the BRL (XML) file containing policies and vocabularies
    5     FileRuleStore fileRuleStore = null;
    6 
    7     // RuleSetDeploymentDriver has the following important methods            
    8     Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver dd = new Microsoft.BizTalk.RuleEngineExtensions.RuleSetDeploymentDriver();
    9 
   10     // SqlRuleStore - gives access t0 the rule engine database
   11     SqlRuleStore sqlRuleStore = (SqlRuleStore)dd.GetRuleStore();
   12 
   13     //Get VocabularyInfoCollection object based on the file
   14     fileRuleStore = new FileRuleStore(filename);
   15     VocabularyInfoCollection vocabularyInfoList = fileRuleStore.GetVocabularies(RuleStore.Filter.All);
   16     foreach (VocabularyInfo vocabularyInfo in vocabularyInfoList)
   17     {
   18         string vocabularyNameWithVer = string.Format("{0}.{1}.{2}", vocabularyInfo.Name, vocabularyInfo.MajorRevision, vocabularyInfo.MinorRevision);
   19         ExtractVocabularyNameMajorMinor(vocabularyNameWithVer);
   20         VocabularyInfo vi = new VocabularyInfo(App.vocabularyName, App.vocabularyMajorVer, App.vocabularyMinorVer);
   21         Vocabulary oVoc = fileRuleStore.GetVocabulary(vi);
   22         sqlRuleStore.Add(oVoc, App.publishVocabulary);
   23     }
   24     return result;
   25 }

There, now you don't have to be bound to import a single vocabulary version every time you need to move your rules from DEV to UAT to PROD.


Hope this saves someone lots of time and grief.  Happy BRE'ing... ;)

Wednesday, May 14, 2008

Distinguished fields of type xs:dateTime not Working on Orchestrations

Writing a spyke for a simple program, I came out with this odd behavior when I try to compile my BizTalk project.

image

I have created a simple schema, and in one of the fields I have field of type xs:dateTime. Well, when I have tried to use this field on an expression shape, I get this build compiler error:

'System.Xml.XmlDocument' does not contain a definition for 'XXXX'

where XXXX is the field name of the element that I have declared as a xs:dateTime type. I then went and set it up as a distinguished field. Here is a sample generated xml from my test schema:

  1. <ns0:Customer xmlns:ns0="http://DistingProperty.Test.Customer.v1">
    <FName>FName_0</FName>
    <DOB_datetime>1999-05-31T13:20:00.000-05:00</DOB_datetime>
    <DOB_date>1999-05-31</DOB_date>
    </ns0:Customer>

and this is the schema that I have used


image

When I am trying to use the distinguished field inside an expression shape, noticed that I get the Visual Studio IntelliSense:

image

When you try to read this value, it will always complain about the XmlDocument not being able to find the definition for the field that is defined as DateTime.

To get around this, you should use the System.Convert.ToString() instead of the .ToString() function;


1 Trace.WriteLine(" bad:[" + msgIN.DOB_datetime.ToString() + "]");

2 Trace.WriteLine("good:[" + System.Convert.ToString(msgIN.DOB_datetime) + "]");



Another lengthy way to get around this issue is to assign the distinguish field to an xmlNode and then use the xml Namespace Manager to get to the node value instead.

The code on my expression shape looks like this:


1 System.Diagnostics.Trace.WriteLine("bts- In here");

2

3 //assign values to person

4 xDoc = msgIN;

5

6 xmlnsMgr = new System.Xml.XmlNamespaceManager(xDoc.NameTable);

7 xmlnsMgr.AddNamespace("ns0", "http://DistingProperty.Test.Customer.v1");

8

9 xNode = xDoc.SelectSingleNode("/ns0:Customer/DOB_datetime", xmlnsMgr);

10 System.Diagnostics.Trace.WriteLine("bts-[" + xNode.OuterXml + "]");

11

12 xNode = xDoc.SelectSingleNode("/ns0:Customer/DOB_date", xmlnsMgr);

13 System.Diagnostics.Trace.WriteLine("bts-[" + xNode.OuterXml + "]");

14

15 //this works as expected

16 System.Diagnostics.Trace.WriteLine("bts- " + msgIN.FName);

17


Which ever way you choose, this looks like a limitation on the way the XLANG/s in the Expression shape interprets the command code.

Wednesday, April 02, 2008

MOCSDG: Mid Ohio Connected System Developer's Group - OSLO

Yeah, the first meeting of this group will be kicked off this Thrusday.!! Don't miss it. If you want to be on the mailing list, email Monish and he will add you to the list. The meeting will be held at the Microsoft Office in Columbus, OH.

This first meeting, is going to be started with a presentation from Delbert Murphy. He is one out of 90 MCA's that holds this certification. He is the only Certified Architect in both Microsoft .NET and Java that I have met. So this is a good opportunity to meet him (even if you DONT believe in Certifications... blog post coming....;)

He will be talking about OSLO, which is not just the next version of BizTalk, but the next generation of a unified platform for integrating applications and services. (lots of buzzwords... ;) This is all part of the Connected Systems Division at Microsoft and I believe these set of technologies that Microsoft is working on will have everything including the kitchen sink!! Elkay Mystic Kitchen sink Don't believe me?

... the technology to deliver these capabilities will be delivered through BizTalk Server "V6", System Center "V5", Visual Studio "V10", BizTalk Services "V1" and .NET Framework "V4". The code name for this effort is "Oslo"...[read whole article]

  1. Visual Studio v.10
  2. System Center v.5
  3. Biztalk Services v.1
  4. .NET framework v4.0
  5. Biztalk Server v.6

and that is very powerful.! And if you are a Challenge Junkie like Brian said, then OSLO will give you something to get excited about.

Friday, February 29, 2008

Grok talk on Business Rule Engine Essentials

I have presented a grok on BRE essentials tonight at our monthly Solutions Group meeting.  The main focus on my presentation was to give a quick glance at what is available to developers when they enter the realm of BizTalk.  Some smart guy once said that knowing what's available out there is half the battle.

Anyways, the main points of my talk was to show how you can interface with the BRE (from BRE to .NET, and from .NET to BRE).  I have found the BizTalk rules engine to be very efficient and fast.  In the last project we have, we had over 450+ policies, and each policy had an average of about 5-7 rules on each of them.  On top of that I had an orchestration that call the vocabularies, determine the policy that needed to be executed, and then execute that policy.  The time for all of this to happen, is between 1-2 seconds from the time the message enter BizTalk to the time it gets send back to the calling routine.

How do you show this much functionality in 20 minutes or less?  Well, I came out with this fictitious company that had the following requirements:

image

The first thing that you do in BizTalk is that you need to define the schemas that will contain the inputs and output of the message that you are dealing with.  So a simple schema:

image

Next, I have implemented those rules in the BRE composer

image

So now that I have the rules implemented, we need to get a way to call them and executed them.  Here is the sample solution code that will call this policy.

I have also included some code that shows how to call the vocabulary.  And some code to show how to implement a .NET assembly that can be called from the BRE.

image 

 

Feedback [good|bad] is always welcome.  Hope this help someone get a small peek into the vast universe of BizTalk.

Tuesday, November 13, 2007

Biztalk 2006 R2 Upgrade gotchas?

I just finished upgrading to R2 on my Vista x64. So far everything seems to be running fine, except....

Business Rules Engine:

There is a new location for the assemblies now. On Biztalk 2006, the location for the BRE assemblies was this

c:\Program Files (x86)\Microsoft BizTalk Server 2006\Microsoft.RuleEngine.dll

However, after removing my 2006 version, and freshly installed the R2 version, I have to go and recompile all of my assemblies that had a reference to the Microsoft.RuleEngine. The new location is

C:\Program Files (x86)\Common Files\Microsoft BizTalk\Microsoft.RuleEngine.dll

Other than this, everything seems to be running smoothly (Orchestrations, pipelines, etc...) so far. I will update this post as I find any more gotchas (if any... ;)