blob: 5bb085509321f8a1794c15a751f4c1f501594134 [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<org.eclipse.epf.uma:ContentDescription xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI" xmlns:org.eclipse.epf.uma="http://www.eclipse.org/epf/uma/1.0.5/uma.ecore"
xmlns:epf="http://www.eclipse.org/epf" epf:version="1.5.0" xmlns:rmc="http://www.ibm.com/rmc"
rmc:version="7.5.0" xmi:id="-H6wteXNcAgxFYU3xQqceZw"
name="new_guideline,_IuFgEIm-Ed2dvb7--2nAHw" guid="-H6wteXNcAgxFYU3xQqceZw" authors="Jerome Boyer"
changeDate="2010-04-01T16:23:29.703-0700" version="7.5.0">
<mainDescription>&lt;p>&#xD;
The goal of this &lt;a href=&quot;http://jcp.org/aboutJava/communityprocess/review/jsr094/index.html&quot;&#xD;
target=&quot;_blank&quot;>specification&lt;/a> aims to make the client code for simple rule-based applications less dependent on&#xD;
rule engine vendor-specific classes. The basic interactions with a rule engine are typically parsing the rules in scope&#xD;
of a rule set, adding object references to one engine, firing the rules and getting results from the engine.&lt;br />&#xD;
JSR94 defines a rule set as a &lt;em>rule execution set&lt;/em> which can be loaded from external resources like URIs, Input&#xD;
streams, XML streams and readers. A rule execution set is a collection of rules. Another important JSR94 concept is the&#xD;
&lt;em>rule session&lt;/em> which is a runtime connection between a client and a rule engine. A rule session is associated&#xD;
with a single rule execution set, consumes rule engine resources and must be explicitly released when the client no&#xD;
longer requires it. Session can be stateless or stateful. Stateless executes a rule execution set with a list of input&#xD;
objects in one call. Stateful is designed to maintain a long time conversation between the client and the engine and&#xD;
provides mechanism to assert / retract input object to the session.&lt;br />&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
The client code may run on server layer like a servlet controller, in a service tier part of an EJB or POJO, or in a&#xD;
standalone JSE JVM. The &lt;em>javax.rules&lt;/em> API divides interaction with rule engines into administrative and runtime&#xD;
interactions. The basic operations supported by JSR-94 are:&lt;br />&#xD;
• Acquiring a rule session for a registered rule execution set.&lt;br />&#xD;
• Deploying and undeploying rulesets into a rule engine instance&lt;br />&#xD;
• Querying simple metadata about a ruleset&lt;br />&#xD;
• Executing a ruleset in either a stateful or stateless mode&lt;br />&#xD;
&lt;/p>&#xD;
&lt;h5>&#xD;
The client code for run time execution&#xD;
&lt;/h5>&#xD;
&lt;p>&#xD;
&lt;br />&#xD;
From the client point of view the interaction with a rule engine is done using the rule session. But the first part is&#xD;
to get an instance of the rule engine implementation. The service provider manager helps to get a rule service provider&#xD;
which in turn helps to get rule run time and rule administration implementations. Every specific implementation exposes&#xD;
an uniquely identifier for the service provider URL.&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
&lt;br />&#xD;
// Get the rule service provider from the provider manager&lt;br />&#xD;
Class.forName(&quot;ilog.rules.bres.jsr94.IlrRuleServiceProvider&quot;);&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
RuleServiceProvider serviceProvider = RuleServiceProviderManager.getRuleServiceProvider(“ilog.rules.bres.jsr94”);&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
• For the reference implementation the URL is org.jsp.jsr94.ri.RuleServiceProvider&lt;br />&#xD;
• For JRules the is ilog.rules.bres.jsr94.IlrRuleServiceProvider, and the service provider name is&#xD;
ilog.rules.bres.jsr94&lt;br />&#xD;
• For JBoss-drools the is org.drools.jsr94.rules.RuleServiceProviderImpl and the service provider name is&#xD;
http://drools.org.&lt;br />&#xD;
The code above is used for JSE deployment, as in JEE environment runtime clients should resolve the RuleRuntime and&#xD;
RuleAdministrator services directly using JNDI lookup.&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
Javax.naming.InitialContext initialContext = new InitialContext();&lt;br />&#xD;
RuleRuntime ruleRuntime =&lt;br />&#xD;
(RuleRuntime) PortableRemoveObject.narrow(&lt;br />&#xD;
initialContext.lookup(&quot;org.jcp.jsr94.ri.RuleRuntime&quot;),RuleRuntime.class );&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
In JSE we can use an inversion of control pattern and get those URL references from a properties file or a file&#xD;
descriptor.&lt;br />&#xD;
The next step is to get a rule engine run time.&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
&lt;br />&#xD;
// Get a RuleRuntime and invoke the rule execution.&lt;br />&#xD;
RuleRuntime ruleRuntime = serviceProvider.getRuleRuntime();&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
&lt;br />&#xD;
The RuleRuntime interface exposes the method to create a rule session given a previously registered RuleExecutionSet&#xD;
URI. It is possible to execute the rule engine in stateless or stateful mode using different type of rule session. We&#xD;
need to specify the rule execution set URI and the session type.&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
&lt;br />&#xD;
StatelessRuleSession statelessRuleSession = (StatelessRuleSession) ruleRuntime.createRuleSession(ruleExecutionSetURI,&#xD;
rulesessionProperties,RuleRuntime.STATELESS_SESSION_TYPE);&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
The second parameter is optional and is used to add some additional properties to the session. In JRules it is used to&#xD;
give the references to the rule set parameters and to specify if the RuleSession is a J2SE POJO rule session or a J2EE&#xD;
POJO rule session:&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
&lt;br />&#xD;
Map rulesessionProperties = new HashMap(); rulesessionProperties.put(&quot;loan&quot;, loan);&lt;br />&#xD;
rulesessionProperties.put(&quot;borrower&quot;, borrower);&lt;br />&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
A stateless rules session exposes a stateless rule execution API to an underlying rules engine with two different&#xD;
methods to call the execution of the rule:&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
&lt;br />&#xD;
public java.util.List executeRules(java.util.List objects)&lt;br />&#xD;
throws InvalidRuleSessionException,java.rmi.RemoteException&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
&lt;br />&#xD;
The list of objects set as parameters will be inserted in the engine's working memory. The list returned includes all&#xD;
the objects created by the executed rules. The only things we can retrieve with JSR94 from an execution are the objects&#xD;
in the working memory. The second API uses a filter of objects the client code can supply to select those objects that&#xD;
should be returned from the rule engine.&lt;br />&#xD;
&lt;/p>&#xD;
&lt;h4>&#xD;
Filtering objects&#xD;
&lt;/h4>&#xD;
&lt;p>&#xD;
To filter out objects from the list of returned objects from the rule execution call, the client code needs to provide&#xD;
an implementation of the ObjectFilter interface. The implementing class receives callback methods that allow filtering&#xD;
out objects as desired. Here is a simple filter class that removes any loan which does not have messages.&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
&lt;br />&#xD;
public class MyObjectFilter implements ObjectFilter {&lt;br />&#xD;
&lt;br />&#xD;
@Override&lt;br />&#xD;
public Object filter(Object obj) {&lt;br />&#xD;
if (obj instanceof Loan) {&lt;br />&#xD;
Loan loan = (Loan)obj;&lt;br />&#xD;
if (loan.getMessages().size() != 0)&lt;br />&#xD;
return obj;&lt;br />&#xD;
}&lt;br />&#xD;
return null;&lt;br />&#xD;
}&lt;br />&#xD;
&lt;/p>&#xD;
&lt;h4>&#xD;
Get rule execution set meta data&#xD;
&lt;/h4>&#xD;
&lt;p>&#xD;
&lt;br />&#xD;
RuleRuntime can also being used to get the list of URIs that currently have rule execution set registered with them&#xD;
using the API List listURIs=ruleRuntime.getRegistrations();&lt;br />&#xD;
The other object involved is the RuleExecutionSetMetadata interface which exposes metadata about a Rule Execution Set&#xD;
to runtime clients of a RuleSession like the name, URI and description of the rule execution set.&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
&lt;br />&#xD;
RuleExecutionSetMetadata metadata=statelessRuleSession&lt;br />&#xD;
.getRuleExecutionSetMetadata();&lt;br />&#xD;
metadata.getName();&lt;br />&#xD;
metadata.getDescription();&lt;br />&#xD;
metadata.getUri()&lt;br />&#xD;
&lt;/p>&#xD;
&lt;h4>&#xD;
Stateful session&#xD;
&lt;/h4>&#xD;
&lt;p>&#xD;
&lt;br />&#xD;
Client code can use stateful session to conduct long running conversation with the engine, and control the working&#xD;
memory with new facts. Input Objects can be progressively added to the StatefulRuleSession through the addObject&#xD;
method. Output Objects can be progressively retrieved though the getObject method.&lt;br />&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
StatefulRuleSession statefulRuleSession= (StatefulRuleSession) getRuleRuntime()&lt;br />&#xD;
.createRuleSession(ruleExecutionSetURI, getProperties(loan, borrower),RuleRuntime.STATEFUL_SESSION_TYPE);&lt;br />&#xD;
//first call the normal execution&lt;br />&#xD;
statefulRuleSession.executeRules();&lt;br />&#xD;
Loan l2 = new Loan(250000,240,7.25);&lt;br />&#xD;
Handle hdl=statefulRuleSession.addObject(l2);&lt;br />&#xD;
statefulRuleSession.executeRules();&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
&lt;br />&#xD;
Objects that have been added to the StatefulRuleSession must be removed and updated using the removeObject and&#xD;
updateObject methods. A client must test for the existence of an added Object using the containsObject method. The&#xD;
removeObject, updateObject, and containsObject methods must all use a javax.rules.Handle implementation&amp;nbsp;instances&#xD;
to refer to and identify Object instances. Handle are used to ensure that Object instances can be unambiguously&#xD;
identified in the event of multiple class loaders being used or the StatefulRuleSession being serialized. The addObject&#xD;
methods returns a Handle instance for an Object added to a StatefulRuleSession, so that it can be used in the remove&#xD;
API for example.&lt;br />&#xD;
In JRules Ruleset parameters and objects added to the RuleSession when it is created are uniquely identified by an&#xD;
instance of the IlrRuleSessionHandle class.&#xD;
&lt;/p>&#xD;
&lt;h4>&#xD;
&lt;br />&#xD;
Administrate rule execution set&#xD;
&lt;/h4>&#xD;
&lt;p>&#xD;
&lt;br />&#xD;
Administrative tasks supported by the API javax.rules.admin include instantiating the rule engine and loading rules. To&#xD;
get the rule administrator we use the service provider such as: RuleAdministrator ruleAdministrator =&#xD;
serviceProvider.getRuleAdministrator();&lt;br />&#xD;
&lt;br />&#xD;
The RuleAdministrator allows RuleExecutionSet instances to be registered against a URI for use from the runtime API, as&#xD;
well as methods to retrieve a RuleExecutionSetProvider and a LocalRuleExecutionSetProvider implementation. The&#xD;
RuleExecutionSetProvider interface defines methods to create a RuleExecutionSet from a number of Serializable sources&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
LocalRuleExecutionSetProvider ruleExecutionSetProvider =&#xD;
ruleAdministrator.getLocalRuleExecutionSetProvider(null);&lt;br />&#xD;
RuleExecutionSet ruleSet = ruleExecutionSetProvider.createRuleExecutionSet( inputStream, null );&lt;br />&#xD;
ruleAdministrator.registerRuleExecutionSet( ruleSet.getName(),ruleSet,null );&lt;br />&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
The use of the local rule execution set provider is interesting to send a local execution set to a remote engine using&#xD;
serialization and marshaling. The API get(Local)RuleExecutionSetProvider takes an argument of type Map, which is&#xD;
documented as &quot;additional properties&quot; and used for setting the JNDI properties. The source for the rule can come from&#xD;
non-Serializable resources, such as binary InputStreams or character-based Readers. Registering the execution set to a&#xD;
URI helps to create session to an execution set. The rules registered using the rules admin API are the only rules&#xD;
accessible to the runtime clients.&lt;br />&#xD;
The following code gets the name and description of the execution set deployed:&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
&lt;br />&#xD;
ruleSet.getDescription();&lt;br />&#xD;
ruleSet.getName();&lt;br />&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
getName() in the case of JRules Rule Execution server deployment returns the rule set path. From the rules set we can&#xD;
get all the rules in a list and then for each rule its name and description.&lt;br />&#xD;
Rule.getName()returns in the case of JRules a string which specify the language name and the name space for this rule,&#xD;
like for example “IRL/validation/maximum_amount-brl.irl”. The rule.getDescription() returns the rule in the language of&#xD;
the rule engine vendor. For JRules it is the Ilog rule language such as:&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;codeSample&quot;>&#xD;
&lt;br />&#xD;
package validation {&lt;br />&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; rule maximum_amount {&lt;br />&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; property status = &quot;new&quot;;&lt;br />&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; when {&lt;br />&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;miniloan.Loan() from loan;&lt;br />&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; evaluate (loan.amount &amp;gt; 1000000);&lt;br />&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } then {&lt;br />&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; loan.addToMessages(&quot;The loan cannot exceed&#xD;
1,000,000&quot;);&lt;br />&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; loan.reject();&lt;br />&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br />&#xD;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br />&#xD;
}&lt;br />&#xD;
&lt;br />&#xD;
&lt;br />&#xD;
&amp;nbsp;&#xD;
&lt;/p></mainDescription>
</org.eclipse.epf.uma:ContentDescription>