🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: cn.bbs.comp.lang.java
Article #22036

Jess and the javax.rules API

#22036
From: ��ʵ��ɵ
Date: Fri, 31 Oct 2003 04:25
230 lines
15244 bytes
Jess and the javax.rules API
                          ByErnest Friedman-Hill
October 2003
Introduction
Jess is a rule engine and scripting environment for the Java platform. JSR 9
4 is a developing Java Community Process standard for interfacing rule engin
es to Java software. The reference implementation of JSR 94 is a driver for 
Jess; with it, you can connect Jess to Java software using the vendor-indepe
ndent JSR 94 API. In this article, based on an excerpt from the new book "Je
ss in Action" from Manning Publications (http://www.manning.com/friedman-hil
l,) you��ll see how to apply this new API to access Jess from your J2EE or J
2SE applications.
JSR 94: the javax.rules API
Rule-based programming is a declarative programming technique in which you w
rite heuristic rules rather than procedural instructions. A software module 
called a rule engine decides how to apply the rules to your data. Rule-based
 programming is widely used in the insurance and financial services industri
es, among others, and is especially useful whenever complex criteria must be
 applied to large amounts of information.
Rule engines can be used together with various commercial off-the-shelf prod
ucts, including application servers. Historically, there has been a certain 
amount of vendor lock-in in choosing a rule engine, because each rule engine
 has its own programmer��s interface.
The Java Rule Engine API (http://www.jcp.org/jsr/detail/94.jsp), defined by 
the javax.rules package, is a standard enterprise API for accessing rule eng
ines, currently being developed by a consortium of rule engine vendors under
 the Java Community Process. The javax.rules package will allow the host pro
gram to interact generically with multiple rule engines, the same way the Ja
va Database Connectivity (JDBC) API makes it possible to write vendor-neutra
l database programs. The API will include mechanisms for creating and managi
ng sets of rules; for adding, removing, and modifying objects in working mem
ory; and for initializing, resetting, and running the engine.
The javax.rules package can be used in both J2SE and J2EE applications. It i
ncludes mechanisms for storing and managing rule bases as well as classes th
at represent individual sessions with a rule engine. Using the javax.rules p
ackage, you can write Java code to work with rule engines in a generic manne
r, so that changing from one rule engine to another won��t necessitate chang
es to your Java code. The name JSR 94 refers to the standards committee that
 developed this new API.
Implementations of JSR 94 intended for use with J2EE containers deal with th
e programming restrictions imposed by that environment. For example, some JS
R 94 implementations will be implemented on top of an RMI-based rule server 
like the one developed in Chapter 21 of "Jess in Action." Other JSR 94 imple
mentations will be targeted toward high performance in J2SE applications, an
d some will switch between the two.
At the time of this writing, the JSR 94 specification is being readied for p
ublic release, and one of the implementations, which is the reference implem
entation, is a driver for Jess. It is possible that some of what I��ll prese
nt here will change, but most of this material will still be valid when the 
javax.rules API becomes official.
Working with javax.rules
The javax.rules API divides interaction with rule engines into administrativ
e and runtime interactions. Administrative tasks include instantiating the r
ule engine and loading rules, and runtime tasks include manipulating working
 memory and executing rules. If you use javax.rules from a J2SE program, you
��ll probably need to perform all of these tasks from your code. On the othe
r hand, in the J2EE environment, the administrative tasks are part of applic
ation deployment. Eventually, javax.rules-compliant application servers shou
ld offer dedicated mechanisms - GUIs - for installing a rule engine and prep
aring rule sessions, just as they currently include tools for plugging in da
tabases and other resources. The JSR 94 reference implementation includes a 
JCA connector that makes a RuleServiceProvider accessible through JNDI.
Setting things up
The administrative phase begins with finding an appropriate javax.rules.Rule
ServiceProvider object, which gives the programmer access to the rest of the
 javax.rules implementation. In a J2EE environment, you may be able to retri
eve the RuleServiceProvider using JNDI. Otherwise, you can get one from the 
javax.rules.RuleServiceProviderManager class:
String implName = "org.jcp.jsr94.ri.RuleServiceProvider";
Class.forName(implName);
RuleServiceProvider serviceProvider =
    RuleServiceProviderManager.getRuleServiceProvider(implName);
This is a little like loading a JDBC driver - it��s a similar concept, in th
at both provide access to an external resource, and you need to do some gene
ral initialization before you instantiate any of the classes.
Once you have the RuleServiceProvider, you can retrieve a javax.rules.admin.
RuleAdministrator. From the RuleAdministrator, you can get a RuleExecutionSe
tProvider, which, as the name suggests, creates javax.rules.RuleExecutionSet
s. A RuleExecutionSet is basically a loaded set of rules, ready to be execut
ed.
The javax.rules.admin package includes two different RuleExecutionSetProvide
r classes. RuleExecutionSetProvider itself includes methods for creating Rul
eExecutionSets from serializable objects, and therefore can be used when the
 rule engine is located in a remote server; the constructor arguments can be
 sent via RMI. Another class called LocalRuleExecutionSetProvider includes a
dditional methods to create RuleExecutionSets from nonserializable resources
 like java.io.Reader objects (local files). Given a RuleServiceProvider, you
 can create a RuleExecutionSet from a local file rules.xml like this:
RuleAdministrator admin = serviceProvider.getRuleAdministrator();
HashMap properties = new HashMap();
properties.put("name", "My Rules");
properties.put("description", "A trivial rulebase");
FileReader reader = new FileReader("rules.xml");
RuleExecutionSet ruleSet = null;
try {
    LocalRuleExecutionSetProvider lresp =
        admin.getLocalRuleExecutionSetProvider(properties);
    ruleSet = lresp.createRuleExecutionSet(reader, properties);
} finally {
    reader.close();
}
You then register the RuleExecutionSet with the RuleAdministrator under a we
ll-known name. At runtime, you use the same name to create a RuleSession; th
e RuleSession uses the named RuleExecutionSet. This example uses the well-kn
own name rules:
admin.registerRuleExecutionSet("rules", ruleSet, properties);
Executing the rule engine
In the runtime phase, you create a RuleSession. A RuleSession is basically a
n instance of a rule engine with a specific set of rules loaded into it. You
 get RuleSessions from the javax.rules.RuleRuntime object, and you get the R
uleRuntime, in turn, from the RuleServiceProvider.
There are two kinds of RuleSessions: stateful and stateless. They differ in 
the capabilities they offer. The working memory of a StatefulRuleSession per
sists between method calls. You can add objects to working memory in a serie
s of invocations, then run the engine, and then add more objects and run aga
in. In contrast, a StatelessRuleSession is a one-shot affair: To call its ex
ecuteRules methods, you must supply the entire initial contents of working m
emory, and you will receive a list of the final contents as a return value.
Here you create a StatefulRuleSession, add two objects (an Integer and a Str
ing) to working memory, execute the rules, and then retrieve the entire cont
ents of working memory as a java.util.List. Finally, you dispose of the Rule
Session by calling release:
RuleRuntime runtime = rsp.getRuleRuntime();
StatefulRuleSession session = (StatefulRuleSession)
    runtime.createRuleSession("rules", properties,
    RuleRuntime.STATEFUL_SESSION_TYPE);
session.addObject(new Integer(1));
session.addObject("A string");
session.executeRules();
List results = session.getObjects();
session.release();
The javax.rules API is clearly designed to be used in a managed environment 
like the J2EE. For a simple application like the one we��re imagining here, 
it could be overkill. Consider that by using Jess��s native API, all the cod
e in this section and the preceding one can be expressed as follows (assumin
g the appropriate defclasses are defined in rules.clp):
Rete session = new Rete();
session.executeCommand("(batch rules.clp)");
session.definstance("java.lang.Integer", new Integer(1), false);
session.definstance("java.lang.String", "A string", false);
session.run();
Iterator results = engine.listDefinstances();
On the other hand, both in the J2EE environment and in standalone applicatio
ns, javax.rules gives you some measure of vendor independence.
The Reference Implementation
The first implementation of javax.rules is the reference implementation (RI)
 included as part of the specification. This RI is, as I mentioned earlier, 
a wrapper for Jess. Jess is a rule engine and scripting environment written 
in Java. You can learn more about Jess (and download a trial version) from h
ttp://herzberg.ca.sandia.gov/jess.
The RI is an interesting case study, because the mapping of the javax.rules 
API forces a specific interpretation onto Jess��s more general facilities. H
ere I��m not concerned with describing how it is implemented, but simply wit
h filling in the missing information that allows you to use it.
javax.rules is not a standard rule language; it says nothing about rule lang
uages. Other groups are working on developing standardized rule languages, a
lthough less consensus exists in this area. For the same reason there is no 
one standard general programming language, it is likely that vendor-specific
 rule languages will be with us for a long time. Each rule language has its 
own strengths and weaknesses, and the expressiveness, elegance, and power of
 a rule language can be a major factor in choosing a rule engine. Therefore,
 if you change rule engine vendors, you will probably have to rewrite your r
ules, even if you don��t need to change your Java code. In this section, you
��ll see how to write Jess code that fits into the javax.rules framework.
Generally, the rules in a rule engine can operate on Java objects. Those Jav
a objects that have been made available to the rules are known as working me
mory elements. Working memory elements in a RuleSession are arbitrary Java o
bjects. Because Jess doesn��t let you add arbitrary objects to working memor
y without providing extra information in the form of a definstance call, the
 RI has to make some assumptions and provide the extra information. Every ti
me an object is added to working memory, Jess automatically defines a defcla
ss for it; the defclass name is the full class name of the object: com.acme.
Employee, for example. Therefore, a Jess program meant for use within the JS
R 94 RI (here, a trivial rule to give an employee a promotion after three ye
ars) might look like this:
(defclass com.acme.Employee com.acme.Employee nil)
(defrule promote-programmer
    ?e <- (com.acme.Employee (rank "Programmer I")
                             (service ?s&:(> ?s 3)))
    =>
(modify ?e (rank "Programmer II")))
Working memory elements that are not JavaBeans call for a different programm
ing style, compared to normal Jess. You can use individual patterns to bind 
objects, as is the case here, but most tests will be fairly verbose and so s
hould be expressed as test conditional elements, as in the following example
:
(defrule find-number-3
    (java.lang.Integer (OBJECT ?i1))
    (test (eq 3 (?i1 intValue)))
    =>
    ;; Found 3, do something...
One other thing about the RI is special: The input files must be XML, rather
 than normal Jess input files. The format is exceedingly simple. Each XML fi
le must contain a rule-execution-set element, which contains three children:
 a name (the name of the set of rules); a description (a brief summary of th
e rule��s purpose); and a code element, which contains Jess code. Note that 
the Jess code has to use normal XML encoding, so that special characters lik
e & and < must be represented using their escape characters. Here��s a rule 
base containing the single add-two-integers rule:
Finally, note that the RI is by definition a strictly conforming implementat
ion of the javax.rules API. As such, there are no hooks to give you access t
o queries, store/fetch, or other Jess features that go beyond the lowest com
mon denominator of what a rule engine offers. The javax.rules API doesn��t p
rovide a specific escape mechanism by which vendors can expose nonstandard i
nterfaces, although many of its methods accept property lists as a customiza
tion mechanism. Jess is more than just a rule engine, so the javax.rules int
erface limits what you can do with Jess. When the javax.rules API is finaliz
ed, Jess will offer native support for it, including extensions to allow acc
ess to these features and more.
Summary
The javax.rules API, which as of this writing is still being developed, prom
ises to provide portable, generic access to rule engines from multiple vendo
rs. The API includes sophisticated features for managing rule bases in the J
2EE environment, but is still fairly simple to use in runtime components. Th
e javax.rules API provides one way to integrate the Jess rule engine into en
terprise applications. Although the javax.rules API is not without its flaws
, it represents a powerful capability and will be a welcome addition to the 
Java toolbox.
About the Author
Dr. Friedman-Hill is a Principal Member of the Technical Staff at Sandia Nat
ional Laboratories in Livermore, California. He is the developer of Jess, th
e Java rule engine. He has taught Java programming to over 3,000 students fo
r the University of California Extensions in Berkeley, in San Diego, and onl
ine. Dr. Friedman-Hill's current work at Sandia includes the development of 
software for mechanical design and analysis. He lives in Gaithersburg, MD. 


--
��ʱû��ǩ��
�� ��Դ:���ɽ��ˮ bbs.neu.edu.cn��[FROM: 219.216.70.3]
Technical Details
Message-ID: <495CfP$C8y@bbs.neu.edu.cn>
Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!news.maxwell.syr.edu!elnk-pas-nf1!elnk-nf2-pas!newsfeed.earthlink.net!sjc70.webusenet.com!news.webusenet.com!news.neu.edu.cn!NEU

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,GB
X-Google-Thread: f6cb0,1e15dd5df273b7be,start
X-Google-Attributes: gidf6cb0,public
X-Google-ArrivalTime: 2003-10-30 20:26:10 PST
Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!news.maxwell.syr.edu!elnk-pas-nf1!elnk-nf2-pas!newsfeed.earthlink.net!sjc70.webusenet.com!news.webusenet.com!news.neu.edu.cn!NEU
From: huntersazi.bbs@bbs.neu.edu.cn (��ʵ��ɵ)
Newsgroups: cn.bbs.comp.lang.java
Subject: Jess and the javax.rules API
Date: 31 Oct 2003 04:25:11 GMT
Organization: ��ɽ��ˮ
Message-ID: <495CfP$C8y@bbs.neu.edu.cn>
Mime-Version: 1.0
Content-Type: text/plain; charset="gb2312"
Content-Transfer-Encoding: 8bit
X-Filename: java/M.1067574217.A
Lines: 230