[jboss-svn-commits] JBL Code SVN: r18786 - in labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en: Chapter-Deployment and 1 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Mar 10 02:13:41 EDT 2008
Author: irooskov at redhat.com
Date: 2008-03-10 02:13:40 -0400 (Mon, 10 Mar 2008)
New Revision: 18786
Modified:
labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en/Chapter-BRMS/Section-UserGuide.xml
labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en/Chapter-Deployment/Section-Deployment.xml
labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en/Chapter-Rule_Engine/Section-The_Drools_Rule_Engine.xml
Log:
Completed Drools Rule Engine re-wording, going through Deployment and added in a section id anchor to the Userguide
Modified: labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en/Chapter-BRMS/Section-UserGuide.xml
===================================================================
--- labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en/Chapter-BRMS/Section-UserGuide.xml 2008-03-10 01:51:00 UTC (rev 18785)
+++ labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en/Chapter-BRMS/Section-UserGuide.xml 2008-03-10 06:13:40 UTC (rev 18786)
@@ -881,7 +881,7 @@
"consume" them in your application? This section covers the usage of the
RuleAgent deployment component that automates most of this for you.</para>
- <section>
+ <section id="Chapter-BRMS-Section-UserGuide-The_Rule_Agent">
<title>The Rule Agent</title>
<para>The rule agent is a component which is embedded in the core
Modified: labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en/Chapter-Deployment/Section-Deployment.xml
===================================================================
--- labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en/Chapter-Deployment/Section-Deployment.xml 2008-03-10 01:51:00 UTC (rev 18785)
+++ labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en/Chapter-Deployment/Section-Deployment.xml 2008-03-10 06:13:40 UTC (rev 18786)
@@ -2,18 +2,15 @@
<section>
<title>Deployment options</title>
- <para>Once you have rules integrated in your application (or ideally before)
- you will need to plan how to deploy rules along with your application.
+ <para>Once the rules have been integrated into the application (or ideally before),
+ planning on the deployment of the rules alongside the application will need to be undertaken.
Typically rules are used to allow changes to application business logic
without re-deploying the whole application. This means that the rules must
- be provided to the application as data, not as part of the application (eg
+ be provided to the application as data, not as part of the application (for example,
embedded in the classpath).</para>
- <para>The recommended way of deploying depends on how you are managing your
- rules. If you are using the BRMS, you should use the RuleAgent (the detailed
- documentation for this is in the chapter on the BRMS). You can still use the
- RuleAgent even without the BRMS, in which case you will need to use ant (the drools-ant task or
- something custom) to create serialized "Package" objects of your rules.</para>
+ <para>The recommended way of deploying depends on how the management of the rules is being undertaken. If the BRMS is in use, the RuleAgent (the detailed
+ documentation for this is in the <link linkend='Chapter-BRMS-Section-UserGuide-The_Rule_Agent'>Depoyment-RuleAgent</link> section on the BRMS) is the best option. The RuleAgent can be used without the BRMS, in which case the program <productname>ant</productname> will need to be used (drools-ant) to create serialized "Package" objects of your rules.</para>
<para>As every organization is subtly different, and different deployment
patterns will be needed. Many organizations have (or should have)
@@ -21,38 +18,35 @@
best to think of rules as "data" rather then software in that regard.
However, as rules can contain a considerable amount of powerful logic,
proper procedures should be used in testing and verifying rule changes, and
- approving changes before exposing them to the world. If you need to "roll
- your own" deployment, or have specific deployment needs, the information is
- provided in this chapter for your reference, but for the most part, people
- should be able to deploy either as the agent, or in the classpath.</para>
+ approving changes before exposing them to the world. If you need to undertake specific deployment needs, the information is
+ provided in this chapter, but for the most part, deployment should be able to happen as either the agent, or in the classpath.</para>
<section>
<title>Deployment using the RuleAgent</title>
<para>The easiest and most automated way to deploy rules is to use the
- RuleAgent. This is described in detail in the BRMS user guide. In short,
- the rule agent requires that you build binary packages of rules outside of
- "your" application (ie the application that is using rules).</para>
+ RuleAgent. The rule agent requires that binary packages of rules be built outside of
+ the application (the application that is using rules).</para>
- <para>The upside of this is that your application only needs to include
- drools-core.jar - no other dependencies (of course you need the classes
- that form the model that the rules use as well !). It also means the agent
- can be configured to automatically monitor for rule changes - directly to
+ <para>The upside of this is that the application only needs to include
+ drools-core.jar - no other dependencies apart from the classes
+ that form the model that the rules use. It also means the agent
+ can be configured to automatically monitor for rule changes; directly to
the BRMS, or from a file/directory.</para>
<para>To use the rule agent in your application use the following
code:</para>
- <programlisting>RuleAgent agent = RuleAgent.newRuleAgent("/MyRules.properties");
+ <screen>RuleAgent agent = RuleAgent.newRuleAgent("/MyRules.properties");
RuleBase rb = agent.getRuleBase();
rb.newStatefulSession....
//now assert your facts into the session and away you go !
-</programlisting>
+</screen>
<para>The MyRules.properties is a configuration file which (in the above
case) should be on the root of your classpath:</para>
- <programlisting>##
+ <screen>##
## RuleAgent configuration file example
##
@@ -64,40 +58,37 @@
poll=30
-name=MyConfig</programlisting>
+name=MyConfig</screen>
<para>In the above config, the agent will look for binary package files in
- /my/dir, and also at the specified URLs. It will pick up any changes for
- these packages and apply them to the rulebase.</para>
+ /my/dir, and also at the specified URLs. Any changes for
+ these packages will be found and appled to the rulebase.</para>
- <para>If you are using the BRMS, you can use the url feature. You can use
- "file" or "dir" if the packages need to be manually migrated to your
- production servers.</para>
+ <para>If BRMS is in use, the url feature can be used. In the case that the packages need to be manually migrated to productions servers,
+ "file" or "dir" can be used.</para>
</section>
<section>
<title>Deployment using drl source</title>
<para>In some cases people may wish to deploy drl source. In that case all
- the drools-compiler dependencies will need to be on the classpath for your
- application. You can then load drl from file, classpath, or a database
- (for example) and compile as needed. The trick, as always, is knowing when
- rules change (this is also called "in process" deployment as described
- below).</para>
+ the drools-compiler dependencies will need to be on the classpath for the
+ application. Drl can then be loaded from a file, classpath, or a database and compile as needed. Knowing when
+ rules change is the key.</para>
</section>
<section>
<title>Deploying rules in your classpath</title>
- <para>If you have rules which do not change separate to your application,
- you can put packaged into your classpath. This can be done either as
- source (in which case the drl can be compiled, and the rulebase cached the
- first time it is needed) or else you can pre-compile packages, and just
+ <para>If the created rules do not change separate to your application,
+ the package can be placed into the classpath. This can be done either as
+ source (in which case the drl can be compiled, and the rulebase will be cached the
+ first time it is needed) or else the packages can be pre-compiled, and just
include the binary packages in the classpath.</para>
- <para>Keep in mind with this approach to make a rule change, you will both
- need to deploy your app (and if its a server - restart the
- application).</para>
+<note>
+ <para>With this approach to rule changes, the application will need to be deployed (and if it is a server, the application will need to be restarted).</para>
+</note>
</section>
<section>
Modified: labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en/Chapter-Rule_Engine/Section-The_Drools_Rule_Engine.xml
===================================================================
--- labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en/Chapter-Rule_Engine/Section-The_Drools_Rule_Engine.xml 2008-03-10 01:51:00 UTC (rev 18785)
+++ labs/jbossrules/branches/irooskov_docs/drools-docs/drools-docs-userguide/en/Chapter-Rule_Engine/Section-The_Drools_Rule_Engine.xml 2008-03-10 06:13:40 UTC (rev 18786)
@@ -10,13 +10,13 @@
<para>Drools is split into two main parts: Authoring and Runtime.</para>
<para>The authoring process involves the creation of DRL or XML files for
- rules which are fed into a parser - defined by an Antlr 3 grammar. The
+ rules which are fed into a parser - defined by an ANTLR (ANother Tool for Language Recognition) version 3 grammar. The
parser checks for correctly formed grammar and produces an intermediate
- structure for the "descr"; where the "descr" indicates the AST that
+ structure for the "descr" (description); where the "descr" indicates the AST that
"describes" the rules. The AST is then passed to the Package Builder which
produces Packages. Package Builder also undertakes any code generation and
compilation that is necessary for the creation of the Package. A Package
- object is self contained and deployable, in that it's a serialized object
+ object is self contained and deployable, in that it is a serialized object
consisting of one or more rules.</para>
<figure>
@@ -31,7 +31,7 @@
<para>A RuleBase is a runtime component which consists of one or more
Packages. Packages can be added and removed from the RuleBase at any time.
- A RuleBase can instantiate one or more WorkingMemories at any time; a weak
+ A RuleBase can create an instance of one or more WorkingMemories at any time; a weak
reference is maintained, unless configured otherwise. The Working Memory
consists of a number of sub components, including Working Memory Event
Support, Truth Maintenance System, Agenda and Agenda Event Support. Object
@@ -64,30 +64,29 @@
</figure>
<para>Four classes are used for authoring: DrlParser, XmlParser,
- ProcessBuilder and PackageBuilder. The two parser classes produce "descr"
- (description) AST models from a provided Reader instance. ProcessBuilder
+ ProcessBuilder and PackageBuilder. The two parser classes produce "descr" AST (Abstract Syntax Tree) models from a provided Reader instance. The ProcessBuilder
reads in an xstream serialization representation of the Rule Flow.
- PackageBuilder provides convienience APIs so that you can mostly forget
+ PackageBuilder provides convienience APIs (Application Programming Interface) so that you can mostly forget
about those classes. The three convenience methods are
"addPackageFromDrl", "addPackageFromXml" and addRuleFlow - all take an
instance of Reader as an argument. The example below shows how to build a
package that includes both XML and DRL rule files and a ruleflow file,
which are in the classpath. Note that all added package sources must be of
- the same package namespace for the current PackageBuilder instance!</para>
+ the same package namespace for the current PackageBuilder instance.</para>
<example>
<title>Building a Package from Multiple Sources</title>
- <programlisting>PackageBuilder builder = new PackageBuilder();
+ <screen>PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "package1.drl" ) ) );
builder.addPackageFromXml( new InputStreamReader( getClass().getResourceAsStream( "package2.xml" ) ) );
builder.addRuleFlow( new InputStreamReader( getClass().getResourceAsStream( "ruleflow.rfm" ) ) );
-Package pkg = builder.getPackage(); </programlisting>
+Package pkg = builder.getPackage(); </screen>
</example>
<para>It is essential that you always check your PackageBuilder for errors
before attempting to use it. While the ruleBase does throw an
- InvalidRulePackage when a broken Package is added, the detailed error
+ InvalidRulePackage exception when a broken Package is added, the detailed error
information is stripped and only a toString() equivalent is available. If
you interrogate the PackageBuilder itself much more information is
available.</para>
@@ -95,12 +94,12 @@
<example>
<title>Checking the PackageBuilder for errors</title>
- <programlisting>PackageBuilder builder = new PackageBuilder();
+ <screen>PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "package1.drl" ) ) );
-PackageBuilderErrors errors = builder.getErrors();</programlisting>
+PackageBuilderErrors errors = builder.getErrors();</screen>
</example>
- <para>PackageBuilder is configurable using PackageBuilderConfiguration
+ <para>The PackageBuilder is configurable using the PackageBuilderConfiguration
class.</para>
<figure>
@@ -120,9 +119,9 @@
settings is the ChainedProperties class which searches a number of
locations looking for drools.packagebuilder.conf files; as it finds them
it adds the properties to the master propperties list; this provides a
- level precedence. In order of precedence those locations are: System
- Properties, user defined file in System Properties, user home directory,
- working directory, various META-INF locations. Further to this the
+ level precedence. In order of precedence, those locations are: System
+ Properties, a user defined file in System Properties, the user home directory,
+ working directory and various META-INF locations. Further to this the
drools-compiler jar has the default settings in its META-INF
directory.</para>
@@ -130,7 +129,7 @@
Accumulate functions, registry of Dialects and the main
ClassLoader.</para>
- <para>Drools has a pluggable Dialect system, which allows other languages
+ <para>Drools has a pluggable dialect system, which allows other languages
to compile and execute expressions and blocks, the two currently
supported dialects are Java and MVEL. Each has its own
DialectConfiguration Implementation; the javadocs provide details for each
@@ -148,7 +147,7 @@
</figure>
<para>The JavaDialectConfiguration allows the compiler and language levels
- to be supported. You can override this by setting the
+ to be supported. This can be overridden by setting the
"drools.dialect.java.compiler" property in a packagebuilder.conf file that
the ChainedProperties instance will find, or you can do it at runtime as
shown below.</para>
@@ -157,31 +156,30 @@
<title>Configuring the JavaDialectConfiguration to use JANINO via a
setter</title>
- <programlisting>PackageBuilderConfiguration cfg = new PackageBuilderConfiguration( );
+ <screen>PackageBuilderConfiguration cfg = new PackageBuilderConfiguration( );
JavaDialectConfiguration javaConf = (JavaDialectConfiguration) cfg.getDialectConfiguration( "java" );
-javaConf.setCompiler( JavaDialectConfiguration.JANINO ); </programlisting>
+javaConf.setCompiler( JavaDialectConfiguration.JANINO ); </screen>
</example>
- <para>If you do not have Eclipse JDT Core in your classpath you must
- override the compiler setting before you instantiate this PackageBuilder,
- you can either do that with a packagebuilder properties file that the
- ChainedProperties class will find, or you can do it programmatically as
- shown below; note this time I use properties to inject the value for
+ <para>If the Eclipse JDT Core is not in the classpath the compiler settings must be
+ overridden before the PackageBuilder is instantiated. This can be achieved with a packagebuilder properties file that the
+ ChainedProperties class will find, or it can be programmed as
+ shown below. In this instance properties are used to inject the value for
startup.</para>
<example>
<title>Configuring the JavaDialectConfiguration to use JANINO</title>
- <programlisting>Properties properties = new Properties();
+ <screen>Properties properties = new Properties();
properties.setProperty( "drools.dialect.java.compiler",
"JANINO" );
PackageBuilderConfiguration cfg = new PackageBuilderConfiguration( properties );
JavaDialectConfiguration javaConf = (JavaDialectConfiguration) cfg.getDialectConfiguration( "java" );
assertEquals( JavaDialectConfiguration.JANINO,
- javaConf.getCompiler() ); // demonstrate that the compiler is correctly configured </programlisting>
+ javaConf.getCompiler() ); // demonstrate that the compiler is correctly configured </screen>
</example>
- <para>Currently it allows alternative compilers (Janino, Eclipse JDT) to
+ <para>Currently Eclipse allows alternative compilers (Janino, Eclipse JDT) to
be specified, different JDK source levels ("1.4" and "1.5") and a parent
class loader. The default compiler is Eclipse JDT Core at source level
"1.4" with the parent class loader set to
@@ -194,9 +192,9 @@
<title>Configuring the PackageBuilder to use JANINO via a
property</title>
- <programlisting>PackageBuilderConfiguration conf = new PackageBuilderConfiguration();
+ <screen>PackageBuilderConfiguration conf = new PackageBuilderConfiguration();
conf.setCompiler( PackageBuilderConfiguration.JANINO );
-PackageBuilder builder = new PackageBuilder( conf );</programlisting>
+PackageBuilder builder = new PackageBuilder( conf );</screen>
</example>
<para>The MVELDialectConfiguration is much simpler and only allows strict
@@ -229,16 +227,16 @@
</mediaobject>
</figure>
- <para>A RuleBase is instantiated using the RuleBaseFactory, by default
- this returns a ReteOO RuleBase. Packages are added, in turn, using the
- addPackage method. You may specify packages of any namespace and multiple
+ <para>A RuleBase is bound using the RuleBaseFactory, by default
+ this returns a ReteOO (Rete Object Orientated) RuleBase. Packages are added, in turn, using the
+ addPackage method. Packages of any namespace may be specified and multiple
packages of the same namespace may be added.</para>
<example>
<title>Adding a Package to a new RuleBase</title>
- <programlisting>RuleBase ruleBase = RuleBaseFactory.newRuleBase();
-ruleBase.addPackage( pkg ); </programlisting>
+ <screen>RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+ruleBase.addPackage( pkg ); </screen>
</example>
<figure>
@@ -255,48 +253,52 @@
used, i.e., they have been validated/compiled etc. A Rule Base is
serializable so it can be deployed to JNDI or other such services.
Typically, a rulebase would be generated and cached on first use; to save
- on the continually re-generation of the Rule Base; which is
- expensive when talking about time.</para>
+ on continually re-generating the Rule Base; which is
+ expensive in terms of time.</para>
<para>A Rule Base instance is thread safe, in the sense that you can have
the one instance shared across threads in your application, which may be a
- web application, for instance. The most common operation on a rulebase is
+ web application, as an example. The most common operation on a rulebase is
to create a new rule session; either stateful or stateless.</para>
<para>The Rule Base also holds references to any stateful session that it
has spawned, so that if rules are changing (or being added/removed etc.
for long running sessions), they can be updated with the latest rules
- (without necessarily having to restart the session). You can specify not
- to maintain a reference, but only do so if you know the Rule Base will not
- be updated. References are not stored for stateless sessions.</para>
+ (without necessarily having to restart the session). If the Rule Base is not to be updated, then it can be specified that a reference should not be maintained. References are not stored for stateless sessions.</para>
- <programlisting>ruleBase.newStatefulSession(); // maintains a reference.
-ruleBase.newStatefulSession( false ); // do not maintain a reference </programlisting>
+<caution>
+ <para>
+ If a reference for a statefuls ession is not maintained then this Rule Base cannot be updated in the future.
+ </para>
+</caution>
+ <screen>ruleBase.newStatefulSession(); // maintains a reference.
+ruleBase.newStatefulSession( false ); // do not maintain a reference </screen>
+
<para>Packages can be added and removed at any time - all changes will be
- propagated to the existing stateful sessions; don't forget to call
- fireAllRules() for resulting Activations to fire.</para>
+ propagated to the existing stateful sessions. Be sure to call
+ fireAllRules() in order for resulting Activations to fire.</para>
- <programlisting>ruleBase.addPackage( pkg ); // Add a package instance
+ <screen>ruleBase.addPackage( pkg ); // Add a package instance
ruleBase.removePackage( "org.com.sample" ); // remove a package, and all its parts, by it's namespace
-ruleBase.removeRule( "org.com.sample", "my rule" ); // remove a specific rule from a namespace </programlisting>
+ruleBase.removeRule( "org.com.sample", "my rule" ); // remove a specific rule from a namespace </screen>
<para>While there is a method to remove an indivual rule, there is no
- method to add an individual rule - to achieve this just add a new package
+ method to add an individual rule - to achieve this, add a new package
with a single rule in it.</para>
- <para>RuleBaseConfigurator can be used to specify additional behavior of
- the RuleBase. RuleBaseConfiguration is set to immutable after it has been
+ <para>The RuleBaseConfigurator can be used to specify additional behavior of
+ the RuleBase. RuleBaseConfiguration is set to immutable, meaning it cannot be changed, after it has been
added to a Rule Base. Nearly all the engine optimizations can be turned on
and off from here, and also the execution behavior can be set. Users will
generally be concerned with insertion behavior (identity or equality) and
cross product behavior(remove or keep identity equals cross
products).</para>
- <programlisting>RuleBaseConfiguration conf = new RuleBaseConfiguration();
+ <screen>RuleBaseConfiguration conf = new RuleBaseConfiguration();
conf.setAssertBehaviour( AssertBehaviour.IDENTITY );
conf.setRemoveIdentities( true );
-RuleBase ruleBase = RuleBaseFactory.newRuleBase( conf );</programlisting>
+RuleBase ruleBase = RuleBaseFactory.newRuleBase( conf );</screen>
<figure>
<title>RuleBaseConfiguration</title>
@@ -324,19 +326,18 @@
</figure>
<para>Working Memory holds references to all data that has been "inserted" into it
- (until retracted) and it is the place where the interaction with your
- application occurs. Working memories are stateful objects that may be
+ (until retracted) and it is the place where the interaction with the
+ application occurs. Working Memories are stateful objects that may be
shortlived or longlived.</para>
<section>
<title>Facts</title>
- <para>Facts are objects (beans) from your application that you insert
- into the working memory. Facts are any Java objects which the rules can
- access. The rule engine does not "clone" facts at all, it is all
- references/pointers at the end of the day. Facts are your applications
- data. Strings and other classes without getters and setters are not
- valid Facts, and can't be used with Field Constraints which rely on the
+ <para>Facts are objects (beans) of data from your application that you insert
+ into the Working Memory. Facts are any Java objects which the rules can
+ access. The rule engine does not clone facts, instead it impliments
+ references/pointers to the facts. Strings and other classes without getters and setters are not
+ valid Facts, and cannot be used with Field Constraints which rely on the
JavaBean standard of getters and setters to interact with the
object.</para>
</section>
@@ -344,17 +345,18 @@
<section>
<title>Insertion</title>
- <para>"Insert" is the act of telling the WorkingMemory about the facts.
- WorkingMemory.insert(yourObject) for example. When you insert a fact, it
- is examined for matches against the rules etc. This means ALL of the
+ <para>"Insert" is the act of telling the WorkingMemory about the facts. An example of this would be,
+ <command>WorkingMemory.insert(yourObject)</command>. When a fact is inserted, it
+ is examined for matches against the rules and further information in the WorkingMemory. This means ALL of the
work is done during insertion; however, no rules are executed until you
- call "fireAllRules()". You don't call "fireAllRules()" until after you
- have finished inserting your facts. This is a common misunderstanding by
- people who think the work happens when you call "fireAllRules()". Expert
+ call <command>fireAllRules()</command>. <command>fireAllRules()</command> should not be fired until after all facts have finished being inserted.
+ </para>
+ <para>
+ A common misunderstanding by
+ some is that the testing and insertion occurs when <command>fireAllRules()</command> is fired. Expert
systems typically use the term "assert" or "assertion" to refer to facts
made available to the system, however due to assert becoming a keyword
- in most languages we use the "Insert" keyword; so expect
- to hear the two used interchangeably.</para>
+ in most languages the word "Insert" is used as the keyword. The two will be used interchangeably throughout this user gudie.</para>
<!-- FIXME - I think we might want to add this sentence to the previous paragraph.
However, when the rules are executed, they can assert new objects
@@ -362,15 +364,15 @@
-->
<para>When an Object is inserted it returns a FactHandle. This FactHandle
- is the token used to represent your insert Object inside the
- WorkingMemory, it is also how you will interact with the Working Memory
- when you wish to retract or modify an object.</para>
+ is the token used to represent the insert Object inside the
+ WorkingMemory, it is also how interaction with the Working Memory
+ will be undertaken when an object needs to be retracted or modified.</para>
- <programlisting>Cheese stilton = new Cheese("stilton");
-FactHandle stiltonHandle = session.insert( stilton ); </programlisting>
+ <screen>Cheese stilton = new Cheese("stilton");
+FactHandle stiltonHandle = session.insert( stilton ); </screen>
- <para>As mentioned in the Rule Base section, Working Memory may operate
- in two assertions modes equality and identity - identity is
+ <para>Working Memory may operate
+ in two assertions modes, equality and identity - identity is the
default.</para>
<para>Identity means the Working Memory uses an IdentityHashMap to store
@@ -389,16 +391,21 @@
<para>"Retraction" is when you retract a fact from the Working Memory,
which means it will no longer track and match that fact, and any rules
- that are activated and dependent on that fact will be cancelled. Note
- that it is possible to have rules that depend on the "non existence" of
+ that are activated and dependent on that fact will be cancelled. </para>
+
+<note>
+ <para>
+ It is possible to have rules that depend on the "non existence" of
a fact, in which case retracting a fact may cause a rule to activate
(see the 'not' and 'exist' keywords). Retraction is done using the
- FactHandle that was returned during the assert.</para>
+ FactHandle that was returned during the assert.
+ </para>
+</note>
- <programlisting>Cheese stilton = new Cheese("stilton");
+ <screen>Cheese stilton = new Cheese("stilton");
FactHandle stiltonHandle = session.insert( stilton );
....
-session.retract( stiltonHandle ); </programlisting>
+session.retract( stiltonHandle ); </screen>
</section>
<section>
@@ -407,19 +414,24 @@
<para>The Rule Engine must be notified of modified Facts, so that it can re-process. Modification internally is actually a retract and then an
insert; so it clears the WorkingMemory and then starts again. Use the
modifyObject method to notify the Working Memory of changed objects, for
- objects that are not able to notify the Working Memory themselves.
- Notice modifyObject always takes the modified object as a second
- parameter - this allows you to specify new instances for immutable
- objects. The update() method can only be used with objects that have
+ objects that are not able to notify the Working Memory themselves. The update() method can only be used with objects that have
shadow proxies turned on. If you do not use shadow proxies then you must
call session.modifyRetract() before making your changes and
session.modifyInsert() after the changes.</para>
- <programlisting>Cheese stilton = new Cheese("stilton");
+<note>
+ <para>
+ modifyObject always takes the modified object as a second
+ parameter, allowing the specification of new instances for immutable
+ objects.
+ </para>
+</note>
+
+ <screen>Cheese stilton = new Cheese("stilton");
FactHandle stiltonHandle = workingMemory.insert( stilton );
....
stilton.setPrice( 100 );
-workingMemory.update( stiltonHandle, stilton ); </programlisting>
+workingMemory.update( stiltonHandle, stilton ); </screen>
</section>
<section>
@@ -427,43 +439,51 @@
<para>Globals are named objects that can be passed in to the rule
engine; without needing to insert them. Most often these are used for
- static information, or services that are used in the RHS of a rule, or
+ static information, or services that are used in the RHS (Right Hand Side) of a rule, or
perhaps a means to return objects from the rule engine. If you use a
- global on the LHS of a rule, make sure it is immutable. A global must
+ global on the LHS (Left Hand Side) of a rule, make sure it is immutable. A global must
first be declared in the drl before it can be set on the session.</para>
- <programlisting>global java.util.List list </programlisting>
+ <screen>global java.util.List list</screen>
- <para>With the Rule Base now aware of the global identifier and its type
- any sessions are now able to call session.setGlobal; failure to declare
+ <para>With the Rule Base now aware of the global identifier and its type,
+ any sessions are now able to call session.setGlobal.</para>
+<warning>
+ <para>
+ Failure to declare
the global type and identifier first will result in an exception being
thrown. To set the global on the session use
- session.setGlobal(identifier, value);</para>
+ <command>session.setGlobal(identifier, value); </command></para>
+</warning>
- <programlisting>List list = new ArrayList();
-session.setGlobal("list", list); </programlisting>
+ <screen>List list = new ArrayList();
+session.setGlobal("list", list); </screen>
+<warning>
<para>If a rule evaluates on a global before you set it you will get a
NullPointerException.</para>
+</warning>
</section>
<section>
<title>Shadow Facts</title>
<para>A shadow fact is a shallow copy of an asserted object. Shadow
- facts are cached copies of objects asserted to the working memory. The
+ facts are cached copies of objects asserted to the Working Memory. The
term shadow facts is commonly known as a feature of JESS (Java Expert
System Shell).</para>
<para>The origins of shadow facts traces back to the concept of truth
maintenance. The basic idea is that an expert system should guarantee
- the derived conclusions are accurate. A running system may alter a fact
- during evaluation. When this occurs, the rule engine must know a
+ the derived conclusions are accurate. When a running system alters a fact
+ during evaluation, the rule engine must know a
modification occurred and handle the change appropriately. There's
generally two ways to guarantee truthfulness. The first is to lock all
the facts during the inference process. The second is to make a cache
copy of an object and force all modifications to go through the rule
- engine. This way, the changes are processed in an orderly fashion.
+ engine. This way, the changes are processed in an orderly fashion.</para>
+
+ <para>
Shadow facts are particularly important in multi-threaded environments,
where an engine is shared by multiple sessions. Without truth
maintenance, a system has a difficult time proving the results are
@@ -479,39 +499,43 @@
visible from external code, not even inside code blocks on rules.</para>
<para>Although shadow facts are a great way of ensuring the engine
- integrity, they add some overhead to the the reasoning process. As so,
- Drools 4.0 supports fine grained control over them with the ability to
+ integrity, they add some overhead to the the reasoning process. To compensate this,
+ Drools 4.0 supports fine grained control over shadow facts, with the ability to
enable/disable them for each individual class. To disable shadow facts
for all classes, set the following property in a configuration file or
system property:</para>
- <programlisting>drools.shadowProxy = false</programlisting>
+ <screen>drools.shadowProxy = false</screen>
<para>Alternatively, it is possible to disable them through an API
call:</para>
- <programlisting>RuleBaseConfiguration conf = new RuleBaseConfiguration();
+ <screen>RuleBaseConfiguration conf = new RuleBaseConfiguration();
conf.setShadowProxy( false );
...
RuleBase ruleBase = RuleBaseFactory.newRuleBase( conf );
-</programlisting>
+</screen>
<para>To disable the shadow proxy for a list of classes only, use the
following property instead:</para>
- <programlisting>drools.shadowproxy.exclude = org.domainy.* org.domainx.ClassZ</programlisting>
+ <screen>drools.shadowproxy.exclude = org.domainy.* org.domainx.ClassZ</screen>
<para>As shown above, a space separated list is used to specify more
than one class, and '*' is used as a wild card.</para>
- <important>Disabling shadow facts for a class inhibits the
+ <important>
+ <para>
+ Disabling shadow facts for a class inhibits the
ability of the engine to keep track of changes to that classes attributes. It
means, once asserted, a fact of that class MUST NOT change any of its
attributes or the engine may start to present unpredictable behavior. It
does not help to use update(). The only way to safely change an
attribute of a fact whose shadow fact is disabled is to call
- modifyRetract() before changing the attribute, change the attribute and
- call modifyAssert().</important>
+ modifyRetract() before changing the attribute. After the change
+ call modifyAssert().
+ </para>
+ </important>
</section>
<section>
@@ -520,19 +544,19 @@
<para>If your fact objects are Java Beans, you can implement a property
change listener for them, and then tell the rule engine about it. This
means that the engine will automatically know when a fact has changed,
- and behave accordingly (you don't need to tell it that it is modified).
+ and behave accordingly (it does not need to be notified that the fact has been modified).
There are proxy libraries that can help automate this (a future version
- of drools will bundle some to make it easier). To use the Object in
- dynamic mode specify true for the second assertObject parameter.</para>
+ of drools will come with some libraries bundled to assist with this). To use the Object in
+ dynamic mode, specify true for the second assertObject parameter.</para>
- <programlisting>Cheese stilton = new Cheese("stilton");
-FactHandle stiltonHandle = workingMemory.insert( stilton, true ); //specifies that this is a dynamic fact </programlisting>
+ <screen>Cheese stilton = new Cheese("stilton");
+FactHandle stiltonHandle = workingMemory.insert( stilton, true ); //specifies that this is a dynamic fact</screen>
<para>To make a JavaBean dynamic, add a PropertyChangeSupport field
memory along with two add/remove methods and make sure that each setter
notifies the PropertyChangeSupport instance of the change.</para>
- <programlisting>private final PropertyChangeSupport changes = new PropertyChangeSupport( this );
+ <screen>private final PropertyChangeSupport changes = new PropertyChangeSupport( this );
...
public void addPropertyChangeListener(final PropertyChangeListener l) {
this.changes.addPropertyChangeListener( l );
@@ -549,7 +573,7 @@
this.changes.firePropertyChange( "state",
oldState,
newState );
-} </programlisting>
+} </screen>
</section>
<section>
@@ -560,12 +584,12 @@
the "Initial Fact". This fact is a special fact that is not intended to
be seen by the user.</para>
- <para>On the first working memory action (assert, fireAllRules) on a
+ <para>On the first working memory action (<command>assert</command>, <command>fireAllRules</command>) on a
fresh working memory, the Initial Fact will be propagated through the
RETE network. This allows rules that have no LHS, or perhaps do not use
- normal facts (such as rules that use "from" to pull data from an
+ normal facts (such as rules that use <command>from</command> to pull data from an
external source). For instance, if a new working memory is created, and
- no facts are asserted, calling the fireAllRules will cause the Initial
+ no facts are asserted, calling the <command>fireAllRules</command> will cause the Initial
Fact to propagate, possibly activating rules (otherwise, nothing would
happen as there are no other facts to start with).</para>
</section>
@@ -585,15 +609,15 @@
</figure>
<para>The StatefulSession extends the WorkingMemory class. It simply adds
- async methods and a dispose() method. The ruleBase retains a reference to
+ async methods (methods that work independantly of the main flow) and a <methodname>dispose()</methodname> method. The ruleBase retains a reference to
each StatefulSession it creates, so that it can update them when new rules
- are added, dispose() is needed to release the StatefulSession reference
- from the RuleBase, without it you can get memory leaks.</para>
+ are added. <methodname>dispose()</methodname> is needed to release the StatefulSession reference
+ from the RuleBase, without it memory leaks may occur.</para>
<example>
<title>Createing a StatefulSession</title>
- <programlisting>StatefulSession session = ruleBase.newStatefulSession();</programlisting>
+ <screen>StatefulSession session = ruleBase.newStatefulSession();</screen>
</example>
</section>
@@ -618,24 +642,24 @@
<example>
<title>Createing a StatelessSession</title>
- <programlisting>StatelessSession session = ruleBase.newStatelessSession();
-session.execute( new Cheese( "cheddar" ) );</programlisting>
+ <screen>StatelessSession session = ruleBase.newStatelessSession();
+session.execute( new Cheese( "cheddar" ) );</screen>
</example>
<para>The API is reduced for the problem domain and is thus much simpler;
which in turn can make maintenance of those services easier. The RuleBase
- never retains a reference to the StatelessSession, thus dispose() is not
- needed, and they only have an execute() method that takes an object, an
- array of objects or a collection of objects - there is no insert or
- fireAllRules. The execute method iterates the objects inserting each and
- calling fireAllRules() at the end; session finished. Should the session
- need access to any results information they can use the executeWithResults
+ never retains a reference to the StatelessSession, thus <methodname>dispose()</methodname> is not
+ needed, and they only have an <methodname>execute()</methodname> method that takes an object, an
+ array of objects or a collection of objects - there is no <methodname>insert</methodname> or
+ <methodname>fireAllRules</methodname>. The <methodname>execute()</methodname> method iterates the objects inserting each and
+ calling <methodname>fireAllRules()</methodname> at the end; session finished. Should the session
+ need access to any results information they can use the <methodname>executeWithResults()</methodname>
method, which returns a StatelessSessionResult. The reason for this is in
remote situations you do not always want the return payload, so this way
its optional.</para>
- <para>setAgendaFilter, setGlobal and setGlobalResolver share their state
- across sessions; so each call to execute() will use the set AgendaFilter,
+<para><methodname>setAgendaFilter</methodname>, <methodname>setGlobal</methodname> and <methodname>setGlobalResolver</methodname> share their state
+ across sessions; so each call to <methodname>execute()</methodname> will use the set <methodname>AgendaFilter</methodname>,
or see any previous set globals etc.</para>
<para>StatelessSessions do not currently support
@@ -661,32 +685,32 @@
</mediaobject>
</figure>
- <para>StatelessSession.executeWithResults(....) returns a minimal api to
+ <para><methodname>StatelessSession.executeWithResults(....)</methodname> returns a minimal API to
examine the sessions data. The inserted Objects can be iterated over,
queries can be executed and globals retrieved. Once the
StatelessSessionResult is serialized it loses the reference to the
underlying WorkingMemory and RuleBase, so queries can no longer be
executed, however globals can still be retrieved and objects iterated. To
retrieve globals they must be exported from the StatelessSession; the
- GlobalExporter strategy is set with StatelessSession.setGlobalExporter(
- GlobalExporter globalExporter ). Two implementations of GlobalExporter are
+ GlobalExporter strategy is set with <methodname>StatelessSession.setGlobalExporter(
+ GlobalExporter globalExporter )</methodname>. Two implementations of GlobalExporter are
available and users may implement their own strategies.
CopyIdentifiersGlobalExporter copies named identifiers into a new
GlobalResovler that is passed to the StatelessSessionResult; the
constructor takes a String[] array of identifiers, if no identifiers are
specified it copies all identifiers declared in the RuleBase.
- ReferenceOriginalGlobalExporter just passes a reference to the original
- Global Resolver; the latter should be used with care as identifier
+ <methodname>ReferenceOriginalGlobalExporter</methodname> passes a reference to the original
+ GlobalResolver; the latter should be used with care as identifier
instances can be changed at any time by the StatelessSession and the
GlobalResolver may not be serializable freindly.</para>
<example>
<title>GlobalExporter with StatelessSessions</title>
- <programlisting>StatelessSession session = ruleBase.newStatelessSession();
+ <screen>StatelessSession session = ruleBase.newStatelessSession();
session.setGlobalExporter( new CopyIdentifiersGlobalExporter( new String[]{"list"} ) );
StatelessSessionResult result = session.executeWithResults( new Cheese( "stilton" ) );
-List list = ( List ) result.getGlobal( "list" );</programlisting>
+List list = ( List ) result.getGlobal( "list" );</screen>
</example>
</section>
@@ -717,13 +741,13 @@
<para>Working Memory Actions - this is where most of the work takes
place - in either the Consequence or the main java application
process. Once the Consequence has finished or the main Java
- application process calls fireAllRules() the engine switches to the
+ application process calls <methodname>fireAllRules()</methodname> the engine switches to the
Agenda Evaluation phase.</para>
</listitem>
<listitem>
- <para>Agenda Evaluation - attempts to select a rule to fire, if a rule
- is not found it exits, otherwise it attempts to fire the found rule,
+ <para>Agenda Evaluation - attempts to select a rule to fire if a rule
+ is not found that exists, otherwise it attempts to fire the found rule,
switching the phase back to Working Memory Actions and the process
repeats again until the Agenda is empty.</para>
</listitem>
@@ -753,7 +777,7 @@
agenda).</para>
<para>The default conflict resolution strategies employed by Drools are:
- Salience and LIFO (last in, first out).</para>
+ Salience and LIFO (Last In, First Out).</para>
<para>The most visible one is "salience" or priority, in which case a
user can specify that a certain rule has a higher priority (by giving it
@@ -763,13 +787,15 @@
same action have the same value - execution of these are considered
arbitrary.</para>
+<note>
<para>As a general rule, it is a good idea not to count on the rules
- firing in any particular order, and try and author the rules without
+ firing in any particular order. Instead try and author the rules without
worrying about a "flow".</para>
+</note>
<para>Custom conflict resolution strategies can be specified by setting
- the Class in the RuleBaseConfiguration method setConflictResolver, or
- using the property "drools.conflictResolver".</para>
+ the Class in the <methodname>RuleBaseConfiguration</methodname> method <methodname>setConflictResolver</methodname>, or
+ using the property <property>drools.conflictResolver</property>.</para>
</section>
<section>
@@ -777,22 +803,21 @@
<para>Agenda groups are a way to partition rules (activations)
on the agenda. At any one time, only one group has "focus" which means
- that the activations for rules in that group will only take effect - you
- can also have rules "auto focus" which means the focus for its agenda
+ that the activations for rules in that group will only take effect. Rules can also "auto focus", meaning the focus for its agenda
group is taken when the conditions for the rule are true.</para>
- <para>They are sometimes known as "modules" in CLIPS terminology. Agenda
+ <para>Sometimes known as "modules" in CLIPS terminology, agenda
groups are a handy way to create a "flow" between grouped rules. You can
switch the group which has focus either from within the rule engine, or
from the API. If your rules have a clear need for multiple "phases" or
"sequences" of processing, consider using agenda-groups for this
purpose.</para>
- <para>Each time setFocus(...) is called it pushes that Agenda Group onto
- a stack, when the focus group is empty it is popped off and the next one
- on the stack is evaluated. An Agenda Group can appear in multiple locations
- on the stack. The default Agenda Group is "MAIN", all rules which do not
- specify an Agenda Group are placed there, it is also always the first
+ <para>Each time <methodname>setFocus(...)</methodname> is called it pushes that agenda group onto
+ a stack. When the focus group is empty it is popped off and the next one
+ on the stack is evaluated. An agenda group can appear in multiple locations
+ on the stack. The default agenda group is "MAIN", all rules which do not
+ specify an agenda group are placed there. It is also always the first
group on the Stack and given focus as default.</para>
</section>
@@ -810,7 +835,7 @@
</figure>
<para>Filters are optional implementations of the filter interface
- which are used to allow/or deny an activation from firing (what you
+ which are used to allow or deny an activation from firing (what you
filter on, is entirely up to the implementation). Drools provides the
following convenience default implementations</para>
@@ -832,11 +857,11 @@
</listitem>
</itemizedlist>
- <para>To use a filter specify it while calling FireAllRules. The
+ <para>To use a filter specify it while calling <methodname>FireAllRules</methodname>. The
following example will filter out all rules ending with the text
"Test":</para>
- <programlisting>workingMemory.fireAllRules( new RuleNameEndsWithAgendaFilter( "Test" ) ); </programlisting>
+ <screen>workingMemory.fireAllRules( new RuleNameEndsWithAgendaFilter( "Test" ) ); </screen>
</section>
</section>
@@ -848,31 +873,29 @@
<para>In a regular insert, you need to explicitly retract a fact. With
logical assertions, the fact that was asserted will be automatically
retracted when the conditions that asserted it in the first place are no
- longer true. (It's actually more clever then that! If there are no possible
+ longer true. Further to that, if there are no possible
conditions that could support the logical assertion, only then it will be
- retracted).</para>
+ retracted.</para>
- <para>Normal insertions are said to be “STATED” (ie The Fact has been
+ <para>Normal insertions are said to be <emphasis>STATED</emphasis> (for example, the Fact has been
stated - just like the intuitive concept). Using a HashMap and a counter
- we track how many times a particular equality is STATED; this means we
+ it is tracked how many times a particular equality is <emphasis>STATED</emphasis>; this means we
count how many different instances are equal. When we logically insert an
object we are said to justify it and it is justified by the firing rule.
For each logical insertion there can only be one equal object, each
subsequent equal logical insertion increases the justification counter for
- this logical assertion. As each justification is removed when we have no
- more justifications the logical object is automatically retracted.</para>
+ this logical assertion. As each justification is removed, when there are no justifications left, the logical object is automatically retracted.</para>
- <para>If we logically insert an object when there is an equal STATED
- object it will fail and return null. If we STATE an object that has an
- exist equal object that is JUSTIFIED we override the Fact - how this
+ <para>If we logically insert an object when there is an equal <emphasis>STATED</emphasis>
+ object it will fail and return null. If we <emphasis>STATE</emphasis> an object that has an
+ exist equal object that is <emphasis>JUSTIFIED</emphasis> we override the Fact. How this
override works depends on the configuration setting
"WM_BEHAVIOR_PRESERVE". When the property is set to discard we use the
existing handle and replace the existing instance with the new Object -
- this is the default behavior - otherwise we override it to STATED but we
+ this is the default behavior - otherwise we override it to <emphasis>STATED</emphasis>, but we
create a new FactHandle.</para>
- <para>This can be confusing on a first read, so hopefully the flow charts
- below help. When it says that it returns a new FactHandle, this also
+ <para>The flowchart below outlines this process. When it is refered that the process returns a new FactHandle, this also
indicates the Object was propagated through the network.</para>
<figure>
@@ -902,10 +925,10 @@
<para>An example may make things clearer. Imagine a credit card
processing application, processing transactions for a given account (and
- we have a working memory accumulating knowledge about a single accounts
+ there is a working memory accumulating knowledge about a single accounts
transaction). The rule engine is doing its best to decide if
- transactions are possibly fraudulent or not. Imagine this rule base
- basically has rules that kick in when there is "reason to be suspicious"
+ transactions are possibly fraudulent or not. The rule base
+ has rules that activate when there is "reason to be suspicious"
and when "everything is normal".</para>
<para>Of course there are many rules that operate no matter what
@@ -913,40 +936,46 @@
reasons as to what could trigger a "reason to be suspicious": someone
notifying the bank, a sequence of large transactions, transactions for
geographically disparate locations or even reports of credit card theft.
- Rather then smattering all the little conditions in lots of rules,
- imagine there is a fact class called "SuspiciousAccount".</para>
+ Rather then seperating all the little conditions into many rules,
+ there is a fact class called "SuspiciousAccount".</para>
<para>Then there can be a series of rules whose job is to look for
things that may raise suspicion, and if they fire, they simply insert a
new SuspiciousAccount() instance. All the other rules just have
conditions like "not SuspiciousAccount()" or "SuspiciousAccount()"
- depending on their needs. Note that this has the advantage of allowing
+ depending on their needs.</para>
+<note>
+ <para>
+ The above has the advantage of allowing
there to be many rules around raising suspicion, without touching the
- other rules. When the facts causing the SuspiciousAccount() insertion
+ other rules. </para>
+</note>
+<para>
+ When the facts causing the SuspiciousAccount() insertion
are removed, the rule engine reverts back to the normal "mode" of
operation (and for instance, a rule with "not SuspiciousAccount()" may
kick in which flushes through any interrupted transactions).</para>
- <para>If you have followed this far, you will note that truth
- maintenance, like logical assertions, allows rules to behave a little
- like a human would, and can certainly make the rules more
+<note>
+ <para>Truth
+ maintenance, like logical assertions, allows rules to behave similar to a human, and can make rules more
manageable.</para>
+</note>
</section>
<important>
<title>Important note: Equality for Java objects</title>
<para>It is important to note that for Truth Maintenance (and logical
- assertions) to work at all, your Fact objects (which may be Javabeans)
- override equals and hashCode methods (from java.lang.Object) correctly.
- As the truth maintenance system needs to know when 2 different physical
- objects are equal in value, BOTH equals and hashCode must be overridden
- correctly, as per the Java standard.</para>
+ assertions) to work, your Fact objects (which may be Javabeans) must
+ override the methods <methodname>equals</methodname> and <methodname>hashCode</methodname> (from java.lang.Object) correctly.
+ This is because the truth maintenance system needs to know when 2 different physical
+ objects are equal in value</para>
- <para>Two objects are equal if and only if their equals methods return
- true for each other and if their hashCode methods return the same
- values. See the Java API for more details (but do keep in mind you MUST
- override both equals and hashCode).</para>
+ <para>Two objects are equal if and only if their <methodname>equals</methodname> methods return
+ true for each other and if their <methodname>hashCode</methodname> methods return the same
+ values. See the Java API for more details (keeping in mind you <emphasis>MUST</emphasis>
+ override both <methodname>equals</methodname> and <methodname>hashCode</methodname>).</para>
</important>
</section>
@@ -960,8 +989,8 @@
concern.</para>
<para>There are three types of event listeners -
- WorkingMemoryEventListener, AgendaEventListener
- RuleFlowEventListener.</para>
+ <classname>WorkingMemoryEventListener</classname>, <classname>AgendaEventListener</classname>
+ <classname>RuleFlowEventListener</classname>.</para>
<figure>
<title>WorkingMemoryEventListener</title>
@@ -996,7 +1025,7 @@
</mediaobject>
</figure>
- <para>Both stateful and stateless sessions implement the EventManager
+ <para>Both stateful and stateless sessions implement the <interface>EventManager</interface>
interface, which allows event listeners to be added to the session.</para>
<figure>
@@ -1009,26 +1038,26 @@
</mediaobject>
</figure>
- <para>All EventListeners have default implementations that implement each
+ <para>All <classname>EventListeners</classname> have default implementations that implement each
method, but do nothing, these are convienience classes that you can
inherit from to save having to implement each method -
- DefaultAgendaEventListener, DefaultWorkingMemoryEventListener,
- DefaultRuleFlowEventListener. The following shows how to extend
- DefaultAgendaEventListener and add it to the session - the example prints
+ <classname>DefaultAgendaEventListener</classname>, <classname>DefaultWorkingMemoryEventListener</classname>,
+ <classname>DefaultRuleFlowEventListener</classname>. The following shows how to extend
+ <classname>DefaultAgendaEventListener</classname> and add it to the session. The example prints
statements only when rules are fired:</para>
- <programlisting>session.addEventListener( new DefaultAgendaEventListener() {
+ <screen>session.addEventListener( new DefaultAgendaEventListener() {
public void afterActivationFired(AfterActivationFiredEvent event) {
super.afterActivationFired( event );
System.out.println( event );
}
-}); </programlisting>
+}); </screen>
- <para>Drools also provides DebugWorkingMemoryEventListener,
- DebugAgendaEventListener and DebugRuleFlowEventListener that implements
+<para>Drools also provides <classname>DebugWorkingMemoryEventListener</classname>,
+ <classname>DebugAgendaEventListener</classname> and <classname>DebugRuleFlowEventListener</classname> that implements
each method with a debug print statement:</para>
- <programlisting>session.addEventListener( new DebugWorkingMemoryEventListener() ); </programlisting>
+ <screen>session.addEventListener( new DebugWorkingMemoryEventListener() );</screen>
<para>The Eclipse based Rule IDE also provides an audit logger and
graphical viewer, so that the rule engine can log events for later
@@ -1040,15 +1069,14 @@
<para>With Rete you have a stateful session where objects can be asserted
and modified over time, rules can also be added and removed. Now what
- happens if we assume a stateless session, where after the initial data set
+ happens if a stateless session is assumed, where after the initial data set
no more data can be asserted or modified (no rule re-evaluations) and
- rules cannot be added or removed? This means we can start to make
- assumptions to minimize what work the engine has to do.</para>
+ rules cannot be added or removed? This means assumptions can start to be made
+ to minimize what work the engine has to do.</para>
<orderedlist>
<listitem>
- <para>Order the Rules by salience and position in the ruleset (just
- sets a sequence attribute on the rule terminal node).</para>
+ <para>Order the Rules by salience and position in the ruleset (sets a sequence attribute on the rule terminal node).</para>
</listitem>
<listitem>
@@ -1103,18 +1131,16 @@
remembers an insertion propagation is the right-input Object memory. Once
all the assertions are finished, and all right-input memories populated,
we can then iterate the list of LeftInputAdatperNode Command objects
- calling each in turn; they will propagate down the network attempting to
- join with the right-input objects; not being remembered in the left input,
- as we know there will be no further object assertions and thus
+ calling each in turn. Propagating down the network attempting to
+ join with the right-input objects, the objects will not be remembered in the left input,
+ as it is known that there will be no further object assertions and thus
propagations into the right-input memory.</para>
<para>There is no longer an Agenda, with a priority queue to schedule
the
- Tuples, instead there is simply an array for the number of rules. The
+ Tuples, instead there is an array for the number of rules. The
sequence number of the RuleTerminalNode indicates the element with the
- array to place the Activation. Once all Command Objects have finished
-we
- can iterate our array checking each element in turn and firing the
+ array to place the Activation. Once all Command Objects have finished the array can be iterated, checking each element in turn and firing the
Activations if they exist. To improve performance in the array we
remember to
record the first and last populated cells. The network is constructed
@@ -1122,17 +1148,15 @@
salience number and its order of being added to the network.</para>
<para>Typically the right-input node memories are HashMaps, for fast
- Object retraction, as we know there will be no Object retractions, we can
- use a list when the values of the Object are not indexed. For larger
- numbers of indexed Objects, HashMaps provide a performance increase; if we
- know an Object type has a low number of instances then indexing is
+ Object retraction (sine there will be no Object retractions) a list can be used when the values of the Object are not indexed. For larger
+ numbers of indexed Objects, HashMaps provide a performance increase; if it is
+ known that an Object type has a low number of instances then indexing is
probably not of an advantage and an Object list can be used.</para>
<para>Sequential mode can only be used with a StatelessSession and is off
- by default. To turn on either set the RuleBaseConfiguration.setSequential
- to true or set the rulebase.conf property drools.sequential to true.
- Sequential mode can fallback to a dynamic agenda with setSequentialAgenda
- to either SequentialAgenda.SEQUENTIAL or SequentialAgenda.DYNAMIC setter
- or the "drools.sequential.agenda" property</para>
+ by default. To turn it on, either set the <property>RuleBaseConfiguration.setSequential</property>
+ to true or set the <classname>rulebase.conf</classname> property <property>drools.sequential</property> to true. Sequential mode can fallback to a dynamic agenda with setSequentialAgenda
+ to either <property>SequentialAgenda.SEQUENTIAL</property> or <property>SequentialAgenda.DYNAMIC</property> setter
+ or the <property>drools.sequential.agenda</property> property</para>
</section>
</section>
More information about the jboss-svn-commits
mailing list