[jboss-svn-commits] JBL Code SVN: r34399 - in labs/jbossrules/trunk/drools-docs: drools-docs-expert/src/main/docbook/en-US/Chapter-User_Guide and 2 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Fri Jul 30 01:25:59 EDT 2010
Author: mark.proctor at jboss.com
Date: 2010-07-30 01:25:59 -0400 (Fri, 30 Jul 2010)
New Revision: 34399
Modified:
labs/jbossrules/trunk/drools-docs/drools-docs-expert/src/main/docbook/en-US/Chapter-Language_Reference/Section-Rule.xml
labs/jbossrules/trunk/drools-docs/drools-docs-expert/src/main/docbook/en-US/Chapter-User_Guide/Section-Running.xml
labs/jbossrules/trunk/drools-docs/drools-docs-integration/src/main/docbook/en-US/Chapter-Server/Section-Configuration/Section-Configuration.xml
labs/jbossrules/trunk/drools-docs/drools-docs-integration/src/main/docbook/en-US/Chapter-Spring/Chapter-Spring.xml
Log:
-doc tweaking
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-expert/src/main/docbook/en-US/Chapter-Language_Reference/Section-Rule.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-expert/src/main/docbook/en-US/Chapter-Language_Reference/Section-Rule.xml 2010-07-30 04:43:05 UTC (rev 34398)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-expert/src/main/docbook/en-US/Chapter-Language_Reference/Section-Rule.xml 2010-07-30 05:25:59 UTC (rev 34399)
@@ -1,47 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<section version="5.0"
xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
- xml:base="../" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
+ xml:base="../" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
<title>Rule</title>
<figure>
<title>rule</title>
<mediaobject>
- <imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/rule.png" format="PNG" role="" />
+ <imageobject>
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/rule.png"
+ format="PNG" role=""></imagedata>
</imageobject>
</mediaobject>
</figure>
- <para>A rule specifies that <emphasis>when</emphasis> a particular set
- of conditions occur, specified in the Left Hand Side (LHS),
- <emphasis>then</emphasis> do what is specified as a list of actions in
- the Right Hand Side (RHS). A common question from users
- is "Why use when instead of if?" "When" was chosen over "if" because "if" is
- normally part of a procedural execution flow, where, at a specific point in
- time, a condition is to be checked. In contrast, "when" indicates that
- the condition evaluation is not tied to a specific evaluation sequence
- or point in time, but that it happens continually, at any time during
- the life time of the engine; whenever the condition is met, the
- actions are executed.</para>
+ <para>A rule specifies that <emphasis>when</emphasis> a particular set of
+ conditions occur, specified in the Left Hand Side (LHS),
+ <emphasis>then</emphasis> do what is specified as a list of actions in the
+ Right Hand Side (RHS). A common question from users is "Why use when instead
+ of if?" "When" was chosen over "if" because "if" is normally part of a
+ procedural execution flow, where, at a specific point in time, a condition
+ is to be checked. In contrast, "when" indicates that the condition
+ evaluation is not tied to a specific evaluation sequence or point in time,
+ but that it happens continually, at any time during the life time of the
+ engine; whenever the condition is met, the actions are executed.</para>
- <para>A rule must have a name, unique within its rule package. If
- you define a rule twice in the same DRL it produces an error while loading.
- If you add a DRL that includes a rule name already in the package, it
- replaces the previous rule. If a rule name is to have spaces, then it
- will need to be enclosd in double quotes (it is best to always use double
- quotes).</para>
+ <para>A rule must have a name, unique within its rule package. If you define
+ a rule twice in the same DRL it produces an error while loading. If you add
+ a DRL that includes a rule name already in the package, it replaces the
+ previous rule. If a rule name is to have spaces, then it will need to be
+ enclosd in double quotes (it is best to always use double quotes).</para>
- <para>Attributes - described below - are optional. They are best written
- one per line.</para>
+ <para>Attributes - described below - are optional. They are best written one
+ per line.</para>
- <para>The LHS of the rule follows the <literal>when</literal> keyword (ideally on a new
- line), similarly the RHS follows the <literal>then</literal> keyword (again, ideally on
- a newline). The rule is terminated by the keyword <literal>end</literal>. Rules cannot
- be nested.</para>
+ <para>The LHS of the rule follows the <literal>when</literal> keyword
+ (ideally on a new line), similarly the RHS follows the
+ <literal>then</literal> keyword (again, ideally on a newline). The rule is
+ terminated by the keyword <literal>end</literal>. Rules cannot be
+ nested.</para>
<example>
<title>Rule Syntax Overview</title>
@@ -85,188 +89,186 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/rule_attributes.png" format="PNG" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/rule_attributes.png"
+ format="PNG"></imagedata>
</imageobject>
</mediaobject>
</figure>
<variablelist>
<varlistentry>
- <term><literal>no-loop</literal></term>
-
- <listitem>
- <para>default value: false</para>
-
- <para>type: Boolean</para>
-
- <para>When the rule's consequence modifies a fact it may cause
- the Rule to activate again, causing recursion. Setting no-loop
- to true means the attempt to create the Activation for the
- current set of data will be ignored.</para>
- </listitem>
-
+ <term><literal>no-loop</literal></term>
+
+ <listitem>
+ <para>default value: false</para>
+
+ <para>type: Boolean</para>
+
+ <para>When the rule's consequence modifies a fact it may cause the
+ Rule to activate again, causing recursion. Setting no-loop to true
+ means the attempt to create the Activation for the current set of
+ data will be ignored.</para>
+ </listitem>
</varlistentry>
<varlistentry>
- <term><literal>ruleflow-group</literal></term>
-
- <listitem>
- <para>default value: N/A</para>
-
- <para>type: String</para>
-
- <para>Ruleflow is a Drools feature that lets you exercise
- control over the firing of rules. Rules that are assembled
- by the same ruleflow-group identifier fire only when
- their group is active.</para>
- </listitem>
+ <term><literal>ruleflow-group</literal></term>
+
+ <listitem>
+ <para>default value: N/A</para>
+
+ <para>type: String</para>
+
+ <para>Ruleflow is a Drools feature that lets you exercise control
+ over the firing of rules. Rules that are assembled by the same
+ ruleflow-group identifier fire only when their group is
+ active.</para>
+ </listitem>
</varlistentry>
-
+
<varlistentry>
- <term><literal>lock-on-active</literal></term>
-
- <listitem>
- <para>default value: false</para>
-
- <para>type: Boolean</para>
- <para>Whenever a ruleflow-group becomes active or an
- agenda-group receives the focus, any rule within that
- group that has lock-on-active set to true will not be
- activated any more; irrespective of the origin of the
- update, the activation of a matching rule is discarded.
- This is a stronger version of no-loop, because the change
- could now be caused not only by the rule itself. It's
- ideal for calculation rules where you have a number of
- rules that modify a fact and you don't want any rule
- re-matching and firing again. Only when the ruleflow-group
- is no longer active or the agenda-group loses the focus
- those rules with lock-on-active set to true become
- eligible again for their activations to be placed onto
- the agenda.</para>
- </listitem>
+ <term><literal>lock-on-active</literal></term>
+
+ <listitem>
+ <para>default value: false</para>
+
+ <para>type: Boolean</para>
+
+ <para>Whenever a ruleflow-group becomes active or an agenda-group
+ receives the focus, any rule within that group that has
+ lock-on-active set to true will not be activated any more;
+ irrespective of the origin of the update, the activation of a
+ matching rule is discarded. This is a stronger version of no-loop,
+ because the change could now be caused not only by the rule itself.
+ It's ideal for calculation rules where you have a number of rules
+ that modify a fact and you don't want any rule re-matching and
+ firing again. Only when the ruleflow-group is no longer active or
+ the agenda-group loses the focus those rules with lock-on-active set
+ to true become eligible again for their activations to be placed
+ onto the agenda.</para>
+ </listitem>
</varlistentry>
-
+
<varlistentry>
- <term><literal>salience</literal></term>
-
- <listitem>
- <para>default value : 0</para>
-
- <para>type : integer</para>
-
- <para>Each rule has a salience attribute that can be assigned
- an integer number, which defaults to zero and can be
- negative or positive. Salience is a form of priority where
- rules with higher salience values are given higher priority
- when ordered in the Activation queue.</para>
- </listitem>
+ <term><literal>salience</literal></term>
+
+ <listitem>
+ <para>default value : 0</para>
+
+ <para>type : integer</para>
+
+ <para>Each rule has a salience attribute that can be assigned an
+ integer number, which defaults to zero and can be negative or
+ positive. Salience is a form of priority where rules with higher
+ salience values are given higher priority when ordered in the
+ Activation queue.</para>
+ </listitem>
</varlistentry>
-
-
+
<varlistentry>
- <term><literal>agenda-group</literal></term>
-
- <listitem>
- <para>default value: MAIN</para>
-
- <para>type: String</para>
-
- <para>Agenda groups allow the user to partition the Agenda
- providing more execution control. Only rules in the agenda
- group that has acquired the focus are allowed to fire.</para>
- </listitem>
+ <term><literal>agenda-group</literal></term>
+
+ <listitem>
+ <para>default value: MAIN</para>
+
+ <para>type: String</para>
+
+ <para>Agenda groups allow the user to partition the Agenda providing
+ more execution control. Only rules in the agenda group that has
+ acquired the focus are allowed to fire.</para>
+ </listitem>
</varlistentry>
-
+
<varlistentry>
- <term><literal>auto-focus</literal></term>
-
- <listitem>
- <para>default value: false</para>
-
- <para>type: Boolean</para>
-
- <para>When a rule is activated where the <code>auto-focus</code>
- value is true and the rule's agenda group does
- not have focus yet, then it is given focus, allowing the rule to
- potentially fire.</para>
- </listitem>
+ <term><literal>auto-focus</literal></term>
+
+ <listitem>
+ <para>default value: false</para>
+
+ <para>type: Boolean</para>
+
+ <para>When a rule is activated where the <code>auto-focus</code>
+ value is true and the rule's agenda group does not have focus yet,
+ then it is given focus, allowing the rule to potentially
+ fire.</para>
+ </listitem>
</varlistentry>
-
+
<varlistentry>
- <term><literal>activation-group</literal></term>
-
- <listitem>
- <para>default value: N/A</para>
-
- <para>type: String</para>
-
- <para>Rules that belong to the same activation-group, identified
- by this attribute's string value, will only fire exclusively. In
- other words, the first rule in an activation-group to fire will
- cancel the other rules' activations, i.e., stop them from firing.</para>
-
- <para>Note: This used to be called Xor group, but technically it's
- not quite an Xor. You may still hear people mention Xor group;
- just swap that term in your mind with activation-group.</para>
- </listitem>
+ <term><literal>activation-group</literal></term>
+
+ <listitem>
+ <para>default value: N/A</para>
+
+ <para>type: String</para>
+
+ <para>Rules that belong to the same activation-group, identified by
+ this attribute's string value, will only fire exclusively. In other
+ words, the first rule in an activation-group to fire will cancel the
+ other rules' activations, i.e., stop them from firing.</para>
+
+ <para>Note: This used to be called Xor group, but technically it's
+ not quite an Xor. You may still hear people mention Xor group; just
+ swap that term in your mind with activation-group.</para>
+ </listitem>
</varlistentry>
-
+
<varlistentry>
- <term><literal>dialect</literal></term>
-
- <listitem>
- <para>default value: as specified by the package</para>
-
- <para>type: String</para>
-
- <para>possible values: "java" or "mvel"</para>
-
- <para>The dialect species the language to be used for any code
- expressions in the LHS or the RHS code block. Currently two
- dialects are available, Java and MVEL. While the dialect can
- be specified at the package level, this attribute allows the
- package definition to be overridden for a rule.</para>
- </listitem>
+ <term><literal>dialect</literal></term>
+
+ <listitem>
+ <para>default value: as specified by the package</para>
+
+ <para>type: String</para>
+
+ <para>possible values: "java" or "mvel"</para>
+
+ <para>The dialect species the language to be used for any code
+ expressions in the LHS or the RHS code block. Currently two dialects
+ are available, Java and MVEL. While the dialect can be specified at
+ the package level, this attribute allows the package definition to
+ be overridden for a rule.</para>
+ </listitem>
</varlistentry>
-
-
+
<varlistentry>
- <term><literal>date-effective</literal></term>
-
- <listitem>
- <para>default value: N/A</para>
-
- <para>type: String, containing a date and time definition</para>
-
- <para>A rule can only activate if the current date and time is
- after date-effective attribute.</para>
- </listitem>
+ <term><literal>date-effective</literal></term>
+
+ <listitem>
+ <para>default value: N/A</para>
+
+ <para>type: String, containing a date and time definition</para>
+
+ <para>A rule can only activate if the current date and time is after
+ date-effective attribute.</para>
+ </listitem>
</varlistentry>
-
+
<varlistentry>
- <term><literal>date-expires</literal></term>
-
- <listitem>
- <para>default value: N/A</para>
-
- <para>type: String, containing a date and time definition</para>
-
- <para>A rule cannot activate if the current date and time is
- after the date-expires attribute.</para>
- </listitem>
+ <term><literal>date-expires</literal></term>
+
+ <listitem>
+ <para>default value: N/A</para>
+
+ <para>type: String, containing a date and time definition</para>
+
+ <para>A rule cannot activate if the current date and time is after
+ the date-expires attribute.</para>
+ </listitem>
</varlistentry>
-
+
<varlistentry>
- <term><literal>duration</literal></term>
-
- <listitem>
- <para>default value: no default value</para>
-
- <para>type: long</para>
-
- <para>The duration dictates that the rule will fire after a
+ <term><literal>duration</literal></term>
+
+ <listitem>
+ <para>default value: no default value</para>
+
+ <para>type: long</para>
+
+ <para>The duration dictates that the rule will fire after a
specified duration, if it is still true.</para>
- </listitem>
+ </listitem>
</varlistentry>
</variablelist>
@@ -281,21 +283,101 @@
</example>
</section>
+ <section>
+ <title>Timers and Calendars</title>
+
+ <para>Rule's now suport both interval and cron based timers, which replace
+ the now deprecated duration attribute.</para>
+
+ <example>
+ <title>Sample timer attribute uses</title>
+
+ <programlisting language="java">timer ( int: <initial delay> <repeat interval>? )
+timer ( int: 30s )
+timer ( int: 30s 5m )
+
+timer ( cron: <cron expression> )
+timer ( cron:* 0/15 * * * ? )</programlisting>
+ </example>
+
+ <para>Interval "int:" timers follow the JDK semantics for initial delay
+ optionally followed by a repeat interval. Cron "cron:" timers follow
+ standard cron expressions:</para>
+
+ <example>
+ <title>A Cron Example</title>
+
+ <programlisting language="java">rule "Send SMS every 15 minutes"
+ timer (cron:* 0/15 * * * ?)
+when
+ $a : Alarm( on == true )
+then
+ channels[ "sms" ].insert( new Sms( $a.mobileNumber, "The alarm is still on" );
+end</programlisting>
+ </example>
+
+ <para>Calendars can now controll when rules can fire. The Calendar api is
+ modelled on <link xlink:href="http://www.quartz-scheduler.org/">Quartz
+ http://www.quartz-scheduler.org/</link> :</para>
+
+ <example>
+ <title>Adapting a Quartz Calendar</title>
+
+ <programlisting language="java">Calendar weekDayCal = QuartzHelper.quartzCalendarAdapter(org.quartz.Calendar quartzCal)</programlisting>
+ </example>
+
+ <para>Calendars are registered with the StatefulKnowledgeSession:</para>
+
+ <example>
+ <title>Registering a Calendar</title>
+
+ <programlisting language="java">ksession.getCalendars().set( "week day", weekDayCal );</programlisting>
+ </example>
+
+ <para>They can be used in conjunction with normal rules and rules
+ including timers. The rule calendar attribute can have one or more comma
+ calendar names.</para>
+
+ <example>
+ <title>Using Calendars and Timers together</title>
+
+ <programlisting language="java">rule "weekdays are high priority"
+ calendars "weekday"
+ timer (int:0 1h)
+when
+ Alarm()
+then
+ send( "priority high - we have an alarm” );
+end
+
+rule "weekend are low priority"
+ calendars "weekend"
+ timer (int:0 4h)
+when
+ Alarm()
+then
+ send( "priority low - we have an alarm” );
+end</programlisting>
+ </example>
+ </section>
+
<section id="RuleLanguage-ConditionalElements">
<title>Left Hand Side (when) Conditional Elements</title>
<para>The Left Hand Side (LHS) is a common name for the conditional part
of the rule. It consists of zero or more Conditional Elements. If the LHS
- is left empty, it is re-written as <code>eval(true)</code>, which means
- that the rule's condition is always true. It will be activated, once,
- when a new Working Memory session is created.</para>
+ is left empty, it is re-written as <code>eval(true)</code>, which means
+ that the rule's condition is always true. It will be activated, once, when
+ a new Working Memory session is created.</para>
<figure>
<title>Left Hand Side</title>
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/lhs.png" format="PNG" role="" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/lhs.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
@@ -319,13 +401,15 @@
end</programlisting>
</example>
- <para>Conditional elements work on one or more <emphasis>patterns</emphasis> (which are
- described below). The most common one is <literal>and</literal>, which is implicit when you
- have multiple patterns in the LHS of a rule that are not connected in
- any way. Note that an <literal>and</literal> cannot have a leading declaration binding like
+ <para>Conditional elements work on one or more
+ <emphasis>patterns</emphasis> (which are described below). The most common
+ one is <literal>and</literal>, which is implicit when you have multiple
+ patterns in the LHS of a rule that are not connected in any way. Note that
+ an <literal>and</literal> cannot have a leading declaration binding like
<literal>or</literal>. This is obvious, since a declaration can only
- reference a single fact, and when the <literal>and</literal> is satisfied it matches more
- than one fact - so which fact would the declaration bind to?</para>
+ reference a single fact, and when the <literal>and</literal> is satisfied
+ it matches more than one fact - so which fact would the declaration bind
+ to?</para>
<section>
<title>Pattern</title>
@@ -341,8 +425,9 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/patternER.png" format="PNG"
- role="" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/patternER.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
@@ -356,21 +441,21 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/pattern.png" format="PNG"
- role="" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/pattern.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
<para>In its simplest form, with no constraints, a pattern matches
- against a fact of the given type. In the following case the type
- is <code>Cheese</code>, which means that the pattern will match
- against all <code>Cheese</code> objects in the Working Memory.</para>
+ against a fact of the given type. In the following case the type is
+ <code>Cheese</code>, which means that the pattern will match against all
+ <code>Cheese</code> objects in the Working Memory.</para>
- <para>Notice that the type need not be the actual class of some
- fact object. Patterns may refer to superclasses or even interfaces,
- thereby potentially matching facts from many different
- classes.</para>
+ <para>Notice that the type need not be the actual class of some fact
+ object. Patterns may refer to superclasses or even interfaces, thereby
+ potentially matching facts from many different classes.</para>
<example>
<title>Simple Pattern</title>
@@ -379,10 +464,9 @@
</example>
<para>For referring to the matched object, use a pattern binding
- variable such as <code>$c</code>. The prefixed dollar symbol ('$')
- is optional; it can
- be useful in complex rules where it helps to more easily
- differentiate between variables and fields.</para>
+ variable such as <code>$c</code>. The prefixed dollar symbol ('$') is
+ optional; it can be useful in complex rules where it helps to more
+ easily differentiate between variables and fields.</para>
<example>
<title>Pattern with a binding variable</title>
@@ -391,17 +475,18 @@
</example>
<para>Inside of the pattern parenthesis is where all the action happens.
- A constraint can be either a Field Constraint, Inline Eval,
- or a Constraint Group. Constraints can be separated by
- the following symbols: ',', '&&' or '||'.</para>
+ A constraint can be either a Field Constraint, Inline Eval, or a
+ Constraint Group. Constraints can be separated by the following symbols:
+ ',', '&&' or '||'.</para>
<figure>
<title>Constraints</title>
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/constraints.png" format="PNG"
- role="" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/constraints.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
@@ -411,8 +496,9 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/constraint.png" format="PNG"
- role="" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/constraint.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
@@ -421,9 +507,9 @@
<title>constraintGroup</title>
<mediaobject>
-
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/constraintGroup.png"
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/constraintGroup.png"
format="PNG" role="" />
</imageobject>
</mediaobject>
@@ -445,8 +531,8 @@
</listitem>
<listitem>
- <para>Group 2 - <code>price < 10</code> demands a price less
- than 10.</para>
+ <para>Group 2 - <code>price < 10</code> demands a price less than
+ 10.</para>
</listitem>
<listitem>
@@ -491,11 +577,12 @@
parentheses, as in any logic or mathematical expression. Example:</para>
<example>
- <title>Using parentheses to change evaluation priority</title>
+ <title>Using parentheses to change evaluation priority</title>
- <programlisting># Cheese type is stilton and ( price is less than 20 or age is mature ).
+ <programlisting># Cheese type is stilton and ( price is less than 20 or age is mature ).
Cheese( type == "stilton" && ( price < 20 || age == "mature" ) ) </programlisting>
- </example>
+ </example>
+
<para>In the above example, the use of parentheses evaluates the
connective '||' before the connective '&&'.</para>
@@ -516,17 +603,16 @@
<section>
<title>Field Constraints</title>
- <para>A Field constraint specifies a restriction to be used on a
- named field; the field name can have an optional variable
- binding.</para>
+ <para>A Field constraint specifies a restriction to be used on a named
+ field; the field name can have an optional variable binding.</para>
<figure>
<title>fieldConstraint</title>
<mediaobject>
-
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/fieldConstraint.png"
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/fieldConstraint.png"
format="PNG" role="" />
</imageobject>
</mediaobject>
@@ -539,10 +625,10 @@
<title>restriction</title>
<mediaobject>
-
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/restriction.png" format="PNG"
- role="" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/restriction.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
@@ -550,28 +636,27 @@
<section>
<title>JavaBeans as facts</title>
- <para>A field is derived from an accessible method of the object.
- If your model
- objects follow the Java Bean pattern, then fields are exposed using
- "getXXX" or "isXXX" methods, where these methods take no
- arguments, and return something. Within patterns, fields can be
+ <para>A field is derived from an accessible method of the object. If
+ your model objects follow the Java Bean pattern, then fields are
+ exposed using "getXXX" or "isXXX" methods, where these methods take
+ no arguments, and return something. Within patterns, fields can be
accessed using the bean naming convention, so that "getType" would
be accessed as "type". Drools uses the standard JDK Introspector
class to do this mapping.</para>
<para>For example, referring to our Cheese class, the pattern
- <code>Cheese(type == "brie")</code> applies the getType() method
- to a Cheese instance. If a field name cannot be found, the
- compiler will resort to using the name as a method without
- arguments. Thus, the method <code>toString()</code> is called due to a
- constraint <code>Cheese(toString == "cheddar")</code>. In this
- case, you use the full name of the method with correct
- capitalization, but still without parentheses. Do
- please make sure that you are accessing methods that take no
- parameters, and that are in fact <emphasis>accessors</emphasis>
- which don't change the state of the object in a way that may effect the rules.
- Remember that the rule engine effectively caches the results of its
- matching in between invocations to make it faster.</para>
+ <code>Cheese(type == "brie")</code> applies the getType() method to
+ a Cheese instance. If a field name cannot be found, the compiler
+ will resort to using the name as a method without arguments. Thus,
+ the method <code>toString()</code> is called due to a constraint
+ <code>Cheese(toString == "cheddar")</code>. In this case, you use
+ the full name of the method with correct capitalization, but still
+ without parentheses. Do please make sure that you are accessing
+ methods that take no parameters, and that are in fact
+ <emphasis>accessors</emphasis> which don't change the state of the
+ object in a way that may effect the rules. Remember that the rule
+ engine effectively caches the results of its matching in between
+ invocations to make it faster.</para>
</section>
<section>
@@ -586,7 +671,9 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/literal.png" format="PNG" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/literal.png"
+ format="PNG" />
</imageobject>
</mediaobject>
</figure>
@@ -596,7 +683,8 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/qualifiedIdentifier.png"
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/qualifiedIdentifier.png"
format="PNG" />
</imageobject>
</mediaobject>
@@ -606,9 +694,9 @@
<title>variable</title>
<mediaobject>
-
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/identifier.png"
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/identifier.png"
format="PNG" />
</imageobject>
</mediaobject>
@@ -619,22 +707,23 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/returnValue.png"
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/returnValue.png"
format="PNG" />
</imageobject>
</mediaobject>
</figure>
- <para>You can do checks against fields that are or may be null, using
- '==' and '!=' as you would expect, and the literal <literal>null</literal> keyword, as
- in <code>Cheese(type != null)</code>, where the evaluator will not
- throw an exception and return true if the value is null.
- Type coercion is always attempted if the field and the value are
- of different types; exceptions will be thrown if a bad coercion is
- attempted. For instance, if "ten" is provided as a string in a numeric
- evaluator, an exception is thrown, whereas "10" would coerce to a
- numeric 10. Coercion is
- always in favor of the field type and not the value type.</para>
+ <para>You can do checks against fields that are or may be null,
+ using '==' and '!=' as you would expect, and the literal
+ <literal>null</literal> keyword, as in <code>Cheese(type !=
+ null)</code>, where the evaluator will not throw an exception and
+ return true if the value is null. Type coercion is always attempted
+ if the field and the value are of different types; exceptions will
+ be thrown if a bad coercion is attempted. For instance, if "ten" is
+ provided as a string in a numeric evaluator, an exception is thrown,
+ whereas "10" would coerce to a numeric 10. Coercion is always in
+ favor of the field type and not the value type.</para>
</section>
<section>
@@ -645,18 +734,18 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/singleValueRestriction.png"
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/singleValueRestriction.png"
format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
- <para>A Single Value Restriction is a binary relation, applying a binary
- operator to the field value and another value, which may be a literal,
- a variable, a parenthesized expression ("return value"), or a qualified
- identifier, i.e., an enum constant.</para>
+ <para>A Single Value Restriction is a binary relation, applying a
+ binary operator to the field value and another value, which may be a
+ literal, a variable, a parenthesized expression ("return value"), or
+ a qualified identifier, i.e., an enum constant.</para>
-
<section>
<title>Operators</title>
@@ -665,7 +754,8 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/operator.png"
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/operator.png"
format="PNG" />
</imageobject>
</mediaobject>
@@ -673,11 +763,13 @@
<para>The operators '==' and '!=' are valid for all types. Other
relational operatory may be used whenever the type values are
- ordered; for date fields, '<' means "before". The pair <literal>matches</literal> and
- <literal>not matches</literal> is only applicable to string fields, <literal>contains</literal> and
- <literal>not contains</literal> require the field to be of some Collection type.
- Coercion to the correct value for the evaluator and the field will be
- attempted, as mentioned in the "Values" section.</para>
+ ordered; for date fields, '<' means "before". The pair
+ <literal>matches</literal> and <literal>not matches</literal> is
+ only applicable to string fields, <literal>contains</literal> and
+ <literal>not contains</literal> require the field to be of some
+ Collection type. Coercion to the correct value for the evaluator
+ and the field will be attempted, as mentioned in the "Values"
+ section.</para>
<simplesect>
<title>The Operator <literal>matches</literal></title>
@@ -685,10 +777,11 @@
<para>Matches a field against any valid Java <indexterm>
<primary>regular expression</primary>
</indexterm>Regular Expression. Typically that regexp is a
- string literal, but variables that resolve to a valid regexp are also
- allowed. It is important to note that, <emphasis>different from
- Java</emphasis>, within regular expressions written as string literals
- <emphasis>you don't need to escape '\'</emphasis>. Example:</para>
+ string literal, but variables that resolve to a valid regexp are
+ also allowed. It is important to note that, <emphasis>different
+ from Java</emphasis>, within regular expressions written as
+ string literals <emphasis>you don't need to escape
+ '\'</emphasis>. Example:</para>
<example>
<title>Regular Expression Constraint</title>
@@ -701,8 +794,8 @@
<title>The Operator <literal>not matches</literal></title>
<para>The operator returns true if the string does not match the
- regular expression. The same rules apply as for the <literal>matches</literal> operator.
- Example:</para>
+ regular expression. The same rules apply as for the
+ <literal>matches</literal> operator. Example:</para>
<example>
<title>Regular Expression Constraint</title>
@@ -714,8 +807,8 @@
<simplesect>
<title>The Operator <literal>contains</literal></title>
- <para>The operator <literal>contains</literal> is used to check whether a
- field that is a <indexterm>
+ <para>The operator <literal>contains</literal> is used to check
+ whether a field that is a <indexterm>
<primary>Collection</primary>
</indexterm>Collection or array contains the specified
value.</para>
@@ -731,11 +824,11 @@
<simplesect>
<title>The Operator <literal>not contains</literal></title>
- <para>The operator <literal>not contains</literal> is used to check whether a
- field that is a <indexterm>
+ <para>The operator <literal>not contains</literal> is used to
+ check whether a field that is a <indexterm>
<primary>Collection</primary>
- </indexterm>Collection or array does <emphasis>not</emphasis> contain the
- specified value.</para>
+ </indexterm>Collection or array does <emphasis>not</emphasis>
+ contain the specified value.</para>
<example>
<title>Literal Constraint with Collections</title>
@@ -745,16 +838,20 @@
</example>
<blockquote>
- <note><para>For backward compatibility, the <literal>excludes</literal>
- operator is supported as a synonym for <literal>not contains</literal>.</para></note>
+ <note>
+ <para>For backward compatibility, the
+ <literal>excludes</literal> operator is supported as a
+ synonym for <literal>not contains</literal>.</para>
+ </note>
</blockquote>
</simplesect>
<simplesect>
<title>The Operator <literal>memberOf</literal></title>
- <para>The operator <literal>memberOf</literal> is used to check whether a field is a
- member of a collection or array; that collection must be a variable.</para>
+ <para>The operator <literal>memberOf</literal> is used to check
+ whether a field is a member of a collection or array; that
+ collection must be a variable.</para>
<example>
<title>Literal Constraint with Collections</title>
@@ -766,9 +863,9 @@
<simplesect>
<title>The Operator <literal>not memberOf</literal></title>
- <para>The operator <literal>not memberOf</literal> is used to check whether a
- field is not a
- member of a collection or array; that collection must be a variable.</para>
+ <para>The operator <literal>not memberOf</literal> is used to
+ check whether a field is not a member of a collection or array;
+ that collection must be a variable.</para>
<example>
<title>Literal Constraint with Collections</title>
@@ -780,10 +877,11 @@
<simplesect>
<title>The Operator <literal>soundslike</literal></title>
- <para>This operator is similar to <literal>matches</literal>, but it checks
- whether a word has almost the same sound (using English pronounciation)
- as the given value. This is based on the Soundex algorithm
- (see <code>http://en.wikipedia.org/wiki/Soundex</code>).</para>
+ <para>This operator is similar to <literal>matches</literal>,
+ but it checks whether a word has almost the same sound (using
+ English pronounciation) as the given value. This is based on the
+ Soundex algorithm (see
+ <code>http://en.wikipedia.org/wiki/Soundex</code>).</para>
<example>
<title>Test with soundslike</title>
@@ -806,14 +904,16 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/literalRestriction.png"
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/literalRestriction.png"
format="PNG" />
</imageobject>
</mediaobject>
</figure>
<para>Literal Restrictions using the operator '==' provide for
- faster execution as we can index using hashing to improve performance.</para>
+ faster execution as we can index using hashing to improve
+ performance.</para>
<simplesect>
<title>Numeric</title>
@@ -832,8 +932,8 @@
<para>The date format "dd-mmm-yyyy" is supported by default. You
can customize this by providing an alternative date format mask
- as the System property named <code>drools.dateformat</code>. If more control
- is required, use the inline-eval constraint.</para>
+ as the System property named <code>drools.dateformat</code>. If
+ more control is required, use the inline-eval constraint.</para>
<example>
<title>Date Literal Restriction</title>
@@ -857,9 +957,10 @@
<simplesect>
<title>Boolean</title>
- <para>Only <code>true</code> or <code>false</code> can be used; 0 and 1 are not
- acceptable. A boolean field alone (as in <code>Cheese( smelly )</code> is
- not permitted; you must compare this to a boolean literal.</para>
+ <para>Only <code>true</code> or <code>false</code> can be used;
+ 0 and 1 are not acceptable. A boolean field alone (as in
+ <code>Cheese( smelly )</code> is not permitted; you must compare
+ this to a boolean literal.</para>
<example>
<title>Boolean Literal Restriction</title>
@@ -871,9 +972,9 @@
<simplesect>
<title>Qualified Identifier</title>
- <para>Enums can be used as well, both JDK 1.4 and 5 style
- enums are supported. For the latter you must be executing on a
- JDK 5 environment.</para>
+ <para>Enums can be used as well, both JDK 1.4 and 5 style enums
+ are supported. For the latter you must be executing on a JDK 5
+ environment.</para>
<example>
<title>Boolean Literal Restriction</title>
@@ -890,9 +991,9 @@
<title>variableRestriction</title>
<mediaobject>
-
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/variableRestriction.png"
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/variableRestriction.png"
format="PNG" />
</imageobject>
</mediaobject>
@@ -904,8 +1005,8 @@
<primary>declaration</primary>
</indexterm>Declaration. Valid operators are determined by the
type of the field being constrained; coercion will be attempted
- where possible. Bound Variable Restrictions using the operator '=='
- provide for very fast execution as we can use hashing to
+ where possible. Bound Variable Restrictions using the operator
+ '==' provide for very fast execution as we can use hashing to
improve performance.</para>
<example>
@@ -915,15 +1016,16 @@
Cheese( type == likes )</programlisting>
</example>
- <para>Here, <code>likes</code> is the variable that is bound in
- its declaration to the field <code>favouriteCheese</code> of any
- matching Person instance. It is then used to constrain the type of
- Cheese in the following pattern. Any valid Java variable name can
- be used, and it may be prefixed with a '$', which you will often
- see used to help differentiate declarations from fields. The example
- below shows a declaration for <code>$stilton</code>, bound to the
- object matching the first pattern and used with a <code>contains</code>
- operator. - Note the optional use of '$'.</para>
+ <para>Here, <code>likes</code> is the variable that is bound in
+ its declaration to the field <code>favouriteCheese</code> of any
+ matching Person instance. It is then used to constrain the type of
+ Cheese in the following pattern. Any valid Java variable name can
+ be used, and it may be prefixed with a '$', which you will often
+ see used to help differentiate declarations from fields. The
+ example below shows a declaration for <code>$stilton</code>, bound
+ to the object matching the first pattern and used with a
+ <code>contains</code> operator. - Note the optional use of
+ '$'.</para>
<example>
<title>Bound Fact using 'contains' operator</title>
@@ -942,17 +1044,19 @@
<mediaobject>
<imageobject>
<imagedata align="center"
- fileref="images/Chapter-Rule_Language/returnValueRestriction.png" format="PNG" />
+ fileref="images/Chapter-Rule_Language/returnValueRestriction.png"
+ format="PNG" />
</imageobject>
</mediaobject>
</figure>
<para>A <indexterm>
<primary>Return Value</primary>
- </indexterm>Return Value restriction is a parenthesized expression
- composed from literals, any valid Java primitive or object, previously
- bound variables, function calls, and operators. Functions used in a
- Return Value must return results that do not depend on time.</para>
+ </indexterm>Return Value restriction is a parenthesized
+ expression composed from literals, any valid Java primitive or
+ object, previously bound variables, function calls, and operators.
+ Functions used in a Return Value must return results that do not
+ depend on time.</para>
<example>
<title>Return Value Restriction</title>
@@ -968,12 +1072,14 @@
<title>Compound Value Restriction</title>
<para>The compound value restriction is used where there is more
- than one possible value to match. Currently only the <literal>in</literal> and
- <literal>not in</literal> evaluators support this. The second operand of this operator must be
- a comma-separated list of values, enclosed in parentheses. Values may
- be given as variables, literals, return values or qualified identifiers.
- Both evaluators are actually "syntactic sugar", internally rewritten as
- a list of multiple restrictions using the operators '!=' and '=='.</para>
+ than one possible value to match. Currently only the
+ <literal>in</literal> and <literal>not in</literal> evaluators
+ support this. The second operand of this operator must be a
+ comma-separated list of values, enclosed in parentheses. Values may
+ be given as variables, literals, return values or qualified
+ identifiers. Both evaluators are actually "syntactic sugar",
+ internally rewritten as a list of multiple restrictions using the
+ operators '!=' and '=='.</para>
<figure>
<title>compoundValueRestriction</title>
@@ -981,13 +1087,13 @@
<mediaobject>
<imageobject>
<imagedata align="center"
- fileref="images/Chapter-Rule_Language/compoundValueRestriction.png" format="PNG"
- role="" />
+ fileref="images/Chapter-Rule_Language/compoundValueRestriction.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
- <para></para>
+ <para />
<example>
<title>Compound Restriction using "in"</title>
@@ -1011,7 +1117,8 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/multiRestriction.png"
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/multiRestriction.png"
format="PNG" role="" />
</imageobject>
</mediaobject>
@@ -1022,13 +1129,14 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/restrictionGroup.png"
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/restrictionGroup.png"
format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
- <para></para>
+ <para />
<example>
<title>Multi Restriction</title>
@@ -1052,7 +1160,8 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/inlineEvalConstraint.png"
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/inlineEvalConstraint.png"
format="PNG" />
</imageobject>
</mediaobject>
@@ -1061,18 +1170,20 @@
<para>An <indexterm>
<primary>Predicate</primary>
</indexterm>inline eval constraint can use any valid dialect
- expression as long as it results to a primitive boolean. The expression
- must be constant over time. Any previously bound variable, from the current
- or previous pattern, can be used; autovivification is also used to
- auto-create field binding variables. When an identifier is found that
- is not a current variable, the builder looks to see if the identifier
- is a field on the current object type, if it is, the field binding
- is auto-created as a variable of the same name. This is called
- autovivification of field variables inside of inline evals.</para>
+ expression as long as it results to a primitive boolean. The
+ expression must be constant over time. Any previously bound variable,
+ from the current or previous pattern, can be used; autovivification is
+ also used to auto-create field binding variables. When an identifier
+ is found that is not a current variable, the builder looks to see if
+ the identifier is a field on the current object type, if it is, the
+ field binding is auto-created as a variable of the same name. This is
+ called autovivification of field variables inside of inline
+ evals.</para>
- <para>This example will find all male-female pairs where the
- male is 2 years older than the female; the variable <code>age</code>
- is auto-created in the second pattern by the autovivification process.</para>
+ <para>This example will find all male-female pairs where the male is 2
+ years older than the female; the variable <code>age</code> is
+ auto-created in the second pattern by the autovivification
+ process.</para>
<example>
<title>Return Value operator</title>
@@ -1086,20 +1197,20 @@
<section>
<title>Nested Accessors</title>
- <para>Drools permits <emphasis>nested accessors</emphasis> in in the field
- constraints using the MVEL accessor graph notation. Field constraints
- involving nested accessors are actually re-written as an MVEL dialect
- inline-eval. Care should be taken when using nested accessors as the
- Working Memory is not aware of any of the nested values, and does not
- know when they change; they should be considered immutable while any
- of their parent references are inserted into the Working Memory. If
- you wish to modify a nested value you should remove the parent objects
- first and re-assert afterwards. If you only have a single parent at
- the root of the graph, when in the MVEL dialect, you can use the
- <literal>modify</literal> construct and its block setters to write the nested accessor
- assignments while retracting and inserting the the root parent object
- as required. Nested accessors can be used on either side of the operator
- symbol.</para>
+ <para>Drools permits <emphasis>nested accessors</emphasis> in in the
+ field constraints using the MVEL accessor graph notation. Field
+ constraints involving nested accessors are actually re-written as an
+ MVEL dialect inline-eval. Care should be taken when using nested
+ accessors as the Working Memory is not aware of any of the nested
+ values, and does not know when they change; they should be considered
+ immutable while any of their parent references are inserted into the
+ Working Memory. If you wish to modify a nested value you should remove
+ the parent objects first and re-assert afterwards. If you only have a
+ single parent at the root of the graph, when in the MVEL dialect, you
+ can use the <literal>modify</literal> construct and its block setters
+ to write the nested accessor assignments while retracting and
+ inserting the the root parent object as required. Nested accessors can
+ be used on either side of the operator symbol.</para>
<example>
<title>Nested Accessors</title>
@@ -1115,32 +1226,35 @@
Pet( owner == $p, eval( age > $p.children[0].age ) ) </programlisting>
</example>
- <remark><emphasis role="bold">Note: </emphasis>Nested accessors have a much
- greater performance cost than direct field accesses, so use them carefully.</remark>
+ <remark><emphasis role="bold">Note: </emphasis>Nested accessors have a
+ much greater performance cost than direct field accesses, so use them
+ carefully.</remark>
</section>
</section>
<section>
<title>Conditional Element <literal>and</literal></title>
- <para>The Conditional Element <literal>and</literal> is used to group other Conditional
- Elements into a logical conjunction. The root element of the LHS is an
- implicit prefix <literal>and</literal> and doesn't need to be specified. Drools supports
- both prefix <literal>and</literal> and infix <literal>and</literal>, but prefix is the preferred option
- as its implicit grouping avoids confusion.</para>
+ <para>The Conditional Element <literal>and</literal> is used to group
+ other Conditional Elements into a logical conjunction. The root element
+ of the LHS is an implicit prefix <literal>and</literal> and doesn't need
+ to be specified. Drools supports both prefix <literal>and</literal> and
+ infix <literal>and</literal>, but prefix is the preferred option as its
+ implicit grouping avoids confusion.</para>
<figure>
<title>prefixAnd</title>
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/prefixAnd.png" format="PNG"
- role="" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/prefixAnd.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
- <para></para>
+ <para />
<example>
<title>prefixAnd</title>
@@ -1158,18 +1272,19 @@
Person( favouriteCheese == cheeseType )</programlisting>
</example>
- <para>Infix <literal>and</literal> is supported along with explicit grouping with
- parentheses, should it be needed. The symbol '&&', as an
- alternative to <literal>and</literal>, is deprecated although it is still supported in
- the syntax for legacy support reasons.</para>
+ <para>Infix <literal>and</literal> is supported along with explicit
+ grouping with parentheses, should it be needed. The symbol '&&',
+ as an alternative to <literal>and</literal>, is deprecated although it
+ is still supported in the syntax for legacy support reasons.</para>
<figure>
<title>infixAnd</title>
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/infixAnd.png" format="PNG"
- role="" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/infixAnd.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
@@ -1189,26 +1304,29 @@
<section>
<title>Conditional Element <literal>or</literal></title>
- <para>The Conditional Element <literal>or</literal> is used to group other Conditional
- Elements into a logical disjunction. Drools supports both prefix <literal>or</literal> and
- infix <literal>or</literal>, but prefix is the preferred option as its implicit grouping
- avoids confusion. The behavior of the Conditional Element <literal>or</literal> is different
- from the connective '||' for constraints and restrictions in field
- constraints. The engine actually has no understanding of the Conditional
- Element <literal>or</literal>; instead, via a number of different logic transformations,
- a rule with <literal>or</literal> is rewritten as a number of subrules. This process ultimately
- results in a rule that has a single <literal>or</literal> as the root node and one subrule
- for each of its CEs. Each subrule can activate and fire like any normal rule;
- there is no special behavior or interaction between these subrules. - This can
- be most confusing to new rule authors.</para>
+ <para>The Conditional Element <literal>or</literal> is used to group
+ other Conditional Elements into a logical disjunction. Drools supports
+ both prefix <literal>or</literal> and infix <literal>or</literal>, but
+ prefix is the preferred option as its implicit grouping avoids
+ confusion. The behavior of the Conditional Element <literal>or</literal>
+ is different from the connective '||' for constraints and restrictions
+ in field constraints. The engine actually has no understanding of the
+ Conditional Element <literal>or</literal>; instead, via a number of
+ different logic transformations, a rule with <literal>or</literal> is
+ rewritten as a number of subrules. This process ultimately results in a
+ rule that has a single <literal>or</literal> as the root node and one
+ subrule for each of its CEs. Each subrule can activate and fire like any
+ normal rule; there is no special behavior or interaction between these
+ subrules. - This can be most confusing to new rule authors.</para>
<figure>
<title>prefixOr</title>
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/prefixOr.png" format="PNG"
- role="" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/prefixOr.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
@@ -1221,18 +1339,19 @@
</programlisting>
</example>
- <para>Infix <literal>or</literal> is supported along with explicit grouping with
- parentheses, should it be needed. The symbol '||', as an alternative to
- <literal>or</literal>, is deprecated although it is still supported in the syntax for
- legacy support reasons.</para>
+ <para>Infix <literal>or</literal> is supported along with explicit
+ grouping with parentheses, should it be needed. The symbol '||', as an
+ alternative to <literal>or</literal>, is deprecated although it is still
+ supported in the syntax for legacy support reasons.</para>
<figure>
<title>infixOr</title>
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/infixOr.png" format="PNG"
- role="" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/infixOr.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
@@ -1248,10 +1367,10 @@
Person( favouriteCheese == cheeseType ) )</programlisting>
</example>
- <para>The Conditional Element <literal>or</literal> also allows for optional pattern
- binding. This means that each resulting subrule will bind its pattern to
- the pattern binding. Each pattern must be bound separately,
- using eponymous variables:</para>
+ <para>The Conditional Element <literal>or</literal> also allows for
+ optional pattern binding. This means that each resulting subrule will
+ bind its pattern to the pattern binding. Each pattern must be bound
+ separately, using eponymous variables:</para>
<example>
<title>or with binding</title>
@@ -1260,17 +1379,18 @@
pensioner : Person( sex == "m", age > 65 ) )</programlisting>
</example>
- <para>Since the conditional element <literal>or</literal> results in multiple subrule
- generation, one for each possible logically outcome, the example above
- would result in the internal generation of two rules. These two rules
- work independently within the Working Memory, which means both can
- match, activate and fire - there is no shortcutting.</para>
+ <para>Since the conditional element <literal>or</literal> results in
+ multiple subrule generation, one for each possible logically outcome,
+ the example above would result in the internal generation of two rules.
+ These two rules work independently within the Working Memory, which
+ means both can match, activate and fire - there is no
+ shortcutting.</para>
- <para>The best way to think of the conditional element <literal>or</literal> is as a
- shortcut for generating two or more similar rules. When you think
- of it that
- way, it's clear that for a single rule there could be multiple
- activations if two or more terms of the disjunction are true.</para>
+ <para>The best way to think of the conditional element
+ <literal>or</literal> is as a shortcut for generating two or more
+ similar rules. When you think of it that way, it's clear that for a
+ single rule there could be multiple activations if two or more terms of
+ the disjunction are true.</para>
</section>
<section>
@@ -1281,20 +1401,23 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/eval.png" format="PNG" role="" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/eval.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
- <para>The CE <literal>eval</literal> is essentially a catch-all which allows any semantic code
- (that returns a primitive boolean) to be executed. This code can refer to
- variables that were bound in the LHS of the rule, and functions in the
- rule package. Overuse of eval reduces the declarativeness of your rules
- and can result in a poorly performing engine. While <literal>eval</literal> can be used
- anywhere in the patterns, the best practice is to add it as the last
- conditional element in the LHS of a rule.</para>
+ <para>The CE <literal>eval</literal> is essentially a catch-all which
+ allows any semantic code (that returns a primitive boolean) to be
+ executed. This code can refer to variables that were bound in the LHS of
+ the rule, and functions in the rule package. Overuse of eval reduces the
+ declarativeness of your rules and can result in a poorly performing
+ engine. While <literal>eval</literal> can be used anywhere in the
+ patterns, the best practice is to add it as the last conditional element
+ in the LHS of a rule.</para>
- <para>Evals cannot be indexed and thus are not as efficient as Field
+ <para>Evals cannot be indexed and thus are not as efficient as Field
Constraints. However this makes them ideal for being used when functions
return values that change over time, which is not allowed within Field
Constraints.</para>
@@ -1321,20 +1444,22 @@
<title>not</title>
<mediaobject>
-
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/not.png" format="PNG" role="" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/not.png"
+ format="PNG" role="" />
</imageobject>
</mediaobject>
</figure>
- <para>The CE <literal>not</literal> is first order logic's non-existential quantifier and checks
- for the non-existence of something in the Working Memory. Think of "not"
- as meaning "there must be none of...".</para>
+ <para>The CE <literal>not</literal> is first order logic's
+ non-existential quantifier and checks for the non-existence of something
+ in the Working Memory. Think of "not" as meaning "there must be none
+ of...".</para>
- <para>The keyword <literal>not</literal> be followed by parentheses around the CEs
- that it applies to. In the simplest case of a single pattern (like
- below) you may optionally omit the parentheses.</para>
+ <para>The keyword <literal>not</literal> be followed by parentheses
+ around the CEs that it applies to. In the simplest case of a single
+ pattern (like below) you may optionally omit the parentheses.</para>
<example>
<title>No Busses</title>
@@ -1363,25 +1488,28 @@
<title>exists</title>
<mediaobject>
-
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/exists.png" format="PNG" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/exists.png"
+ format="PNG" />
</imageobject>
</mediaobject>
</figure>
- <para>The CE <literal>exists</literal> is first order logic's existential quantifier and checks
- for the existence of something in the Working Memory. Think of "exists" as
- meaning "there is at least one..". It is different from just having the pattern
- on its own, which is more like saying "for each one of...". If you use
- <literal>exists</literal> with a pattern, the rule will only activate at most once, regardless
- of how much data there is in working memory that matches the
- condition inside of the <literal>exists</literal> pattern. Since only the existence matters,
- no bindings will be established.</para>
+ <para>The CE <literal>exists</literal> is first order logic's
+ existential quantifier and checks for the existence of something in the
+ Working Memory. Think of "exists" as meaning "there is at least one..".
+ It is different from just having the pattern on its own, which is more
+ like saying "for each one of...". If you use <literal>exists</literal>
+ with a pattern, the rule will only activate at most once, regardless of
+ how much data there is in working memory that matches the condition
+ inside of the <literal>exists</literal> pattern. Since only the
+ existence matters, no bindings will be established.</para>
- <para>The keyword <literal>exists</literal> must be followed by parentheses around the
- CEs that it applies to. In the simplest case of a single pattern (like
- below) you may optionally omit the parentheses.</para>
+ <para>The keyword <literal>exists</literal> must be followed by
+ parentheses around the CEs that it applies to. In the simplest case of a
+ single pattern (like below) you may optionally omit the
+ parentheses.</para>
<example>
<title>At least one Bus</title>
@@ -1409,17 +1537,18 @@
<title>forall</title>
<mediaobject>
-
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/forall.png" format="PNG" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/forall.png"
+ format="PNG" />
</imageobject>
</mediaobject>
</figure>
- <para>The Conditional Element <literal>forall</literal> completes the First Order Logic
- support in Drools. The Conditional Element <literal>forall</literal> evaluates to true
- when all facts that match the first pattern match all the remaining
- patterns. Example:</para>
+ <para>The Conditional Element <literal>forall</literal> completes the
+ First Order Logic support in Drools. The Conditional Element
+ <literal>forall</literal> evaluates to true when all facts that match
+ the first pattern match all the remaining patterns. Example:</para>
<programlisting>rule "All English buses are red"
when
@@ -1436,26 +1565,28 @@
true.</para>
<para>To state that all facts of a given type in the working memory must
- match a set of constraints, <literal>forall</literal> can be written with a single pattern
- for simplicity. Example:</para>
+ match a set of constraints, <literal>forall</literal> can be written
+ with a single pattern for simplicity. Example:</para>
<example>
- <title>Single Pattern Forall</title>
+ <title>Single Pattern Forall</title>
- <programlisting>rule "All Buses are Red"
+ <programlisting>rule "All Buses are Red"
when
forall( Bus( color == 'red' ) )
then
# all asserted Bus facts are red
end
</programlisting>
- </example>
+ </example>
- <para>Another example shows multiple patterns inside the <literal>forall</literal>:</para>
+ <para>Another example shows multiple patterns inside the
+ <literal>forall</literal>:</para>
+
<example>
- <title>Multi-Pattern Forall</title>
+ <title>Multi-Pattern Forall</title>
- <programlisting>rule "all employees have health and dental care programs"
+ <programlisting>rule "all employees have health and dental care programs"
when
forall( $emp : Employee()
HealthCare( employee == $emp )
@@ -1465,15 +1596,18 @@
# all employees have health and dental care
end
</programlisting>
- </example>
+ </example>
<para>Forall can be nested inside other CEs for complete expressiveness.
- For instance, <literal>forall</literal> can be used inside a <literal>not</literal> CE. Note that only single
- patterns have optional parentheses, so that with a nested forall parentheses
- must be used:</para><example>
- <title>Combining Forall with Not CE</title>
+ For instance, <literal>forall</literal> can be used inside a
+ <literal>not</literal> CE. Note that only single patterns have optional
+ parentheses, so that with a nested forall parentheses must be
+ used:</para>
- <programlisting>rule "not all employees have health and dental care"
+ <example>
+ <title>Combining Forall with Not CE</title>
+
+ <programlisting>rule "not all employees have health and dental care"
when
not ( forall( $emp : Employee()
HealthCare( employee == $emp )
@@ -1483,17 +1617,17 @@
# not all employees have health and dental care
end
</programlisting>
- </example>
+ </example>
<para>As a side note, <code>not( forall( p1 p2 p3...))</code> is
- equivalent to writing:</para>
+ equivalent to writing:</para>
<programlisting>not(p1 and not(and p2 p3...))</programlisting>
- <para>Also, it is important to note that <literal>forall</literal> is a <emphasis>scope
- delimiter</emphasis>. Therefore, it can use any previously bound
- variable, but no variable bound inside it will be available for use
- outside of it.</para>
+ <para>Also, it is important to note that <literal>forall</literal> is a
+ <emphasis>scope delimiter</emphasis>. Therefore, it can use any
+ previously bound variable, but no variable bound inside it will be
+ available for use outside of it.</para>
</section>
<section>
@@ -1504,16 +1638,18 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/from.png" format="PNG" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/from.png"
+ format="PNG" />
</imageobject>
</mediaobject>
</figure>
- <para>The Conditional Element <literal>from</literal> enables users to specify an arbitrary
- source for data to be matched by LHS patterns. This
- allows the engine to reason over data not in the Working Memory. The data
- source could be a sub-field on a bound variable or the results of a method
- call. It is a powerful construction that allows out of the box
+ <para>The Conditional Element <literal>from</literal> enables users to
+ specify an arbitrary source for data to be matched by LHS patterns. This
+ allows the engine to reason over data not in the Working Memory. The
+ data source could be a sub-field on a bound variable or the results of a
+ method call. It is a powerful construction that allows out of the box
integration with other application components and frameworks. One common
example is the integration with data retrieved on-demand from databases
using hibernate named queries.</para>
@@ -1548,12 +1684,12 @@
end
</programlisting>
- <para>Previous examples were evaluations using a single pattern. The
- CE <literal>from</literal> also support object sources that return a collection of objects.
- In that case, <literal>from</literal> will iterate over all objects in the
- collection and try to match each of them individually. For instance, if
- we want a rule that applies 10% discount to each item in an order, we
- could do:</para>
+ <para>Previous examples were evaluations using a single pattern. The CE
+ <literal>from</literal> also support object sources that return a
+ collection of objects. In that case, <literal>from</literal> will
+ iterate over all objects in the collection and try to match each of them
+ individually. For instance, if we want a rule that applies 10% discount
+ to each item in an order, we could do:</para>
<programlisting>rule "apply 10% discount to all items over US$ 100,00 in an order"
when
@@ -1567,12 +1703,12 @@
<para>The above example will cause the rule to fire once for each item
whose value is greater than 100 for each given order.</para>
- <para>You must take caution, however, when using <literal>from</literal>,
- especially in conjunction with the
- <literal>lock-on-active</literal> rule attribute
- as it may produce unexpected results. Consider the example provided earlier, but
- now slightly modified as follows:</para>
-
+ <para>You must take caution, however, when using
+ <literal>from</literal>, especially in conjunction with the
+ <literal>lock-on-active</literal> rule attribute as it may produce
+ unexpected results. Consider the example provided earlier, but now
+ slightly modified as follows:</para>
+
<programlisting>rule "Assign people in North Carolina (NC) to sales region 1"
ruleflow-group "test"
lock-on-active true
@@ -1594,51 +1730,57 @@
end
</programlisting>
- <para>
- In the above example, persons in Raleigh, NC should be assigned to sales region 1 and
- receive a discount; i.e., you would expect both rules to activate and fire. Instead you
- will find that only the second rule fires.</para>
-
- <para>If you were to turn on the audit log, you would also see that when the second rule fires,
- it deactivates the first rule. Since the rule attribute <literal>lock-on-active</literal>
- prevents a rule from creating new activations when a set of facts change, the first rule fails to
- reactivate. Though the set of facts have not changed, the use of
- <literal>from</literal> returns a new fact for all intents and purposes each time
- it is evaluated.
- </para>
-
- <para>First, it's important to review why you would use the above pattern. You may have
- many rules across different rule-flow groups. When rules modify working memory and other rules
- downstream of your RuleFlow (in different rule-flow groups) need to be reevaluated,
- the use of <literal>modify</literal> is critical. You don't, however, want other rules in the
- same rule-flow group to place activations on one another recursively. In this case,
- the <literal>no-loop</literal> attribute is ineffective, as it would only prevent a rule from
- activating itself recursively. Hence, you resort to <literal>lock-on-active</literal>.</para>
-
- <para>
- There are several ways to address this issue:</para>
+ <para>In the above example, persons in Raleigh, NC should be assigned to
+ sales region 1 and receive a discount; i.e., you would expect both rules
+ to activate and fire. Instead you will find that only the second rule
+ fires.</para>
+ <para>If you were to turn on the audit log, you would also see that when
+ the second rule fires, it deactivates the first rule. Since the rule
+ attribute <literal>lock-on-active</literal> prevents a rule from
+ creating new activations when a set of facts change, the first rule
+ fails to reactivate. Though the set of facts have not changed, the use
+ of <literal>from</literal> returns a new fact for all intents and
+ purposes each time it is evaluated.</para>
+
+ <para>First, it's important to review why you would use the above
+ pattern. You may have many rules across different rule-flow groups. When
+ rules modify working memory and other rules downstream of your RuleFlow
+ (in different rule-flow groups) need to be reevaluated, the use of
+ <literal>modify</literal> is critical. You don't, however, want other
+ rules in the same rule-flow group to place activations on one another
+ recursively. In this case, the <literal>no-loop</literal> attribute is
+ ineffective, as it would only prevent a rule from activating itself
+ recursively. Hence, you resort to
+ <literal>lock-on-active</literal>.</para>
+
+ <para>There are several ways to address this issue:</para>
+
<itemizedlist>
<listitem>
- <para>Avoid the use of <literal>from</literal> when you can assert all facts into working memory
- or use nested object references in your constraint expressions (shown below).</para>
+ <para>Avoid the use of <literal>from</literal> when you can assert
+ all facts into working memory or use nested object references in
+ your constraint expressions (shown below).</para>
</listitem>
+
<listitem>
- <para>Place the variable assigned used in the modify block as the last sentence
- in your condition (LHS).</para>
+ <para>Place the variable assigned used in the modify block as the
+ last sentence in your condition (LHS).</para>
</listitem>
+
<listitem>
<para>Avoid the use of <literal>lock-on-active</literal> when you
- can explicitly manage how rules within the same rule-flow group place
- activations on one another (explained below).</para>
+ can explicitly manage how rules within the same rule-flow group
+ place activations on one another (explained below).</para>
</listitem>
</itemizedlist>
- <para>The preferred solution is to minimize use of <literal>from</literal> when you can assert
- all your facts into working memory directly. In the example above, both the
- Person and Address instance can be asserted into working memory. In this case,
- because the graph is fairly simple, an even easier solution is to modify your
- rules as follows:</para>
+ <para>The preferred solution is to minimize use of
+ <literal>from</literal> when you can assert all your facts into working
+ memory directly. In the example above, both the Person and Address
+ instance can be asserted into working memory. In this case, because the
+ graph is fairly simple, an even easier solution is to modify your rules
+ as follows:</para>
<programlisting>rule "Assign people in North Carolina (NC) to sales region 1"
ruleflow-group "test"
@@ -1659,20 +1801,19 @@
end
</programlisting>
- <para>Now, you will find that both rules fire as expected. However, it is not
- always possible to access nested facts as above. Consider an example where a Person
- holds one or more Addresses and you wish to use an existential quantifier to
- match people with at least one address that meets certain conditions.
- In this case, you would have to resort to
- the use of <literal>from</literal> to reason over the collection.</para>
-
- <para>
- There are several ways to use <literal>from</literal> to achieve this and not all of them
- exhibit an issue with the use of <literal>lock-on-active</literal>.
- For example, the following use of <literal>from</literal> causes both rules to fire as
- expected:</para>
-
- <programlisting>rule "Assign people in North Carolina (NC) to sales region 1"
+ <para>Now, you will find that both rules fire as expected. However, it
+ is not always possible to access nested facts as above. Consider an
+ example where a Person holds one or more Addresses and you wish to use
+ an existential quantifier to match people with at least one address that
+ meets certain conditions. In this case, you would have to resort to the
+ use of <literal>from</literal> to reason over the collection.</para>
+
+ <para>There are several ways to use <literal>from</literal> to achieve
+ this and not all of them exhibit an issue with the use of
+ <literal>lock-on-active</literal>. For example, the following use of
+ <literal>from</literal> causes both rules to fire as expected:</para>
+
+ <programlisting>rule "Assign people in North Carolina (NC) to sales region 1"
ruleflow-group "test"
lock-on-active true
when
@@ -1692,10 +1833,11 @@
modify ($p) {} #Apply discount to person in a modify block
end
</programlisting>
-
- <para>However, the following slightly different approach does exhibit the problem:</para>
-
- <programlisting>rule "Assign people in North Carolina (NC) to sales region 1"
+
+ <para>However, the following slightly different approach does exhibit
+ the problem:</para>
+
+ <programlisting>rule "Assign people in North Carolina (NC) to sales region 1"
ruleflow-group "test"
lock-on-active true
when
@@ -1718,37 +1860,34 @@
then
modify ($assessment) {} #Modify assessment in a modify block
end</programlisting>
-
- <para>In the above example, the $addresses variable is returned from the
- use of <literal>from</literal>. The example also introduces
- a new object, assessment, to highlight one possible solution in this case.
- If the $assessment variable assigned in the condition (LHS) is moved to the last condition
- in each rule, both rules fire as expected.
- </para>
-
- <para>
- Though the above examples demonstrate how to combine the use of <literal>from</literal>
- with <literal>lock-on-active</literal> where no loss of rule activations occurs, they
- carry the drawback of placing a dependency
- on the order of conditions on the LHS. In addition, the solutions present
- greater complexity for the rule author in terms of keeping track of
- which conditions may create issues.</para>
-
- <para>A better alternative is to
- assert more facts into working memory. In this case, a person's addresses
- may be asserted into working memory and the use of <literal>from</literal>
- would not be necessary.</para>
-
- <para>There are cases, however, where asserting all data into working memory is not
- practical and we need to find other solutions. Another option is to reevaluate the
- need for <literal>lock-on-active</literal>. An alternative to <literal>lock-on-active</literal> is to
- directly manage how rules within the same rule-flow group activate one another
- by including conditions in each rule that prevent rules from activating
- each other recursively when working memory is modified. For example, in the
- case above where a discount is applied to citizens of Raleigh, a condition may
- be added to the rule that checks whether the discount has already been applied.
- If so, the rule does not activate.</para>
-
+
+ <para>In the above example, the $addresses variable is returned from the
+ use of <literal>from</literal>. The example also introduces a new
+ object, assessment, to highlight one possible solution in this case. If
+ the $assessment variable assigned in the condition (LHS) is moved to the
+ last condition in each rule, both rules fire as expected.</para>
+
+ <para>Though the above examples demonstrate how to combine the use of
+ <literal>from</literal> with <literal>lock-on-active</literal> where no
+ loss of rule activations occurs, they carry the drawback of placing a
+ dependency on the order of conditions on the LHS. In addition, the
+ solutions present greater complexity for the rule author in terms of
+ keeping track of which conditions may create issues.</para>
+
+ <para>A better alternative is to assert more facts into working memory.
+ In this case, a person's addresses may be asserted into working memory
+ and the use of <literal>from</literal> would not be necessary.</para>
+
+ <para>There are cases, however, where asserting all data into working
+ memory is not practical and we need to find other solutions. Another
+ option is to reevaluate the need for <literal>lock-on-active</literal>.
+ An alternative to <literal>lock-on-active</literal> is to directly
+ manage how rules within the same rule-flow group activate one another by
+ including conditions in each rule that prevent rules from activating
+ each other recursively when working memory is modified. For example, in
+ the case above where a discount is applied to citizens of Raleigh, a
+ condition may be added to the rule that checks whether the discount has
+ already been applied. If so, the rule does not activate.</para>
</section>
<section>
@@ -1758,16 +1897,18 @@
<title>collect</title>
<mediaobject>
-
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/collect.png" format="PNG" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/collect.png"
+ format="PNG" />
</imageobject>
</mediaobject>
</figure>
- <para>The Conditional Element <literal>collect</literal> allows rules to reason over a collection
- of objects obtained from the given source or from the working memory. In First
- Oder Logic terms this is the cardinality quantifier. A simple example:</para>
+ <para>The Conditional Element <literal>collect</literal> allows rules to
+ reason over a collection of objects obtained from the given source or
+ from the working memory. In First Oder Logic terms this is the
+ cardinality quantifier. A simple example:</para>
<programlisting>import java.util.ArrayList
@@ -1788,25 +1929,26 @@
If 3 or more alarms are found for a given system, the rule will
fire.</para>
- <para>The result pattern of <literal>collect</literal> can
- be any concrete class that implements the <code>java.util.Collection</code>
- interface
- and provides a default no-arg public constructor. This means that you can use
- Java collections like ArrayList, LinkedList, HashSet, etc., or
- your own class, as long as it implements the <code>java.util.Collection</code>
- interface and provide a default no-arg public constructor.</para>
+ <para>The result pattern of <literal>collect</literal> can be any
+ concrete class that implements the <code>java.util.Collection</code>
+ interface and provides a default no-arg public constructor. This means
+ that you can use Java collections like ArrayList, LinkedList, HashSet,
+ etc., or your own class, as long as it implements the
+ <code>java.util.Collection</code> interface and provide a default no-arg
+ public constructor.</para>
<para>Both source and result patterns can be constrained as any other
pattern.</para>
- <para>Variables bound before the <literal>collect</literal> CE are in the scope of both source and
- result patterns and therefore you can use them to constrain both your
- source and result patterns. But note that <literal>collect</literal> is a scope delimiter for
- bindings, so that any binding made inside of it is not available for use
- outside of it.</para>
+ <para>Variables bound before the <literal>collect</literal> CE are in
+ the scope of both source and result patterns and therefore you can use
+ them to constrain both your source and result patterns. But note that
+ <literal>collect</literal> is a scope delimiter for bindings, so that
+ any binding made inside of it is not available for use outside of
+ it.</para>
- <para>Collect accepts nested <literal>from</literal> CEs. The following example is a valid
- use of "collect":</para>
+ <para>Collect accepts nested <literal>from</literal> CEs. The following
+ example is a valid use of "collect":</para>
<programlisting>import java.util.LinkedList;
@@ -1831,19 +1973,23 @@
<mediaobject>
<imageobject>
- <imagedata align="center" fileref="images/Chapter-Rule_Language/accumulate.png" format="PNG" />
+ <imagedata align="center"
+ fileref="images/Chapter-Rule_Language/accumulate.png"
+ format="PNG" />
</imageobject>
</mediaobject>
</figure>
- <para>The Conditional Element <literal>accumulate</literal> is a more flexible and powerful
- form of <literal>collect</literal>, the sense that it can be used to do what <literal>collect</literal> does
- and also achieve things that the CE <literal>collect</literal> is not capable of doing.
- Basically, what it does is that it allows a rule to iterate
- over a collection of objects, executing custom actions for each of the
+ <para>The Conditional Element <literal>accumulate</literal> is a more
+ flexible and powerful form of <literal>collect</literal>, the sense that
+ it can be used to do what <literal>collect</literal> does and also
+ achieve things that the CE <literal>collect</literal> is not capable of
+ doing. Basically, what it does is that it allows a rule to iterate over
+ a collection of objects, executing custom actions for each of the
elements, and at the end it returns a result object.</para>
- <para>The general syntax of the <literal>accumulate</literal> CE is:</para>
+ <para>The general syntax of the <literal>accumulate</literal> CE
+ is:</para>
<programlisting><replaceable><result pattern></replaceable> <literal>from accumulate(</literal> <replaceable><source pattern></replaceable><literal>,</literal>
<literal>init(</literal> <replaceable><init code></replaceable> <literal>),</literal>
@@ -1856,51 +2002,50 @@
<itemizedlist>
<listitem>
- <para><emphasis><source pattern></emphasis>: the
- source pattern is a regular pattern that the engine will try to
- match against each of the source objects.</para>
+ <para><emphasis><source pattern></emphasis>: the source
+ pattern is a regular pattern that the engine will try to match
+ against each of the source objects.</para>
</listitem>
<listitem>
- <para><emphasis><init code></emphasis>: this is a
- semantic block of code in the selected dialect that will be executed
- once for each tuple, before iterating over the source
- objects.</para>
+ <para><emphasis><init code></emphasis>: this is a semantic
+ block of code in the selected dialect that will be executed once for
+ each tuple, before iterating over the source objects.</para>
</listitem>
<listitem>
- <para><emphasis><action code></emphasis>: this is
- a semantic block of code in the selected dialect that will be
- executed for each of the source objects.</para>
+ <para><emphasis><action code></emphasis>: this is a semantic
+ block of code in the selected dialect that will be executed for each
+ of the source objects.</para>
</listitem>
<listitem>
- <para><emphasis><reverse code></emphasis>: this is
- an optional semantic block of code in the selected dialect that if
- present will be executed for each source object that no longer
- matches the source pattern. The objective of this code block is to
- undo any calculation done in the <emphasis><action code></emphasis> block, so
- that the engine can do decremental calculation when a source object
- is modified or retracted, hugely improving performance of these
+ <para><emphasis><reverse code></emphasis>: this is an optional
+ semantic block of code in the selected dialect that if present will
+ be executed for each source object that no longer matches the source
+ pattern. The objective of this code block is to undo any calculation
+ done in the <emphasis><action code></emphasis> block, so that
+ the engine can do decremental calculation when a source object is
+ modified or retracted, hugely improving performance of these
operations.</para>
</listitem>
<listitem>
- <para><emphasis><result expression></emphasis>:
- this is a semantic expression in the selected dialect that is
- executed after all source objects are iterated.</para>
+ <para><emphasis><result expression></emphasis>: this is a
+ semantic expression in the selected dialect that is executed after
+ all source objects are iterated.</para>
</listitem>
<listitem>
- <para><emphasis><result pattern></emphasis>: this
- is a regular pattern that the engine tries to match against the
- object returned from the <emphasis><result expression></emphasis>.
- If it matches, the <literal>accumulate</literal> conditional element
- evaluates to <emphasis>true</emphasis> and the engine
- proceeds with the evaluation of the next CE in the rule. If it does
- not matches, the <literal>accumulate</literal> CE
- evaluates to <emphasis>false</emphasis> and the engine
- stops evaluating CEs for that rule.</para>
+ <para><emphasis><result pattern></emphasis>: this is a regular
+ pattern that the engine tries to match against the object returned
+ from the <emphasis><result expression></emphasis>. If it
+ matches, the <literal>accumulate</literal> conditional element
+ evaluates to <emphasis>true</emphasis> and the engine proceeds with
+ the evaluation of the next CE in the rule. If it does not matches,
+ the <literal>accumulate</literal> CE evaluates to
+ <emphasis>false</emphasis> and the engine stops evaluating CEs for
+ that rule.</para>
</listitem>
</itemizedlist>
@@ -1920,32 +2065,33 @@
end
</programlisting>
- <para>In the above example, for each <code>Order</code> in the
- Working Memory, the engine will execute the <emphasis>init code</emphasis>
+ <para>In the above example, for each <code>Order</code> in the Working
+ Memory, the engine will execute the <emphasis>init code</emphasis>
initializing the total variable to zero. Then it will iterate over all
<code>OrderItem</code> objects for that order, executing the
<emphasis>action</emphasis> for each one (in the example, it will sum
the value of all items into the total variable). After iterating over
- all <code>OrderItem</code> objects, it will return the value corresponding
- to the <emphasis>result expression</emphasis> (in the above example, the
- value of variable <code>total</code>). Finally, the engine will try to match the
- result with the <code>Number</code> pattern, and if the double value is greater
- than 100, the rule will fire.</para>
+ all <code>OrderItem</code> objects, it will return the value
+ corresponding to the <emphasis>result expression</emphasis> (in the
+ above example, the value of variable <code>total</code>). Finally, the
+ engine will try to match the result with the <code>Number</code>
+ pattern, and if the double value is greater than 100, the rule will
+ fire.</para>
<para>The example used Java as the semantic dialect, and as such, note
- that the usage of the semicolon as statement delimiter is mandatory in the
- init, action and reverse code
- blocks. The result is an expression and, as such, it does not admit ';'.
- If the user uses any other dialect, he must comply to that dialect's
- specific syntax.</para>
+ that the usage of the semicolon as statement delimiter is mandatory in
+ the init, action and reverse code blocks. The result is an expression
+ and, as such, it does not admit ';'. If the user uses any other dialect,
+ he must comply to that dialect's specific syntax.</para>
- <para>As mentioned before, the <emphasis>reverse code</emphasis> is optional,
- but it is strongly recommended that the user writes it in order to benefit
- from the <emphasis>improved performance on update and retract</emphasis>.</para>
+ <para>As mentioned before, the <emphasis>reverse code</emphasis> is
+ optional, but it is strongly recommended that the user writes it in
+ order to benefit from the <emphasis>improved performance on update and
+ retract</emphasis>.</para>
- <para>The <literal>accumulate</literal> CE can be used to
- execute any action on source objects. The following example instantiates
- and populates a custom object:</para>
+ <para>The <literal>accumulate</literal> CE can be used to execute any
+ action on source objects. The following example instantiates and
+ populates a custom object:</para>
<programlisting>rule "Accumulate using custom objects"
when
@@ -2033,11 +2179,11 @@
engine and rules can start to use them without any restrictions. To
implement a new Accumulate Functions all one needs to do is to create
a Java class that implements the
- <code>org.drools.base.acumulators.AccumulateFunction</code> interface and add a
- line to the configuration file or set a system property to let the
- engine know about the new function. As an example of an Accumulate
- Function implementation, the following is the implementation of the
- <literal>average</literal> function:</para>
+ <code>org.drools.base.acumulators.AccumulateFunction</code> interface
+ and add a line to the configuration file or set a system property to
+ let the engine know about the new function. As an example of an
+ Accumulate Function implementation, the following is the
+ implementation of the <literal>average</literal> function:</para>
<programlisting role="JAVA">/*
* Copyright 2007 JBoss Inc
@@ -2149,52 +2295,53 @@
<section>
<title>The Right Hand Side (then)</title>
-
<section>
<title>Usage</title>
<para>The Right Hand Side (RHS) is a common name for the consequence or
- action part of the rule; this part should contain a list of actions to be
- executed. It is bad practice to use imperative or conditional code in the
- RHS of a rule; as a rule should be atomic in nature - "when this, then do
- this", not "when this, maybe do this". The RHS part of a rule should also
- be kept small, thus keeping it declarative and readable. If you find you
- need imperative and/or conditional code in the RHS, then maybe you should
- be breaking that rule down into multiple rules. The main purpose of the
- RHS is to insert, retractor modify working memory data. To assist with
- that there are a few convenience methods you can use to modify working
- memory; without having to first reference a working memory
- instance.</para>
+ action part of the rule; this part should contain a list of actions to
+ be executed. It is bad practice to use imperative or conditional code in
+ the RHS of a rule; as a rule should be atomic in nature - "when this,
+ then do this", not "when this, maybe do this". The RHS part of a rule
+ should also be kept small, thus keeping it declarative and readable. If
+ you find you need imperative and/or conditional code in the RHS, then
+ maybe you should be breaking that rule down into multiple rules. The
+ main purpose of the RHS is to insert, retractor modify working memory
+ data. To assist with that there are a few convenience methods you can
+ use to modify working memory; without having to first reference a
+ working memory instance.</para>
- <para><literal>update(</literal><emphasis>object, handle</emphasis><literal>);</literal>
- will tell the engine that an object has
- changed (one that has been bound to something on the LHS) and rules may
- need to be reconsidered.</para>
-
- <para><literal>update(</literal><emphasis>object</emphasis><literal>);</literal> can
- also be used; here the Knowledge Helper will look up the facthandle for you,
- via an identity check, for the passed object. (Note that if you provide
- Property Change Listeners to your Java beans that you are inserting into
- the engine, you can avoid the need to call <code>update()</code> when the
- object changes.)</para>
+ <para><literal>update(</literal><emphasis>object,
+ handle</emphasis><literal>);</literal> will tell the engine that an
+ object has changed (one that has been bound to something on the LHS) and
+ rules may need to be reconsidered.</para>
- <para><literal>insert(new</literal> <emphasis>Something</emphasis><literal>());</literal>
- will place a new object of your creation into the Working Memory.</para>
+ <para><literal>update(</literal><emphasis>object</emphasis><literal>);</literal>
+ can also be used; here the Knowledge Helper will look up the facthandle
+ for you, via an identity check, for the passed object. (Note that if you
+ provide Property Change Listeners to your Java beans that you are
+ inserting into the engine, you can avoid the need to call
+ <code>update()</code> when the object changes.)</para>
- <para><literal>insertLogical(new</literal> <emphasis>Something</emphasis><literal>());</literal>
- is similar to insert, but the object will be automatically retracted when there are
- no more facts to support the truth of the currently firing rule.</para>
+ <para><literal>insert(new</literal>
+ <emphasis>Something</emphasis><literal>());</literal> will place a new
+ object of your creation into the Working Memory.</para>
+ <para><literal>insertLogical(new</literal>
+ <emphasis>Something</emphasis><literal>());</literal> is similar to
+ insert, but the object will be automatically retracted when there are no
+ more facts to support the truth of the currently firing rule.</para>
+
<para><literal>retract(</literal><emphasis>handle</emphasis><literal>);</literal>
removes an object from Working Memory.</para>
-
+
<para>These convenience methods are basically macros that provide short
- cuts to the <code>KnowledgeHelper</code> instance that lets you access your
- Working Memory from rules files. The predefined variable <code>drools</code>
- of type <code>KnowledgeHelper</code> lets you call several other useful
- methods. (Refer to the <code>KnowledgeHelper</code> interface documentation for
- more advanced operations).</para>
-
+ cuts to the <code>KnowledgeHelper</code> instance that lets you access
+ your Working Memory from rules files. The predefined variable
+ <code>drools</code> of type <code>KnowledgeHelper</code> lets you call
+ several other useful methods. (Refer to the <code>KnowledgeHelper</code>
+ interface documentation for more advanced operations).</para>
+
<itemizedlist>
<listitem>
<para>The call <code>drools.halt()</code> terminates rule execution
@@ -2204,10 +2351,10 @@
</listitem>
<listitem>
- <para>Methods <code>insert(Object o)</code>,
- <code>update(Object o)</code> and <code>retract(Object o)</code>
- can be called on <code>drools</code> as well, but due to their
- frequent use they can be called without the object reference.</para>
+ <para>Methods <code>insert(Object o)</code>, <code>update(Object
+ o)</code> and <code>retract(Object o)</code> can be called on
+ <code>drools</code> as well, but due to their frequent use they can
+ be called without the object reference.</para>
</listitem>
<listitem>
@@ -2216,53 +2363,58 @@
</listitem>
<listitem>
- <para><code>drools.setFocus( String s)</code> sets the focus
- to the specified agenda group.</para>
+ <para><code>drools.setFocus( String s)</code> sets the focus to the
+ specified agenda group.</para>
</listitem>
<listitem>
- <para><code>drools.getRule().getName()</code>, called from a
- rule's RHS, returns the name of the rule.</para>
+ <para><code>drools.getRule().getName()</code>, called from a rule's
+ RHS, returns the name of the rule.</para>
</listitem>
<listitem>
- <para><code>drools.getTuple()</code> returns the Tuple that
- matches the currently executing rule, and
+ <para><code>drools.getTuple()</code> returns the Tuple that matches
+ the currently executing rule, and
<code>drools.getActivation()</code> delivers the corresponding
Activation. (These calls are useful for logging and debugging
purposes.)</para>
</listitem>
</itemizedlist>
- <para>The full Knowlege Runtime API is exposed through another predefined
- variable, <code>kcontext</code>, of type <code>KnowledgeContext</code>. Its
- method <code>getKnowledgeRuntime()</code> delivers an object of type
- <code>KnowledgeRuntime</code>, which, in turn, provides access to a wealth
- of methods, many of which are quite useful for coding RHS logic.</para>
+ <para>The full Knowlege Runtime API is exposed through another
+ predefined variable, <code>kcontext</code>, of type
+ <code>KnowledgeContext</code>. Its method
+ <code>getKnowledgeRuntime()</code> delivers an object of type
+ <code>KnowledgeRuntime</code>, which, in turn, provides access to a
+ wealth of methods, many of which are quite useful for coding RHS
+ logic.</para>
<itemizedlist>
<listitem>
<para>The call <code>kcontext.getKnowledgeRuntime().halt()</code>
terminates rule execution immediately.</para>
</listitem>
-
+
<listitem>
- <para>The accessor <code>getAgenda()</code> returns a reference
- to this session's <code>Agenda</code>, which in turn provides access
- to the various rule groups: activation groups, agenda groups, and
- rule flow groups. A fairly common paradigm is the activation of some
+ <para>The accessor <code>getAgenda()</code> returns a reference to
+ this session's <code>Agenda</code>, which in turn provides access to
+ the various rule groups: activation groups, agenda groups, and rule
+ flow groups. A fairly common paradigm is the activation of some
agenda group, which could be done with the lengthy call:</para>
+
<programlisting role="JAVA">
// give focus to the agenda group CleanUp
kcontext.getKnowledgeRuntime().getAgenda().getAgendaGroup( "CleanUp" ).setFocus();</programlisting>
- <para>(You can achieve the same using <code>drools.setFocus( "CleanUp" )</code>.)</para>
+
+ <para>(You can achieve the same using <code>drools.setFocus(
+ "CleanUp" )</code>.)</para>
</listitem>
<listitem>
- <para>To run a query, you call <code>getQueryResults(String query)</code>,
- whereupon you may process the results, as explained in section
- <quote><link linkend='sec.query' endterm="sec.query.title"/></quote>.
- </para>
+ <para>To run a query, you call <code>getQueryResults(String
+ query)</code>, whereupon you may process the results, as explained
+ in section <quote><link endterm="sec.query.title"
+ linkend="sec.query"></link></quote>.</para>
</listitem>
<listitem>
@@ -2273,48 +2425,47 @@
<listitem>
<para>Method<code>getKnowledgeBase()</code> returns the
- <code>KnowledgeBase</code> object, the backbone of all the
- Knowledge in your system, and the originator of the current
- session.</para>
+ <code>KnowledgeBase</code> object, the backbone of all the Knowledge
+ in your system, and the originator of the current session.</para>
</listitem>
<listitem>
<para>You can manage globals with <code>setGlobal(...)</code>,
<code>getGlobal(...)</code> and <code>getGlobals()</code>.</para>
</listitem>
-
+
<listitem>
<para>Method <code>getEnvironment()</code> returns the runtime's
- <code>Environment</code> which works much like what you know as
- your operating system's environment.</para>
+ <code>Environment</code> which works much like what you know as your
+ operating system's environment.</para>
</listitem>
</itemizedlist>
-
</section>
<section>
<title>The <literal>modify</literal> Statement</title>
- <para>This language extension provides a structured approach to
- fact updates. It combines the update operation with a number of
- setter calls to change the object's fields. This is the syntax
- schema for the <literal>modify</literal> statement:</para>
+ <para>This language extension provides a structured approach to fact
+ updates. It combines the update operation with a number of setter calls
+ to change the object's fields. This is the syntax schema for the
+ <literal>modify</literal> statement:</para>
<programlisting><literal>modify ( </literal><replaceable><fact-expression></replaceable><literal> ) {</literal>
<replaceable><expression></replaceable> [ <literal>,</literal> <replaceable><expression></replaceable> ]*
<literal>}</literal></programlisting>
- <para>The parenthesized <emphasis><fact-expression></emphasis> must yield
- a fact object reference. The expression list in the block should consist of
- setter calls for the given object, to be written without the usual object reference,
- which is automatically prepended by the compiler.</para>
+ <para>The parenthesized <emphasis><fact-expression></emphasis>
+ must yield a fact object reference. The expression list in the block
+ should consist of setter calls for the given object, to be written
+ without the usual object reference, which is automatically prepended by
+ the compiler.</para>
<para>The example illustrates a simple fact modification.</para>
- <example>
- <title>A modify statement</title>
+ <example>
+ <title>A modify statement</title>
- <programlisting>rule "modify stilton"
+ <programlisting>rule "modify stilton"
when
$stilton : Cheese(type == "stilton")
then
@@ -2323,10 +2474,8 @@
setAge( "overripe" )
}
end</programlisting>
- </example>
-
+ </example>
</section>
-
</section>
<section>
@@ -2337,9 +2486,9 @@
block or expression will no longer need manual unboxing; unlike Drools 3.0
where all primitives were autoboxed, requiring manual unboxing. A variable
bound to an object wrapper will remain as an object; the existing JDK 1.5
- and JDK 5 rules to handle auto-boxing and unboxing apply in this case. When
- evaluating field constraints, the system attempts to coerce one of the
- values into a comparable format; so a primitive is comparable to an object
- wrapper.</para>
+ and JDK 5 rules to handle auto-boxing and unboxing apply in this case.
+ When evaluating field constraints, the system attempts to coerce one of
+ the values into a comparable format; so a primitive is comparable to an
+ object wrapper.</para>
</section>
</section>
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-expert/src/main/docbook/en-US/Chapter-User_Guide/Section-Running.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-expert/src/main/docbook/en-US/Chapter-User_Guide/Section-Running.xml 2010-07-30 04:43:05 UTC (rev 34398)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-expert/src/main/docbook/en-US/Chapter-User_Guide/Section-Running.xml 2010-07-30 05:25:59 UTC (rev 34399)
@@ -1,9 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<section version="5.0"
xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
- xml:base="../" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
+ xml:base="../" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
<title>Running</title>
<para></para>
@@ -171,8 +174,8 @@
objects. The <code>update()</code> method can only be used with
objects that have shadow proxies turned on. The update method is only
available within Java code. On the right hand side of a rule, also the
- <literal>modify</literal> statement is supported, providing simplified calls to
- the object's setters.</para>
+ <literal>modify</literal> statement is supported, providing simplified
+ calls to the object's setters.</para>
<programlisting role="JAVA">Cheese stilton = new Cheese("stilton");
FactHandle stiltonHandle = workingMemory.insert( stilton );
@@ -243,6 +246,56 @@
}</programlisting>
</example>
</section>
+
+ <section>
+ <title>Live Querries</title>
+
+ <para>Drools has always had query support, but the result was returned
+ as an iterable set; this makes it hard to monitor changes over
+ time.</para>
+
+ <para>We have now complimented this with Live Querries, which has a
+ listener attached instead of returning an iterable result set. These
+ live querries stay open creating a view and publish change events for
+ the contents of this view. So now you can execute your query, with
+ parameters and listen to changes in the resulting view.</para>
+
+ <example>
+ <title>Implementing ViewChangedEventListener</title>
+
+ <programlisting language="java">final List updated = new ArrayList();
+final List removed = new ArrayList();
+final List added = new ArrayList();
+
+ViewChangedEventListener listener = new ViewChangedEventListener() {
+ public void rowUpdated(Row row) {
+ updated.add( row.get( "$price" ) );
+ }
+
+ public void rowRemoved(Row row) {
+ removed.add( row.get( "$price" ) );
+ }
+
+ public void rowAdded(Row row) {
+ added.add( row.get( "$price" ) );
+ }
+};
+
+// Open the LiveQuery
+LiveQuery query = ksession.openLiveQuery( "cheeses",
+ new Object[] { "cheddar", "stilton" },
+ listener );
+...
+...
+query.dispose() // make sure you call dispose when you want the query to close</programlisting>
+ </example>
+
+ <para>A Drools blog article contains an example of Glazed Lists
+ integration for live queries,</para>
+
+ <para><link
+ xlink:href="http://blog.athico.com/2010/07/glazed-lists-examples-for-drools-live.html">http://blog.athico.com/2010/07/glazed-lists-examples-for-drools-live.html</link></para>
+ </section>
</section>
<section>
@@ -250,7 +303,8 @@
<para>The <code>KnowledgeRuntime</code> provides further methods that
are applicable to both rules and processes, such as setting globals and
- registering <code>ExitPoints</code>.</para>
+ registering <code>Channels (previously exit points, some references may
+ remain in docs for a while)</code>.</para>
<figure>
<title>KnowledgeRuntime</title>
@@ -336,6 +390,7 @@
<code>fireAllRules()</code>. The following example permits only rules
ending in the string <code>"Test"</code>. All others will be filtered
out.</para>
+
<programlisting role="JAVA">ksession.fireAllRules( new RuleNameEndsWithAgendaFilter( "Test" ) );</programlisting>
</section>
</section>
@@ -482,7 +537,9 @@
"activation-group" rule attribute. In this group only one rule can fire,
and after that rule has fired all the other rules are cancelled from the
agenda. The <code>clear()</code> method can be called at any time, which
- cancels all of the activations before one has had a chance to fire.</para>
+ cancels all of the activations before one has had a chance to
+ fire.</para>
+
<programlisting role="JAVA">ksession.getAgenda().getActivationGroup( "Group B" ).clear();</programlisting>
</section>
@@ -506,6 +563,7 @@
elaboration of the ruleflow diagram reaches the node representing the
group. Here too, the <code>clear()</code> method can be called at any
time to cancels all activations still remaining on the Agenda.</para>
+
<programlisting role="JAVA">ksession.getAgenda().getRuleFlowGroup( "Group C" ).clear();</programlisting>
</section>
</section>
@@ -919,356 +977,6 @@
</section>
<section>
- <title>Pipeline</title>
-
- <para>The <code>PipelineFactory</code> and associated classes are there to
- help with the automation of getting information into and out of Drools,
- especially when using services such as Java Message Service (JMS), and
- other data sources that aren't Java objects. Transformers for Smooks,
- JAXB, XStream and jXLS are povided. Smooks is an ETL (extract, transform,
- load) tool and can work with a variety of data sources. JAXB is a Java
- standard for XML binding capable of working with XML schemas. XStream is a
- simple and fast XML serialisation framework. jXLS finally allows for
- loading of Java objects from an Excel spreadsheet. Minimal information on
- these technologies will be provided here; beyond this, you should consult
- the relevant user guide for each of these tools.</para>
-
- <figure>
- <title>PipelineFactory</title>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/Chapter-User_Guide/PipelineFactory.png"
- format="" width="100%"></imagedata>
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>Pipeline is not meant as a replacement for products like the more
- powerful Apache Camel. It is a simple framework aimed at the specific
- Drools use cases.</para>
-
- <para>In Drools, a pipeline is a series of stages that operate on and
- propagate a given payload. Typically this starts with a
- <code>Pipeline</code> instance which is responsible for taking the
- payload, creating a <code>PipelineContext</code> for it and propagating
- that to the first receiver stage. Two subtypes of <code>Pipeline</code>
- are provided, both requiring a different <code>PipelineContext</code>:
- <code>StatefulKnowledgeSessionPipeline</code> and
- <code>StatelessKnowledgeSessionPipeline</code>.
- <code>PipelineFactory</code> provides methods to create both of the two
- <code>Pipeline</code> subtypes. Notice that both factory methods take the
- relevant session as an argument. The construction of a
- <code>StatefulKnowledgeSessionPipeline</code> is shown below, where also
- its receiver is set.</para>
-
- <example>
- <title>StatefulKnowledgeSessionPipeline</title>
-
- <programlisting role="JAVA">Pipeline pipeline = PipelineFactory.newStatefulKnowledgeSessionPipeline( ksession );
-pipeline.setReceiver( receiver );</programlisting>
- </example>
-
- <para>A pipeline is then made up of a chain of <code>Stage</code>s that
- implement both the <code>Emitter</code> and the <code>Receiver</code>
- interfaces. The <code>Emitter</code> interface enables the
- <code>Stage</code> to propagate a payload, and the <code>Receiver</code>
- interface lets it receive a payload. This is why the <code>Pipeline</code>
- interface only implements <code>Emitter</code> and <code>Stage</code> and
- not <code>Receiver</code>, as it is the first instance in the chain. The
- <code>Stage</code> interface allows a custom exception handler to be set
- on the <code>Stage</code> object.</para>
-
- <example>
- <title>StageExceptionHandler</title>
-
- <programlisting role="JAVA">Transformer transformer = PipelineFactory.newXStreamFromXmlTransformer( xstream );
-transformer.setStageExceptionHandler( new StageExceptionHandler() { .... } );
-</programlisting>
- </example>
-
- <para>The <code>Transformer</code> interface extends <code>Stage</code>,
- <code>Emitter</code> and <code>Receiver</code>, providing those interface
- methods as a single type. Its other purpose is that of a marker interface
- indicating this particulare role of the implementing class. (We have
- several other marker interfaces such as <code>Expression</code> and
- <code>Action</code>, both of which also extend <code>Stage</code>,
- <code>Emitter</code> and <code>Receiver</code>.) One of the stages should
- be responsible for setting a result value on the
- <code>PipelineContext</code>. It's the responsibility of the
- <code>ResultHandler</code> interface, to be implemented by the user, to
- process on these results. It may do so by inserting them into some
- suitable object, whence the user's code may retrieve them.</para>
-
- <example>
- <title>StageExceptionHandler</title>
-
- <programlisting role="JAVA">ResultHandler resultHandler = new ResultHandlerImpl();
-pipeline.insert( factHandle, resultHandler );
-System.out.println( resultHandler );
-...
-public class ResultHandlerImpl implements ResultHandler {
- Object result;
-
- public void handleResult(Object result) {
- this.result = result;
- }
-
- public Object getResult() {
- return this.result;
- }
-}
-</programlisting>
- </example>
-
- <para>While the above example shows a simple handler that merely assigns
- the result to a field that the user can access, it could do more complex
- work like sending the object as a message.</para>
-
- <para>Pipeline provides an adapter to insert the payload and to create the
- correct Pipeline Context internally.</para>
-
- <para>In general it is easier to construct the pipelines in reverse. In
- the following example XML data is loaded from disk, transformed with
- XStream and finally inserted into the session.</para>
-
- <example>
- <title>Constructing a pipeline</title>
-
- <programlisting role="JAVA">// Make the results (here: FactHandles) available to the user
-Action executeResultHandler = PipelineFactory.newExecuteResultHandler();
-
-// Insert the transformed object into the session
-// associated with the PipelineContext
-KnowledgeRuntimeCommand insertStage =
- PipelineFactory.newStatefulKnowledgeSessionInsert();
-insertStage.setReceiver( executeResultHandler );
-
-// Create the transformer instance and the Transformer Stage,
-// to transform from Xml to a Java object.
-XStream xstream = new XStream();
-Transformer transformer = PipelineFactory.newXStreamFromXmlTransformer( xstream );
-transformer.setReceiver( insertStage );
-
-// Create the start adapter Pipeline for StatefulKnowledgeSessions
-Pipeline pipeline = PipelineFactory.newStatefulKnowledgeSessionPipeline( ksession );
-pipeline.setReceiver( transformer );
-
-// Instantiate a simple result handler and load and insert the XML
-ResultHandlerImpl resultHandler = new ResultHandlerImpl();
-pipeline.insert( ResourceFactory.newClassPathResource( "path/facts.xml", getClass() ),
- resultHandler );
-</programlisting>
- </example>
-
- <para>While the above example is for loading a resource from disk, it is
- also possible to work from a running messaging service. Drools currently
- provides a single service for JMS, called <code>JmsMessenger</code>.
- Support for other services will be added later. The code below shows part
- of a unit test which illustrates part of the <code>JmsMessenger</code> in
- action:</para>
-
- <example>
- <title>Using JMS with Pipeline</title>
-
- <programlisting role="JAVA">// As this is a service, it's more likely that
-// the results will be logged or sent as a return message.
-Action resultHandlerStage = PipelineFactory.newExecuteResultHandler();
-
-// Insert the transformed object into the session associated with the PipelineContext
-KnowledgeRuntimeCommand insertStage = PipelineFactory.newStatefulKnowledgeSessionInsert();
-insertStage.setReceiver( resultHandlerStage );
-
-// Create the transformer instance and create the Transformer stage where we are
-// going from XML to Pojo. JAXB needs an array of the available classes.
-JAXBContext jaxbCtx = KnowledgeBuilderHelper.newJAXBContext( classNames,
- kbase );
-Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
-Transformer transformer = PipelineFactory.newJaxbFromXmlTransformer( unmarshaller );
-transformer.setReceiver( insertStage );
-
-// Payloads for JMS arrive in a Message wrapper: we need to unwrap this object.
-Action unwrapObjectStage = PipelineFactory.newJmsUnwrapMessageObject();
-unwrapObjectStage.setReceiver( transformer );
-
-// Create the start adapter Pipeline for StatefulKnowledgeSessions
-Pipeline pipeline = PipelineFactory.newStatefulKnowledgeSessionPipeline( ksession );
-pipeline.setReceiver( unwrapObjectStage );
-
-// Services, like JmsMessenger take a ResultHandlerFactory implementation.
-// This is because a result handler must be created for each incoming message.
-ResultHandlerFactory factory = new ResultHandlerFactoryImpl();
-Service messenger = PipelineFactory.newJmsMessenger( pipeline,
- props,
- destinationName,
- factory );
-messenger.start();
-</programlisting>
- </example>
-
- <section>
- <title>Xstream Transformer</title>
-
- <example>
- <title>XStream FromXML transformer stage</title>
-
- <programlisting role="JAVA">XStream xstream = new XStream();
-Transformer transformer = PipelineFactory.newXStreamFromXmlTransformer( xstream );
-transformer.setReceiver( nextStage );</programlisting>
- </example> <example>
- <title>XStream ToXML transformer stage</title>
-
- <programlisting role="JAVA">XStream xstream = new XStream();
-Transformer transformer = PipelineFactory.newXStreamToXmlTransformer( xstream );
-transformer.setReceiver( receiver );</programlisting>
- </example>
- </section>
-
- <section>
- <title>JAXB Transformer</title>
-
- <para>The Transformer objects are <code>JaxbFromXmlTransformer</code>
- and <code>JaxbToXmlTransformer</code>. The former uses an
- <code>javax.xml.bind.Unmarshaller</code> for converting an XML document
- into a content tree; the latter serializes a content tree to XML by
- passing it to a <code>javax.xml.bind.Marshaller</code>. Both of these
- objects can be obtained from a <code>JAXBContext</code> object.</para>
-
- <para>A JAXBContext maintains the set of Java classes that are bound to
- XML elements. Such classes may be generated from an XML schema, by
- compiling it with JAXB's schema compiler <command>xjc</command>.
- Alternatively, handwritten classes can be augmented with annotations
- from <code>jaxb.xml.bind.annotation</code>.</para>
-
- <para>Unmarshalling an XML document results in an object tree. Inserting
- objects from this tree as facts into a session can be done by walking
- the tree and inserting nodes as appropriate. This could be done in the
- context of a pipeline by a custom Transformer that emits the nodes one
- by one to its receiver.</para>
-
- <example>
- <title>JAXB XSD Generation into the KnowlegeBuilder</title>
-
- <programlisting role="JAVA">Options xjcOpts = new Options();
-xjcOpts.setSchemaLanguage( Language.XMLSCHEMA );
-KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
-
-String[] classNames =
- KnowledgeBuilderHelper.addXsdModel(
- ResourceFactory.newClassPathResource( "order.xsd", getClass() ),
- kbuilder,
- xjcOpts,
- "xsd" );</programlisting>
- </example>
- <example>
- <title>JAXB From XML transformer stage</title>
-
- <programlisting role="JAVA">JAXBContext jaxbCtx =
- KnowledgeBuilderHelper.newJAXBContext( classNames, kbase );
-Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
-Transformer transformer = PipelineFactory.newJaxbFromXmlTransformer( unmarshaller );
-transformer.setReceiver( receiver );
- </programlisting>
- </example>
- <example>
- <title>JAXB to XML transformer stage</title>
-
- <programlisting role="JAVA">Marshaller marshaller = jaxbCtx.createMarshaller();
-Transformer transformer = PipelineFactory.newJaxbToXmlTransformer( marshaller );
-transformer.setReceiver( receiver );</programlisting>
- </example>
- </section>
-
- <section>
- <title>Smooks Transformer</title>
-
- <example>
- <title>Smooks FromSource transformer stage</title>
-
- <programlisting role="JAVA">Smooks smooks = new Smooks( getClass().getResourceAsStream( "smooks-config.xml" ) );
-Transformer transformer =
- PipelineFactory.newSmooksFromSourceTransformer( smooks, "orderItem" );
-transformer.setReceiver( receiver );</programlisting>
- </example>
- <example>
- <title>Smooks ToSource transformer stage</title>
-
- <programlisting role="JAVA">Smooks smooks = new Smooks( getClass().getResourceAsStream( "smooks-config.xml" ) );
-Transformer transformer = PipelineFactory.newSmooksToSourceTransformer( smooks );
-transformer.setReceiver( receiver );</programlisting>
- </example>
- </section>
-
- <section>
- <title>jXLS (Excel/Calc/CSV) Transformer</title>
-
- <para>This transformer transforms from an Excel spreadsheet to a map of
- Java objects, using jXLS, and the resulting map is set as the
- propagating object. You may need to use splitters and MVEL expressions
- to split up the transformation to insert individual Java objects. Note
- that you must provde an XLSReader, which references the mapping file and
- also an MVEL string which will instantiate the map. The MVEL expression
- is pre-compiled but executed on each usage of the transformation.</para>
-
- <example>
- <title>JXLS transformer stage</title>
-
- <programlisting role="JAVA">XLSReader mainReader =
- ReaderBuilder.buildFromXML( ResourceFactory.newClassPathResource( "departments.xml", getClass() ).getInputStream() );
-String expr = "[ 'departments' : new java.util.ArrayList()," +
- " 'company' : new org.drools.runtime.pipeline.impl.Company() ]";
-Transformer transformer = PipelineFactory.newJxlsTransformer(mainReader, expr );</programlisting>
- </example>
- </section>
-
- <section>
- <title>JMS Messenger</title>
-
- <para>This transformer creates a new <code>JmsMessenger</code> which
- runs as a service in its own thread. It expects an existing JNDI entry
- for "ConnectionFactory", used to create the MessageConsumer which will
- feed into the specified pipeline.</para>
-
- <example>
- <title>JMS Messenger stage</title>
-
- <programlisting role="JAVA">// As this is a service, it's more likely the results will be logged
-// or sent as a return message.
-Action resultHandlerStage = PipelineFactory.newExecuteResultHandler();
-
-// Insert the transformed object into the session associated with the PipelineContext
-KnowledgeRuntimeCommand insertStage = PipelineFactory.newStatefulKnowledgeSessionInsert();
-insertStage.setReceiver( resultHandlerStage );
-
-// Create the transformer instance and create the Transformer stage,
-// where we are going from XML to Java object.
-// JAXB needs an array of the available classes
-JAXBContext jaxbCtx = KnowledgeBuilderHelper.newJAXBContext( classNames, kbase );
-Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
-Transformer transformer = PipelineFactory.newJaxbFromXmlTransformer( unmarshaller );
-transformer.setReceiver( insertStage );
-
-// Payloads for JMS arrive in a Message wrapper, we need to unwrap this object.
-Action unwrapObjectStage = PipelineFactory.newJmsUnwrapMessageObject();
-unwrapObjectStage.setReceiver( transformer );
-
-// Create the start adapter Pipeline for StatefulKnowledgeSessions
-Pipeline pipeline = PipelineFactory.newStatefulKnowledgeSessionPipeline( ksession );
-pipeline.setReceiver( unwrapObjectStage );
-
-// Services like JmsMessenger take a ResultHandlerFactory implementation.
-// This is so because a result handler must be created for each incoming message.
-ResultHandleFactoryImpl factory = new ResultHandleFactoryImpl();
-Service messenger = PipelineFactory.newJmsMessenger( pipeline,
- props,
- destinationName,
- factory );
-</programlisting>
- </example>
- </section>
- </section>
-
- <section>
<title>Commands and the CommandExecutor</title>
<para>Drools has the concept of stateful or stateless sessions. We've
@@ -1463,89 +1171,10 @@
</programlisting>
</example>
- <para>The previously mentioned pipeline allows for a series of Stage
- objects, combined to help with getting data into and out of sessions.
- There is a Stage implementing the <code>CommandExecutor</code> interface
- that allows the pipeline to script either a stateful or stateless session.
- The pipeline setup is trivial:</para>
+ <para>Spring and Camel, covered in the integrations book, facilitate
+ declarative services.</para>
<example>
- <title>Pipeline for CommandExecutor</title>
-
- <programlisting role="JAVA">Action executeResultHandler = PipelineFactory.newExecuteResultHandler();
-
-Action assignResult = PipelineFactory.newAssignObjectAsResult();
-assignResult.setReceiver( executeResultHandler );
-
-Transformer outTransformer =
- PipelineFactory.newXStreamToXmlTransformer( BatchExecutionHelper.newXStreamMarshaller() );
-outTransformer.setReceiver( assignResult );
-
-KnowledgeRuntimeCommand cmdExecution = PipelineFactory.newCommandExecutor();
-batchExecution.setReceiver( cmdExecution );
-
-Transformer inTransformer =
- PipelineFactory.newXStreamFromXmlTransformer( BatchExecutionHelper.newXStreamMarshaller() );
-inTransformer.setReceiver( batchExecution );
-
-Pipeline pipeline = PipelineFactory.newStatelessKnowledgeSessionPipeline( ksession );
-pipeline.setReceiver( inTransformer );
-</programlisting>
- </example>
-
- <para>The key thing here to note is the use of the
- <code>BatchExecutionHelper</code> to provide a specially configured
- XStream with custom converters for our Command objects and the new
- <code>BatchExecutor</code> stage.</para>
-
- <para>Using the pipeline is very simple. You must provide your own
- implementation of the <code>ResultHandler</code> which is called when the
- pipeline executes the <code>ExecuteResultHandler</code> stage.</para>
-
- <figure>
- <title>Pipeline ResultHandler</title>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/Chapter-User_Guide/ResultHandler.png"
- format=""></imagedata>
- </imageobject>
- </mediaobject>
- </figure>
-
- <example>
- <title>Simple Pipeline ResultHandler</title>
-
- <programlisting role="JAVA">public static class ResultHandlerImpl implements ResultHandler {
- Object object;
-
- public void handleResult(Object object) {
- this.object = object;
- }
-
- public Object getObject() {
- return this.object;
- }
-}
-</programlisting>
- </example>
-
- <example>
- <title>Using a Pipeline</title>
-
- <programlisting role="JAVA">
-InputStream inXml = ...;
-ResultHandler resultHandler = new ResultHandlerImpl();
-pipeline.insert( inXml, resultHandler );
-</programlisting>
- </example>
-
- <para>Earlier a <code>BatchExecution</code> was created with Java to
- insert some objects and execute a query. The XML representation to be used
- with the pipeline for that example is shown below, with parameters added
- to the query.</para>
-
- <example>
<title>BatchExecution Marshalled to XML</title>
<programlisting><batch-execution>
@@ -1701,12 +1330,13 @@
</example>
<para><code><set-global></code> also supports two other optional
- attributes, <literal>out</literal> and <literal>out-identifier</literal>. A true value for the
- boolean <literal>out</literal> will add the global to the
- <code><batch-execution-results></code> payload, using the name from
- the <literal>identifier</literal> attribute. <literal>out-identifier</literal> works like
- <literal>out</literal> but additionally allows you to override the identifier used
- in the <code><batch-execution-results></code> payload.</para>
+ attributes, <literal>out</literal> and <literal>out-identifier</literal>.
+ A true value for the boolean <literal>out</literal> will add the global to
+ the <code><batch-execution-results></code> payload, using the name
+ from the <literal>identifier</literal> attribute.
+ <literal>out-identifier</literal> works like <literal>out</literal> but
+ additionally allows you to override the identifier used in the
+ <code><batch-execution-results></code> payload.</para>
<example>
<title>Set Global Command</title>
@@ -1727,9 +1357,10 @@
</example>
<para>There is also a <code><get-global></code> element, without
- contents, with just an <literal>out-identifier</literal> attribute. (There is no
- need for an <literal>out</literal> attribute because retrieving the value is the
- sole purpose of a <code><get-global></code> element.</para>
+ contents, with just an <literal>out-identifier</literal> attribute. (There
+ is no need for an <literal>out</literal> attribute because retrieving the
+ value is the sole purpose of a <code><get-global></code>
+ element.</para>
<example>
<title>Get Global Command</title>
@@ -1741,12 +1372,13 @@
</programlisting>
</example>
- <para>While the <literal>out</literal> attribute is useful in returning specific
- instances as a result payload, we often wish to run actual queries. Both
- parameter and parameterless queries are supported. The <literal>name</literal>
- attribute is the name of the query to be called, and the
- <literal>out-identifier</literal> is the identifier to be used for the query results
- in the <code><execution-results></code> payload.</para>
+ <para>While the <literal>out</literal> attribute is useful in returning
+ specific instances as a result payload, we often wish to run actual
+ queries. Both parameter and parameterless queries are supported. The
+ <literal>name</literal> attribute is the name of the query to be called,
+ and the <literal>out-identifier</literal> is the identifier to be used for
+ the query results in the <code><execution-results></code>
+ payload.</para>
<example>
<title>Query Command</title>
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-integration/src/main/docbook/en-US/Chapter-Server/Section-Configuration/Section-Configuration.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-integration/src/main/docbook/en-US/Chapter-Server/Section-Configuration/Section-Configuration.xml 2010-07-30 04:43:05 UTC (rev 34398)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-integration/src/main/docbook/en-US/Chapter-Server/Section-Configuration/Section-Configuration.xml 2010-07-30 05:25:59 UTC (rev 34399)
@@ -9,11 +9,64 @@
xmlns:ns="http://docbook.org/ns/docbook">
<title>Configuration</title>
- <para>Inside the war file you will found a few XML configuration files. The
- most importants are knowledge-services.xml and camel-server.xml that we'll
- see in depth in the next sections. The other file, beans.xml only includes
- these two files.</para>
+ <para>Inside the war file you will find a few XML configuration
+ files.</para>
+ <itemizedlist>
+ <listitem>
+ <para>breans.xml</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Skeleton xml that imports knowledge-services.xml and
+ camel-server.xml</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>camel-server.xml</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Configures CXF endpoints with Camel Routes</para>
+ </listitem>
+
+ <listitem>
+ <para>Came Routes pipeline messages to various configured knowledge
+ services</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>knowledge-services.xml</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Various Knowege Bases and Sessions</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>camel-client.xml</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Sample camel client showing how to send and receive a
+ message</para>
+ </listitem>
+
+ <listitem>
+ <para>Used by "out of the box" test.jsp</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+
+ <para></para>
+
<section>
<title>REST/Camel Services configuration</title>
@@ -37,10 +90,16 @@
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<!--
+ ! If you are running on JBoss you will need to copy a camel-jboss.jar into the lib and set this classloader configuration
+ ! http://camel.apache.org/camel-jboss.html
+ ! <bean id="jbossResolver" class="org.apache.camel.jboss.JBossPackageScanClassResolver"/>
+ -->
+
+ <!--
! Define the server end point.
! Copy and paste this element, changing id and the address, to expose services on different urls.
! Different Camel routes can handle different end point paths.
- -->
+ -->
<cxf:rsServer id="rsServer"
address="/kservice/rest"
serviceClass="org.drools.jax.rs.CommandExecutorImpl">
@@ -154,5 +213,90 @@
<para>Both parameters are configured in knowledge-services.xml
file.</para>
</section>
+
+ <section>
+ <title>Knowledge Services configuration</title>
+
+ <para>The next step is create the Knowledge Sessions that you are going
+ to use.</para>
+
+ <programlisting><beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:drools="http://drools.org/schema/drools-spring"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
+ http://drools.org/schema/drools-spring http://drools.org/schema/drools-spring.xsd">
+
+ <drools:execution-node id="node1" />
+
+ <drools:kbase id="kbase1" node="node1">
+ <drools:resources>
+ <drools:resource type="XSD" source="classpath:model.xsd"/>
+ <drools:resource type="DRL" source="classpath:test.drl"/>
+ </drools:resources>
+ </drools:kbase>
+
+ <drools:ksession id="ksession1" type="stateless" kbase="kbase1" node="node1"/>
+</beans>
+</programlisting>
+
+ <para>The execution-node is a context or registered kbases and
+ ksessions, here kbase1 and ksession1 are planed in the node1 context.
+ The kbase itself concists of tow knoeldge defiitions, a drl and an xsd.
+ The Spring documentaiton contains a lot more information on configuring
+ these knowledge services.</para>
+
+ <para></para>
+ </section>
+
+ <section>
+ <title>Test</title>
+
+ <para>With drools-server war unzipped you should be able to see a
+ test.jsp and run it. This example just executes a simple "echo" type
+ application. It sends a message to the rule server that pre-appends the
+ word "echo" to the front and sends it back. By default the message is
+ "Hello World", different messages can be passed using the url parameter
+ msg - test.jsp?msg="My Custom Message".</para>
+
+ <para>Under the hood the jsp invokes the Test.java class, this then
+ calls out to Camel which is where the meet happens. The camel-client.xml
+ defines the client with just a few lines of xml:</para>
+
+ <programlisting><camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="direct://kservice"/>
+ <policy ref="droolsPolicy">
+ <to uri="cxfrs://http://localhost:8080/drools-server-app/kservice/rest"/>
+ </policy>
+ </route>
+ </camelContext>
+</programlisting>
+
+ <para>"direct://kservice" is just a named hook, allowing java to grab a
+ reference and push data into it. In this example the data is already in
+ xml, so we don't need to add any DataFormat's to do the marshalling. The
+ DroolsPolicy adds some smarts to the route and you'll see it used on the
+ server side too. If JAXB or XStream were used, it would inject custom
+ paths and converters, it can also set the classloader too on the server
+ side, on the client side it automatically unwrapes the Response
+ object.</para>
+
+ <para>The rule itself can be found here: test.drl. Notice the type
+ Message is declared part of the drl and is thus not present on the
+ Classpath.</para>
+
+ <programlisting>declare Message
+ text : String
+end
+
+
+rule "echo" dialect "mvel"
+when
+ $m : Message();
+then
+ $m.text = "echo:" + $m.text;
+end
+</programlisting>
+ </section>
</section>
</section>
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-integration/src/main/docbook/en-US/Chapter-Spring/Chapter-Spring.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-integration/src/main/docbook/en-US/Chapter-Spring/Chapter-Spring.xml 2010-07-30 04:43:05 UTC (rev 34398)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-integration/src/main/docbook/en-US/Chapter-Spring/Chapter-Spring.xml 2010-07-30 05:25:59 UTC (rev 34399)
@@ -240,7 +240,7 @@
</listitem>
<listitem>
- <para>multithread </para>
+ <para>multithread</para>
<itemizedlist>
<listitem>
@@ -314,7 +314,7 @@
</listitem>
<listitem>
- <para>assert-behavior </para>
+ <para>assert-behavior</para>
<itemizedlist>
<listitem>
@@ -394,10 +394,23 @@
<drools:ksession id="ksession2" type="stateful" kbase="kbase1"/>
<drools:ksession id="ksession3" type="stateful" kbase="kbase2>
+
+ <drools:batch>
+ <drools:insert-object ref="person" />
+
+ <drools:set-global identifier="list1">
+ <bean class="java.util.ArrayList" />
+ </drools:set-global>
+
+ <drools:startProcess process-id="start fire">
+
+ </drools:batch>
+
<drools:configurations>
<drools:keep-reference enabled="false" />
<drools:clock-type type="PSEUDO" />
</drools:configurations>
+
</drools:ksession>
</programlisting>
</example>
@@ -468,6 +481,102 @@
</itemizedlist>
</figure>
+ <figure>
+ <title>Initialization Batch Commands</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>insert-object</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>ref = String (optional)</para>
+ </listitem>
+
+ <listitem>
+ <para>Anonymous bean</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>set-global</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>identifier = String (required)</para>
+ </listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <listitem>
+ <para>reg = String (optiona)</para>
+ </listitem>
+
+ <listitem>
+ <para>Anonymous bean</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>fire-all-rules</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>max : n</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>fire-until-halt</para>
+ </listitem>
+
+ <listitem>
+ <para>start-process</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>parameter</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>identifier = String (required)</para>
+ </listitem>
+
+ <listitem>
+ <para>ref = String (optional)</para>
+ </listitem>
+
+ <listitem>
+ <para>Anonymous bean</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>signal-event</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>ref = String (optional)</para>
+ </listitem>
+
+ <listitem>
+ <para>event-type = String (required)</para>
+ </listitem>
+
+ <listitem>
+ <para>process-instance-id =n (optional)</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </figure>
+
<example>
<title>ksession JPA configuraiton example</title>
More information about the jboss-svn-commits
mailing list