Application developers can call upon the BRE to
execute business policies from within their .NET code or through the
Call Rules shape in their BizTalk orchestrations. At runtime, the
Business Rules Framework provides a caching mechanism for RuleEngine
instances. Each RuleEngine instance contains an in-memory representation
of a specific policy version.
According to the BizTalk Server 2009 documentation
(Microsoft, 2009), when a new policy instance is instantiated, either
through a direct call from a .NET application through the API or the
execution of the Call Rules shape in an orchestration, the following
happens:
The Policy object requests a RuleEngine instance from the rule engine cache.
If
a RuleEngine instance for the policy version exists in the cache, the
RuleEngine instance is returned to the Policy object. If a RuleEngine
instance is not available, the cache creates a new instance. When a
RuleEngine instance is instantiated, it does, in turn, create a new fact
retriever instance if one is configured for the policy version.
Likewise, when the Execute method is called on the Policy object, the following steps occur:
The Policy object calls the UpdateFacts
method on the fact retriever instance if a fact retriever exists. The
fact retriever's implementation of the method may assert long-term facts
into the working memory of the RuleEngine.
The Policy object asserts the short term facts contained in the Array that was passed in the Execute call.
The Policy object calls Execute on the RuleEngine.
The RuleEngine completes execution and returns control to the Policy object.
The
Policy object retracts the short term facts from the RuleEngine. The
long term facts asserted by the fact retriever will remain in the
working memory of the rule engine.
After the Dispose method is called on the Policy object, the RuleEngine instance is released back to the rule engine cache.
The rule engine cache will have multiple rule engine
instances for a given policy version if the load requires it, and each
rule engine instance has its own fact retriever instance.
1. Calling the Engine from Within an Orchestration
Orchestration developers can use the Call Rules shape
to call upon the Business Rule Engine to execute a business rule
policy. They can assert facts to the policy that they wish to execute by
passing them as parameters to the Call Rules shape. This is done by
double-clicking the Call Rules shape, which brings up the parameters
dialog depicted in Figure 1.
Some logic might require an Orchestration Designer to
use the Call Rules shape in a loop. If the loop executes quickly—i.e.,
it takes only seconds or minutes—then this is fine. If the loop spans
days and the logic is hanging on to a specific policy instance, then
"policy version updates will not be picked up by the rule engine
instance executing the policy..." and "the overall application
performance may suffer as the rule engine instance held onto by the
policy will be tied up and not returned to the pool to be reused by
other orchestrations".
|
|
Parameters to an orchestration's Call Rules shape are
implicitly defined in the policy. These facts can be XML schema
instances, .NET classes, or database elements. If a schema is referenced
in a policy's rule, the Orchestration Designer is required to pass in
an instance of that schema as a parameter as a fact that will be
evaluated.
In their orchestrations, the developers will have to
select a message that matches the same type from the drop-down list in
the Call Rules shape. Oftentimes developers run into the issue where
they are not allowed to add any parameters in the Call Rules shape. This
means there are no messages defined in the orchestration with the same
type as the schema used in the policy. The problem is that the document
type in the Business Rule Engine and the message type in the schema do
not match, so the designer cannot find any messages with the appropriate
type to populate the drop-down lists in the parameter selection dialog.
NOTE
We mentioned this before, but so many developers
run into the issue that it is worth mentioning again. If you expect to
be able to assign messages as parameters to a Call Rules shape in an
orchestration and the Orchestration Designer is not allowing you to do
so, then most probably the document type defined in the Facts Explorer
is not fully qualified; you need to fix that before you add the fields
to your rules.
2. Referencing a .NET Class from a Policy That Is Being Called from an Orchestration
A developer might want to reference and use a .NET
class in the business policies. The class could provide helper functions
to add nodes to an XML document, the ability to store rule results in
an array or a hash table, or make calls to another set of libraries
(Moons, 2005).
If the policies are using a .NET class member as a
fact in the business rules, and you need to call these policies from
within an orchestration using a Call Rules shape, you need to do two
things:
At design time, reference the assembly in the
Business Rule Composer to use the methods and/or properties in the
policy rules, so that you can create vocabulary items based on that
class, or simply use properties and member functions of that class in
your rule's conditions and actions.
Pass
an object instance of that class into the policy at runtime. This needs
to be done even if you are just referencing static members of the class.
Add
a reference to your .NET class in the BizTalk project that contains the
orchestration making the call to the business rule policy.
Add a variable to the orchestration of that .NET class type.
Create an instance object of the class in an Expression shape.
Select
the policy in the Call Rules shape and select the variable you defined
previously in the orchestration as a parameter to that policy. "The
messages or variables that are available to you in the rules shape
parameter list are determined by the XML Schemas or classes referenced
in the policy. When you select the .NET class variable you will be
asserting the class instance into the rules engine at runtime" (Moons,
2005).
3. Returning a Value from the BRE to the Calling Orchestration
Sometimes a developer needs a return value from the
business rules policy for his code to execute a different piece of logic
depending on the policy's results.
Despite the fact that the BRE doesn't support return values, it still
can "share" a common object with a calling orchestration. The shared
object could be an XML document; in this case an orchestration simply
passes through a message of that document type to be modified and
returned
by the Business Rule Engine. Or, it could be either a complex structure
or a simple single value, for example, a Boolean value. In either case,
it is not efficient to use an XML document—a BizTalk message—to pass
those values back and forth; using an object instance of a .NET class
would be the right approach. The following example of using a .NET class
in a policy will illustrate how an object instance of a .NET class can
be used to act as a return value from a policy. A policy will be
executed and an action fired that sets a Boolean public property on a
class.
You start off by writing a simple class that has a public Boolean property:
public class MyReturn
{
private bool approved;
public bool Approved
{
get{ return approved; }
set{ approved = value; }
}
}
After compiling this class into a .NET library and
deploying its assembly to the GAC, reference that assembly from the
Business Rule Composer and set the property of this class in an action
to true or false, either by dragging the property from the .NET Class
Facts Explorer or by creating and using a vocabulary definition. Your
rule should look something like Figure 2.
Reference that assembly in the BizTalk project
hosting the orchestration that will call the policy and create a
variable of type MyReturn. Assign a reference of a new object instance
of this class to the variable in an Expression shape and pass it as a
parameter to the policy in the Call Rules shape as in Figure 3.
hlpr = new RulesHelper.Helper();
The orchestration can access the class's Boolean
property in a Decision shape to find out what value it was set to in the
Business Rule Engine.
hlpr.Approved == true
To test the policy from the Business Rule Composer, you can write a fact creator to cre-ate an object instance of the MyReturn class.