1.1. Introduction

It's been a busy year since the last 5.x series release and so much has change.

One of the biggest complaints during the 5.x series was the lack of defined methodology for
deployment. The mechanism used by Drools and jBPM was very flexible, but it was too flexible.
A big focus for 6.0 was streamlining the build, deploy and loading(utilization) aspects of the
system. Building and deploying now align with Maven and the utilization is now convention and
configuration oriented, instead of programmatic, with sane default to minimise the
configuration.

The workbench has been rebuilt from the ground up, inspired by Eclipse, to provide a
flexible and better integrated solution; with panels and perspectives via plugins. The base
workbench has been spun off into a standalone project called UberFire, so that anyone now can
build high quality web based workbenches. In the longer term it will facilitate user
customised Drools and jBPM installations.

Git replaces JCR as the content repository, offering a fast and scalable back-end storage
for content that has strong tooling support. There has been a refocus on simplicity away from
databases with an aim of storing everythign as as text file, even meta data is just a file.
The database is just there to provide fast indexing and search via Lucene. This will allow
repositories now to be synced and published with estbalished infrastructure, like
GitHub.

jBPM has been dramatically beefed up, thanks to the Polymita acquisition, with human
tasks, form builders, class modellers, execution servers and runtime management. All fully
integrated into the new workbench.

OptaPlanner is now a top level project and getting full time attention.

A new umbrella name, KIE (Knowledge Is Everything), has been introduced to bring our related technologies
together under one roof. It also acts as the core shared around for our projects. So expect to see it a
lot.

1.2. Getting Involved

We are often asked "How do I get involved". Luckily the answer is
simple, just write some code and submit it :) There are no hoops you have to
jump through or secret handshakes. We have a very minimal "overhead" that we
do request to allow for scalable project development. Below we provide a
general overview of the tools and "workflow" we request, along with some
general advice.

If you contribute some good work, don't forget to blog about it
:)

1.2.1. Sign up to jboss.org

Signing to jboss.org will give you access to the JBoss wiki, forums and JIRA. Go to
http://www.jboss.org/ and click "Register".

1.2.2. Sign the Contributor Agreement

The only form you need to sign is the contributor agreement, which
is fully automated via the web. As the image below says "This establishes
the terms and conditions for your contributions and ensures that source
code can be licensed appropriately"

1.2.3. Submitting issues via JIRA

To be able to interact with the core development team you will need
to use JIRA, the issue tracker. This ensures that all requests are logged
and allocated to a release schedule and all discussions captured in one
place. Bug reports, bug fixes, feature requests and feature submissions
should all go here. General questions should be undertaken at the mailing
lists.

Minor code submissions, like format or documentation fixes do not
need an associated JIRA issue created.

1.2.4. Fork GitHub

With the contributor agreement signed and your requests submitted to
JIRA you should now be ready to code :) Create a GitHub account and fork
any of the Drools, jBPM or Guvnor repositories. The fork will create a copy
in your own GitHub space which you can work on at your own pace. If you
make a mistake, don't worry blow it away and fork again. Note each GitHub
repository provides you the clone (checkout) URL, GitHub will provide you
URLs specific to your fork.

1.2.5. Writing Tests

When writing tests, try and keep them minimal and self contained. We
prefer to keep the DRL fragments within the test, as it makes for quicker
reviewing. If their are a large number of rules then using a String is not
practical so then by all means place them in separate DRL files instead to
be loaded from the classpath. If your tests need to use a model, please
try to use those that already exist for other unit tests; such as Person,
Cheese or Order. If no classes exist that have the fields you need, try
and update fields of existing classes before adding a new class.

There are a vast number of tests to look over to get an idea,
MiscTest is a good place to start.

1.2.6. Commit with Correct Conventions

When you commit, make sure you use the correct conventions. The
commit must start with the JIRA issue id, such as JBRULES-220. This
ensures the commits are cross referenced via JIRA, so we can see all
commits for a given issue in the same place. After the id the title of the
issue should come next. Then use a newline, indented with a dash, to
provide additional information related to this commit. Use an additional
new line and dash for each separate point you wish to make. You may add
additional JIRA cross references to the same commit, if it's appropriate.
In general try to avoid combining unrelated issues in the same
commit.

Don't forget to rebase your local fork from the original master and
then push your commits back to your fork.

1.2.7. Submit Pull Requests

With your code rebased from original master and pushed to your
personal GitHub area, you can now submit your work as a pull request. If
you look at the top of the page in GitHub for your work area their will be
a "Pull Request" button. Selecting this will then provide a gui to
automate the submission of your pull request.

The pull request then goes into a queue for everyone to see and
comment on. Below you can see a typical pull request. The pull requests
allow for discussions and it shows all associated commits and the diffs
for each commit. The discussions typically involve code reviews which
provide helpful suggestions for improvements, and allows for us to leave
inline comments on specific parts of the code. Don't be disheartened if we
don't merge straight away, it can often take several revisions before we
accept a pull request. Luckily GitHub makes it very trivial to go back to
your code, do some more commits and then update your pull request to your
latest and greatest.

It can take time for us to get round to responding to pull requests,
so please be patient. Submitted tests that come with a fix will generally
be applied quite quickly, where as just tests will often way until we get
time to also submit that with a fix. Don't forget to rebase and resubmit
your request from time to time, otherwise over time it will have merge
conflicts and core developers will general ignore those.

1.3. Installation and Setup (Core and IDE)

1.3.1. Installing and using

Drools provides an Eclipse-based IDE (which is optional), but at its core only Java 1.5 (Java SE) is
required.

A simple way to get started is to download and install the Eclipse plug-in - this will also require the Eclipse
GEF framework to be installed (see below, if you don't have it installed already). This will provide you with all the
dependencies you need to get going: you can simply create a new rule project and everything will be done for you.
Refer to the chapter on the Rule Workbench and IDE for detailed instructions on this. Installing the Eclipse plug-in
is generally as simple as unzipping a file into your Eclipse plug-in directory.

Use of the Eclipse plug-in is not required. Rule files are just textual input (or spreadsheets as the case may
be) and the IDE (also known as the Rule Workbench) is just a convenience. People have integrated the rule engine in
many ways, there is no "one size fits all".

Alternatively, you can download the binary distribution, and include the relevant JARs in your projects
classpath.

1.3.1.1. Dependencies and JARs

Drools is broken down into a few modules, some are required during rule development/compiling, and some are
required at runtime. In many cases, people will simply want to include all the dependencies at runtime, and this is
fine. It allows you to have the most flexibility. However, some may prefer to have their "runtime" stripped down to
the bare minimum, as they will be deploying rules in binary form - this is also possible. The core runtime engine
can be quite compact, and only requires a few 100 kilobytes across 3 JAR files.

The following is a description of the important libraries that make up JBoss Drools

knowledge-api.jar - this provides the interfaces and factories. It also helps clearly show what is
intended as a user API and what is just an engine API.

drools-core.jar - this is the core engine, runtime component. Contains both the RETE engine and the LEAPS
engine. This is the only runtime dependency if you are pre-compiling rules (and deploying via Package or
RuleBase objects).

drools-compiler.jar - this contains the compiler/builder components to take rule source, and build
executable rule bases. This is often a runtime dependency of your application, but it need not be if you are
pre-compiling your rules. This depends on drools-core.

drools-jsr94.jar - this is the JSR-94 compliant implementation, this is essentially a layer over the
drools-compiler component. Note that due to the nature of the JSR-94 specification, not all features are easily
exposed via this interface. In some cases, it will be easier to go direct to the Drools API, but in some
environments the JSR-94 is mandated.

drools-decisiontables.jar - this is the decision tables 'compiler' component, which uses the
drools-compiler component. This supports both excel and CSV input formats.

There are quite a few other dependencies which the above components require, most of which are for the
drools-compiler, drools-jsr94 or drools-decisiontables module. Some key ones to note are "POI" which provides the
spreadsheet parsing ability, and "antlr" which provides the parsing for the rule language itself.

NOTE: if you are using Drools in J2EE or servlet containers and you come across classpath issues with "JDT",
then you can switch to the janino compiler. Set the system property "drools.compiler": For example:
-Ddrools.compiler=JANINO.

For up to date info on dependencies in a release, consult the released POMs, which can be found on the Maven
repository.

This is similar for Gradle, Ivy and Buildr. To identify the latest version, check the Maven repository.

If you're still using Ant (without Ivy), copy all the JARs from the download zip's
binaries directory and manually verify that your classpath doesn't contain duplicate
JARs.

1.3.1.3. Runtime

The "runtime" requirements mentioned here are if you are deploying rules as their binary form (either as
KnowledgePackage objects, or KnowledgeBase objects etc). This is an optional feature that allows you to keep your
runtime very light. You may use drools-compiler to produce rule packages "out of process", and then deploy them to a
runtime system. This runtime system only requires drools-core.jar and knowledge-api for execution. This is an optional
deployment pattern, and many people do not need to "trim" their application this much, but it is an ideal option for
certain environments.

1.3.1.4. Installing IDE (Rule Workbench)

The rule workbench (for Eclipse) requires that you have Eclipse 3.4 or greater, as well as Eclipse GEF 3.4 or
greater. You can install it either by downloading the plug-in or, or using the update site.

Another option is to use the JBoss IDE, which comes with all the plug-in requirements pre packaged, as well as
a choice of other tools separate to rules. You can choose just to install rules from the "bundle" that JBoss IDE
ships with.

1.3.1.4.1. Installing GEF (a required dependency)

GEF is the Eclipse Graphical Editing Framework, which is used for graph viewing components in the
plug-in.

If you don't have GEF installed, you can install it using the built in update mechanism (or downloading GEF
from the Eclipse.org website not recommended). JBoss IDE has GEF already, as do many other "distributions" of
Eclipse, so this step may be redundant for some people.

Open the Help->Software updates...->Available Software->Add Site... from the help menu. Location
is:

http://download.eclipse.org/tools/gef/updates/releases/

Next you choose the GEF plug-in:

Press next, and agree to install the plug-in (an Eclipse restart may be required). Once this is completed,
then you can continue on installing the rules plug-in.

1.3.1.4.2. Installing GEF from zip file

To install from the zip file, download and unzip the file. Inside the zip you will see a plug-in directory,
and the plug-in JAR itself. You place the plug-in JAR into your Eclipse applications plug-in directory, and
restart Eclipse.

1.3.1.4.3. Installing Drools plug-in from zip file

Download the Drools Eclipse IDE plugin from the link below. Unzip the downloaded file in your main eclipse
folder (do not just copy the file there, extract it so that the feature and plugin JARs end up in the features and
plugin directory of eclipse) and (re)start Eclipse.

To check that the installation was successful, try opening the Drools perspective: Click the 'Open
Perspective' button in the top right corner of your Eclipse window, select 'Other...' and pick the Drools
perspective. If you cannot find the Drools perspective as one of the possible perspectives, the installation
probably was unsuccessful. Check whether you executed each of the required steps correctly: Do you have the right
version of Eclipse (3.4.x)? Do you have Eclipse GEF installed (check whether the org.eclipse.gef_3.4.*.jar exists
in the plugins directory in your eclipse root folder)? Did you extract the Drools Eclipse plugin correctly (check
whether the org.drools.eclipse_*.jar exists in the plugins directory in your eclipse root folder)? If you cannot
find the problem, try contacting us (e.g. on irc or on the user mailing list), more info can be found no our
homepage here:

1.3.1.4.4. Drools Runtimes

A Drools runtime is a collection of JARs on your file system that represent one specific release of the
Drools project JARs. To create a runtime, you must point the IDE to the release of your choice. If you want to
create a new runtime based on the latest Drools project JARs included in the plugin itself, you can also easily do
that. You are required to specify a default Drools runtime for your Eclipse workspace, but each individual project
can override the default and select the appropriate runtime for that project specifically.

1.3.1.4.4.1. Defining a Drools runtime

You are required to define one or more Drools runtimes using the Eclipse preferences view. To open up your
preferences, in the menu Window select the Preferences menu item. A new preferences dialog should show all your
preferences. On the left side of this dialog, under the Drools category, select "Installed Drools runtimes". The
panel on the right should then show the currently defined Drools runtimes. If you have not yet defined any
runtimes, it should like something like the figure below.

To define a new Drools runtime, click on the add button. A dialog as shown below should pop up, requiring
the name for your runtime and the location on your file system where it can be found.

In general, you have two options:

If you simply want to use the default JARs as included in the Drools Eclipse plugin, you can create a
new Drools runtime automatically by clicking the "Create a new Drools 5 runtime ..." button. A file browser
will show up, asking you to select the folder on your file system where you want this runtime to be created.
The plugin will then automatically copy all required dependencies to the specified folder. After selecting
this folder, the dialog should look like the figure shown below.

If you want to use one specific release of the Drools project, you should create a folder on your file
system that contains all the necessary Drools libraries and dependencies. Instead of creating a new Drools
runtime as explained above, give your runtime a name and select the location of this folder containing all
the required JARs.

After clicking the OK button, the runtime should show up in your table of installed Drools runtimes, as
shown below. Click on checkbox in front of the newly created runtime to make it the default Drools runtime. The
default Drools runtime will be used as the runtime of all your Drools project that have not selected a
project-specific runtime.

You can add as many Drools runtimes as you need. For example, the screenshot below shows a configuration
where three runtimes have been defined: a Drools 4.0.7 runtime, a Drools 5.0.0 runtime and a Drools
5.0.0.SNAPSHOT runtime. The Drools 5.0.0 runtime is selected as the default one.

Note that you will need to restart Eclipse if you changed the default runtime and you want to make sure
that all the projects that are using the default runtime update their classpath accordingly.

1.3.1.4.4.2. Selecting a runtime for your Drools project

Whenever you create a Drools project (using the New Drools Project wizard or by converting an existing
Java project to a Drools project using the "Convert to Drools Project" action that is shown when you are in the
Drools perspective and you right-click an existing Java project), the plugin will automatically add all the
required JARs to the classpath of your project.

When creating a new Drools project, the plugin will automatically use the default Drools runtime for that
project, unless you specify a project-specific one. You can do this in the final step of the New Drools Project
wizard, as shown below, by deselecting the "Use default Drools runtime" checkbox and selecting the appropriate
runtime in the drop-down box. If you click the "Configure workspace settings ..." link, the workspace
preferences showing the currently installed Drools runtimes will be opened, so you can add new runtimes
there.

You can change the runtime of a Drools project at any time by opening the project properties (right-click
the project and select Properties) and selecting the Drools category, as shown below. Check the "Enable project
specific settings" checkbox and select the appropriate runtime from the drop-down box. If you click the
"Configure workspace settings ..." link, the workspace preferences showing the currently installed Drools
runtimes will be opened, so you can add new runtimes there. If you deselect the "Enable project specific
settings" checkbox, it will use the default runtime as defined in your global preferences.

1.3.2. Building from source

1.3.2.1. Getting the sources

The source code of each Maven artifact is available in the JBoss Maven repository as a source JAR. The same
source JARs are also included in the download zips. However, if you want to build from source, it's highly
recommended to get our sources from our source control.

Drools and jBPM use Git for source control. The blessed git
repositories are hosted on GitHub:

Git allows you to fork our code, independently make personal changes on it, yet still merge in our latest
changes regularly and optionally share your changes with us. To learn more about git, read the free book Git Pro.

1.3.2.2. Building the sources

In essense, building from source is very easy, for example if you want to build the
guvnor project:

1.3.3. Eclipse

1.3.3.1. Importing Eclipse Projects

With the Eclipse project files generated they can now be imported into Eclipse. When starting Eclipse open the
workspace in the root of your subversion checkout.

When calling mvn install all the project dependencies were downloaded and added to the
local Maven repository. Eclipse cannot find those dependencies unless you tell it where that repository is. To do
this setup an M2_REPO classpath variable.

2.1. New and Noteworthy in KIE API 6.0.0

2.1.1. New KIE name

KIE is the new umbrella name used to group together our related projects; as the family continues to grow. KIE
is also used for the generic parts of unified API; such as building, deploying and loading. This replaces the
droolsjbpm and knowledge keywords that would have been used before.

Figure 2.1. KIE Anatomy

2.1.2. Maven aligned projects and modules and Maven Deployment

One of the biggest complaints during the 5.x series was the lack of defined methodology for deployment. The
mechanism used by Drools and jBPM was very flexible, but it was too flexible. A big focus for 6.0 was streamlining
the build, deploy and loading (utilization) aspects of the system. Building and deploying activities are now aligned
with Maven and Maven repositories. The utilization for loading rules and processess is now convention and configuration oriented,
instead of programmatic, with sane defaults to minimise the configuration.

Projects can be built with Maven and installed to the local M2_REPO or remote Maven repositories. Maven is
then used to declare and build the classpath of dependencies, for KIE to access.

2.1.3. Configuration and convention based projects

The 'kmodule.xml' provides declarative configuration for KIE projects. Conventions and defaults are used to
reduce the amount of configuration needed.

2.1.4. KieBase Inclusion

It is possible to include all the KIE artifacts belonging to a KieBase into a second KieBase. This means that
the second KieBase, in addition to all the rules, function and processes directly defined into it, will also contain the
ones created in the included KieBase. This inclusion can be done declaratively in the kmodule.xml file

2.1.5. KieModules, KieContainer and KIE-CI

Any Maven produced JAR with a 'kmodule.xml' in it is considered a KieModule. This can be loaded from the
classpath or dynamically at runtime from a Resource location. If the kie-ci dependency is on the classpath it
embeds Maven and all resolving is done automatically using Maven and can access local or remote repositories.
Settings.xml is obeyed for Maven configuration.

The KieContainer provides a runtime to utilize the KieModule, versioning is built in throughout, via Maven.
Kie-ci will create a classpath dynamically from all the Maven declared dependencies for the artifact being loaded.
Maven LATEST, SNAPSHOT, RELEASE and version ranges are supported.

2.1.6. KieScanner

The KieScanner is a Maven-oriented replacement of the KnowledgeAgent
present in Drools 5. It continuously monitors your Maven repository
to check if a new release of a Kie project has been installed and if so, deploys it in
the KieContainer wrapping that project. The use of the KieScanner
requires kie-ci.jar to be on the classpath.

A KieScanner can be registered on a KieContainer
as in the following example.

In this example the KieScanner is configured to run with a fixed
time interval, but it is also possible to run it on demand by invoking the
scanNow() method on it. If the KieScanner finds, in the
Maven repository, an updated version of the Kie project used by that KieContainer
it automatically downloads the new version and triggers an incremental build of the new
project. From this moment all the new KieBases and KieSessions
created from that KieContainer will use the new project version.

2.1.7. Hierarchical ClassLoader

The CompositeClassLoader is no longer used; as it was a constant source of performance problems and bugs.
Traditional hierarchical classloaders are now used. The root classloader is at the KieContext level, with
one child ClassLoader per namespace. This makes it cleaner to add and remove rules, but there can now be no
referencing between namespaces in DRL files; i.e. functions can only be used by the namespaces that declared them.
The recommendation is to use static Java methods in your project, which is visible to all namespaces; but those
cannot (like other classes on the root KieContainer ClassLoader) be dynamically updated.

2.1.8. Legacy API Adapter

The 5.x API for building and running with Drools and jBPM is still available through Maven dependency
"knowledge-api-legacy5-adapter". Because the nature of deployment has significantly changed in 6.0, it was not
possible to provide an adapter bridge for the KnowledgeAgent. If any other methods are missing or problematic,
please open a JIRA, and we'll fix for 6.1

2.1.9. KIE Documentation

While a lot of new documentation has been added for working with the new KIE API, the entire documentation
has not yet been brought up to date. For this reason there will be continued references to old terminologies.
Apologies in advance, and thank you for your patience. We hope those in the community will work with us to get the
documentation updated throughout, for 6.1

2.2. What is New and Noteworthy in Drools 6.0.0

2.2.1. PHREAK - Lazy rule matching algorithm

The main work done for Drools in 6.0 involves the new PREAK algorithm. This is a lazy algorithm that should
enable Drools to handle a larger number of rules and facts. AngendaGroups can now help improvement performance, as
rules are not evaluated until it attempts to fire them.

Sequential mode continues to be supported for PHREAK but now 'modify' is allowed. While there is no
'inference' with sequential configuration, as rules are lazily evaluated, any rule not yet evaluated will see the
more recent data as a result of 'modify'. This is more inline with how people intuitively think sequential
works.

The conflict resolution order has been tweaked for PHREAK, and now is ordered by salience and then rule order;
based on the rule position in the file.. Prior to Drools 6.0.0, after salience, it was considered arbitrary. When
KieModules and updateToVersion are used for dynamic deployment, the rule order in the file is preserved via the
diff processing.

2.2.2. Automatically firing timed rule in passive mode

When the rule engine runs in passive mode (i.e.: using fireAllRules)
by default it doesn't fire consequences of timed rules unless fireAllRules isn't invoked again.
Now it is possible to change this default behavior by configuring the KieSession
with a TimedRuleExectionOption as shown in the following example.

It is also possible to have a finer grained control on the timed rules that have to be
automatically executed. To do this it is necessary to set a FILTEREDTimedRuleExectionOption that allows to define a callback to filter those
rules, as done in the next example.

Example 2.9. Configuring a filter to choose which timed rules should be automatically executed

2.2.3. Expression Timers

It is now possible to define both the delay and interval of an interval timer
as an expression instead of a fixed value. To do that it is necessary to declare
the timer as an expression one (indicated by "expr:") as in the following example:

The expressions, $d and $p in this case, can use any variable defined in the
pattern matching part of the rule and can be any String that can be parsed in a time
duration or any numeric value that will be internally converted in a long representing
a duration expressed in milliseconds.

Both interval and expression timers can have 3 optional parameters named
"start", "end" and "repeat-limit". When one or more of these parameters are used the first
part of the timer definition must be followed by a semicolon ';' and the parameters have
to be separated by a comma ',' as in the following example:

Example 2.11. An Interval Timer with a start and an end

timer (int:30s 10s; start=3-JAN-2010, end=5-JAN-2010)

The value for start and end parameters can be a Date, a String representing
a Date or a long, or more in general any Number, that will be transformed in a Java Date
applying the following conversion:

newDate(((Number) n).longValue())

Conversely the repeat-limit can be only an integer and it defines the maximum
number of repetitions allowed by the timer. If both the end and the repeat-limit parameters
are set the timer will stop when the first of the two will be matched.

The using of the start parameter implies the definition of a phase for the timer,
where the beginning of the phase is given by the start itself plus the eventual delay.
In other words in this case the timed rule will then be scheduled at times:

start + delay + n*period

for up to repeat-limit times and no later than the end timestamp (whichever first).
For instance the rule having the following interval timer

timer (int:30s 1m; start="3-JAN-2010")

will be scheduled at the 30th second of every minute after the midnight of the
3-JAN-2010. This also means that if for example you turn the system on at midnight of
the 3-FEB-2010 it won't be scheduled immediately but will preserve the phase defined by
the timer and so it will be scheduled for the first time 30 seconds after the midnight.
If for some reason the system is paused (e.g. the session is serialized and then deserialized
after a while) the rule will be scheduled only once to recover from missing activations
(regardless of how many activations we missed) and subsequently it will be scheduled
again in phase with the timer.

2.2.4. RuleFowGroup and AgendaGroups are merged

These two groups have been merged and now RuleFlowGroup's behave the same as AgendaGroups. The get methods
have been left, for deprecation reasons, but both return the same underlying data. When jBPM activates a group it
now just calls setFocus. RuleFlowGroups and AgendaGroups when used together was a continued source of errors. It
also aligns the codebase, towards PHREAK and the multi-core explotation that is planned in the future.

2.3. New and Noteworthy in KIE Workbench 6.0.0

The workbench has had a big overhaul using a new base project called UberFire. UberFire is inspired by Eclipse
and provides a clean, extensible and flexible framework for the workbench. The end result is not only a richer
experience for our end users, but we can now develop more rapidly with a clean component based architecture. If you
like he Workbench experience you can use UberFire today to build your own web based dashboard and console
efforts.

As well as the move to a UberFire the other biggest change is the move from JCR to Git; there is an utility
project to help with migration. Git is the most scalable and powerful source repository bar none. JGit provides a
solid OSS implementation for Git. This addresses the continued performance problems with the various JCR
implementations, which would slow down once the number of files and number of versions become too high. There has
been a big "low tech" drive, to remove complexity. Everything is now stored as a file, including meta data. The
database is only there to provide fast indexing and search. So importing and exporting is all standard Git and
external sites, like GitHub, can be used to exchange repositories.

In 5.x developers would work with their own source repository and then push JCR, via the team provider. This
team provider was not full featured and not available outside Eclipse. Git enables our repository to work any
existing Git tool or team provider. While not yet supported in the UI, this will be added over time, it is possible
to connect to the repo and tag and branch and restore things.

Figure 2.2. Workbench

The Guvnor brand leaked too much from its intended role; such as the authoring metaphors, like Decision Tables,
being considered Guvnor components instead of Drools components. This wasn't helped by the monolithic projects
structure used in 5.x for Guvnor. In 6.0 Guvnor 's focus has been narrowed to encapsulates the set of UberFire
plugins that provide the basis for building a web based IDE. Such as Maven integration for building and deploying,
management of Maven repositories and activity notifications via inboxes. Drools and jBPM build workbench
distributions using Uberfire as the base and including a set of plugins, such as Guvnor, along with their own
plugins for things like decision tables, guided editors, BPMN2 designer, human tasks.

The "Model Structure" diagram outlines the new project anatomy. The Drools workbench is called KIE-Drools-WB.
KIE-WB is the uber workbench that combines all the Guvnor, Drools and jBPM plugins. The jBPM-WB is ghosted out, as
it doesn't actually exist, being made redundant by KIE-WB.

Figure 2.3. Module Structure

Important

KIE Drools Workbench and KIE Workbench share a common set of components for generic workbench functionality
such as Project navigation, Project definitions, Maven based Projects, Maven Artifact Repository. These common
features are described in more detail throughout this documentation.

New Data Modeller replaces the declarative Fact Model Editor; bringing authoring of Java classes to the
authoring environment. Java classes are packaged into the project and can be used within rules, processes etc
and externally in your own applications.

Virtual File System replaces JCR with a default Git based implementation.

Default Git based implementation supports remote operations.

External modifications appear within the Workbench.

Incremental Build system showing, near real-time validation results of your project and assets.

The editors themselves are largely unchanged; however of note imports have moved from the package
definition to individual editors so you need only import types used for an asset and not the package as a
whole.

2.4. New and Noteworthy in Integration 6.0.0

2.4.1. CDI

CDI is now tightly integrated into the KIE API. It can be used to inject versioned KieSession and KieBases.

2.4.2. Spring

Spring has been revamped and now integrated with KIE. Spring can replace the 'kmodule.xml' with a more
powerful spring version. The aim is for consistency with kmodule.xml

2.4.3. Aries Blueprints

Aries blueprints is now also supported, and follows the work done for spring. The aim is for consistency with
spring and kmodule.xml

2.4.4. OSGi Ready

All modules have been refactored to avoid package splitting, which was a problem in 5.x.
Testing has been moved to PAX.

2.5. What is New and Noteworthy in Drools 6.1.0

2.5.1. JMX support for KieScanner

Added support for JMX monitoring and management on KieScanner and KieContainer. To enable, set the
property:

KieScannerMBean will register under the name:

It exposes the following properties:

Scanner Release Id: the release ID the scanner was configured with. May
include maven range versions and special keywords like LATEST, SNAPSHOT, etc.

Current Release Id: the actual release ID the artifact resolved
to.

Status: STARTING, SCANNING, UPDATING, RUNNING, STOPPED, SHUTDOWN

It also exposes the following operations:

scanNow(): forces an immediate scan of the maven repository looking for
artifact updates

start(): starts polling the maven repository for artifact updates based
on the polling interval parameter

stop(): stops automatically polling the maven repository

2.6. New and Noteworthy in KIE Workbench 6.1.0

2.6.1. Data Modeler - round trip and source code preservation

Full round trip between Data modeler and Java source code is now supported. No matter
where the Java code was generated (e.g. Eclipse, Data modeller), data modeler will only
update the necessary code blocks to maintain the model updated.

2.6.2. Data Modeler - improved annotations

New annotations @TypeSafe, @ClassReactive, @PropertyReactive, @Timestamp, @Duration and
@Expires were added in order enrich current Drools annotations manged by the data
modeler.

2.6.3. Standardization of the display of tabular data

We have standardized the display of tabular data with a new table widget.

The new table supports the following features:

Selection of visible columns

Resizable columns

Moveable columns

Figure 2.6. New table

The table is used in the following scenarios:

Inbox (Incoming changes)

Inbox (Recently edited)

Inbox (Recently opened)

Project Problems summary

Artifact Repository browser

Project Editor Dependency grid

Project Editor KSession grid

Project Editor Work Item Handlers Configuration grid

Project Editor Listeners Configuration grid

Search Results grid

2.6.4. Generation of modify(x) {...} blocks

Historically these editors supported the older update(x) syntax and hence
rules created within the Workbench would not respond correctly to
@PropertyReactive and associated annotations within a model. This has now been
rectified with the use of modify(x){...} blocks.

Chapter 3. Compatibility matrix

Starting from KIE 6.0, Drools (including workbench), jBPM (including designer and console)
and OptaPlanner follow the same version numbering.

Part II. KIE

KIE is the shared core for Drools and jBPM.It provides a unified methodology and programming model for
building, deploying and utilizing resources.

4.1. Overview

4.1.1. Anatomy of Projects

The process of researching an integration knowledge solution for Drools and jBPM has simply
used the "droolsjbpm" group name. This name permeates GitHub accounts and Maven POMs. As
scopes broadened and new projects were spun KIE, an acronym for Knowledge Is Everything, was
chosen as the new group name. The KIE name is also used for the shared aspects of the system;
such as the unified build, deploy and utilization.

KIE currently consists of the following subprojects:

Figure 4.1. KIE Anatomy

OptaPlanner, a local search and optimization tool, has been spun off from Drools Planner and
is now a top level project with Drools and jBPM. This was a natural evolution as Optaplanner,
while having strong Drools integration, has long been independant of Drools.

From the Polymita acquisition, along with other things, comes the powerful Dashboard Builder
which provides powerful reporting capabities. Dashboard Builder is currently a temporary name
and after the 6.0 release a new name will be chosen. Dashboard Builder is completely
independant of Drools and jBPM and will be used by many projects at JBoss, and hopefully
outside of JBoss :)

UberFire is the new base workbench project, spun off from the ground up rewrite. UberFire
provides Eclipse-like workbench capabilities, with panels and perspectives from plugins. The
project is independant of Drools and jBPM and anyone can use it as a basis of building
flexible and powerful workbenches. UberFire will be used for console and workbench development
throughout JBoss.

It was determined that the Guvnor brand leaked too much from its intended role; such as the authoring
metaphors, like Decision Tables, being considered Guvnor components instead of Drools components. This wasn't
helped by the monolithic projects structure used in 5.x for Guvnor. In 6.0 Guvnor's focus has been narrowed to
encapsulate the set of UberFire plugins that provide the basis for building a web based IDE. Such as Maven
integration for building and deploying, management of Maven repositories and activity notifications via inboxes.
Drools and jBPM build workbench distributions using Uberfire as the base and including a set of plugins, such as
Guvnor, along with their own plugins for things like decision tables, guided editors, BPMN2 designer, human tasks.
The Drools workbench is called Drools-WB. KIE-WB is the uber workbench that combined all the Guvnor, Drools and jBPM
plugins. The jBPM-WB is ghosted out, as it doesn't actually exist, being made redundant by KIE-WB.

4.1.2. Lifecycles

The different aspects, or life cycles, of working with KIE system, whether it's Drools or
jBPM, can typically be broken down into the following:

Deploys the unit to a location where applications may utilize (consume)
them.

KIE uses Maven style repository.

Utilize

The loading of a JAR to provide a KIE session (KieSession), for which the
application can interact with.

KIE exposes the JAR at runtime via a KIE container (KieContainer).

KieSessions, for the runtime's to interact with, are created from the
KieContainer.

Run

System interaction with the KieSession, via API.

Work

User interaction with the KieSession, via command line or UI.

Manage

Manage any KieSession or KieContainer.

4.2. Build, Deploy, Utilize and Run

4.2.1. Introduction

6.0 introduces a new configuration and convention approach to building knowledge bases,
instead of using the programmatic builder approach in 5.x. The builder is still
available to fall back on, as it's used for the tooling integration.

Building now uses Maven, and aligns with Maven practices. A KIE project or module is simply
a Maven Java project or module; with an additional metadata file META-INF/kmodule.xml. The
kmodule.xml file is the descriptor that selects resources to knowledge bases and configures
those knowledge bases and sessions. There is also alternative XML support via Spring and OSGi
BluePrints.

While standard Maven can build and package KIE resources, it will not provide validation at
build time. There is a Maven plugin which is recommended to use to get build time validation. The
plugin also generates many classes, making the runtime loading faster too.

The example project layout and Maven POM descriptor is illustrated in the screenshot

Figure 4.2. Example project layout and Maven POM

KIE uses defaults to minimise the amount of configuration. With an empty kmodule.xml being
the simplest configuration. There must always be a kmodule.xml file, even if empty, as it's used
for discovery of the JAR and its contents.

Maven can either 'mvn install' to deploy a KieModule to the local machine, where all other
applications on the local machine use it. Or it can 'mvn deploy' to push the KieModule to a
remote Maven repository. Building the Application will pull in the KieModule and populate the
local Maven repository in the process.

Figure 4.3. Example project layout and Maven POM

JARs can be deployed in one of two ways. Either added to the classpath, like any other JAR
in a Maven dependency listing, or they can be dynamically loaded at runtime. KIE will scan the
classpath to find all the JARs with a kmodule.xml in it. Each found JAR is represented by the
KieModule interface. The terms classpath KieModule and dynamic KieModule are used to refer to the
two loading approaches. While dynamic modules supports side by side versioning, classpath
modules do not. Further once a module is on the classpath, no other version may be loaded
dynamically.

Detailed references for the API are included in the next sections, the impatient can jump
straight to the examples section, which is fairly self-explanatory on the different use cases.

4.2.2. Building

Figure 4.4. org.kie.api.core.builder

4.2.2.1. Creating and building a Kie Project

A Kie Project has the structure of a normal Maven project with the only peculiarity
of including a kmodule.xml file defining in a declaratively way the KieBases
and KieSessions that can be created from it. This file has to be placed in the
resources/META-INF folder of the Maven project while all the other Kie artifacts, such as
DRL or a Excel files, must be stored in the resources folder or in any other subfolder under it.

Since meaningful defaults have been provided for all configuration aspects, the simplest
kmodule.xml file can contain just an empty kmodule tag like the following:

In this way the kmodule will contain one single default KieBase. All Kie
assets stored under the resources folder, or any of its subfolders, will be compiled and added
to it. To trigger the building of these artifacts it is enough to create a
KieContainer for them.

Figure 4.5. KieContainer

For this simple case it is enough to create a KieContainer that reads the
files to be built from the classpath:

KieServices is the interface from where it possible to access all the Kie
building and runtime facilities:

Figure 4.6. KieServices

In this way all the Java sources and the Kie resources are compiled and deployed into
the KieContainer which makes its contents available for use at runtime.

4.2.2.2. The kmodule.xml file

As explained in the former section, the kmodule.xml file is the place where it is possible
to declaratively configure the KieBase(s) and KieSession(s) that can be
created from a KIE project.

In particular a KieBase is a repository of all the application's knowledge definitions.
It will contain rules, processes, functions, and type models. The KieBase itself does not contain
data; instead, sessions are created from the KieBase into which data can be inserted and from
which process instances may be started. Creating the KieBase can be heavy, whereas session
creation is very light, so it is recommended that KieBase be cached where possible to allow
for repeated session creation. However end-users usually shouldn't worry about it, because this caching
mechanism is already automatically provided by the KieContainer.

Figure 4.7. KieBase

Conversely the KieSession stores and executes on the runtime data.
It is created from the KieBase or more easily can be created directly from the
KieContainer if it has been defined in the kmodule.xml file

Figure 4.8. KieSession

The kmodule.xml allows to define and configure one or more KieBases and for each
KieBase all the different KieSessions that can be created from it,
as showed by the follwing example:

Here 2 KieBases have been defined and it is possible to instance 2 different types of
KieSessions from the first one, while only one from the second. A list of the attributes that
can be defined on the kbase tag, together with their meaning and default values follows:

Table 4.1. kbase Attributes

Attribute name

Default value

Admitted values

Meaning

name

none

any

The name with which retrieve this KieBase from the KieContainer.
This is the only mandatory attribute.

includes

none

any comma separated list

A comma separated list of other KieBases contained in this kmodule.
The artifacts of all these KieBases will be also included in this one.

packages

all

any comma separated list

By default all the Drools artifacts under the resources folder,
at any level, are included into the KieBase. This attribute allows to limit
the artifacts that will be compiled in this KieBase to only the ones
belonging to the list of packages.

default

false

true, false

Defines if this KieBase is the default one for this module, so
it can be created from the KieContainer without passing any name to it.
There can be at most one default KieBase in each module.

equalsBehavior

identity

identity, equality

Defines the behavior of Drools when a new fact is inserted into the
Working Memory. With identity it always create a new FactHandle unless the same
object isn't already present in the Working Memory, while with equality only if
the newly inserted object is not equal (according to its equal method) to an already
existing fact.

eventProcessingMode

cloud

cloud, stream

When compiled in cloud mode the KieBase treats events as normal facts, while
in stream mode allow temporal reasoning on them.

declarativeAgenda

disabled

disabled, enabled

Defines if the Declarative Agenda is enabled or not.

Similarly all attributes of the ksession tag (except of course the name)
have meaningful default. They are listed and described in the following table:

Table 4.2. ksession Attributes

Attribute name

Default value

Admitted values

Meaning

name

none

any

Unique name of this KieSession. Used to fetch the KieSession from the KieContainer.
This is the only mandatory attribute.

type

stateful

stateful, stateless

A stateful session allows to iteratively work with the Working Memory,
while a stateless one is a one-off execution of a Working Memory with a provided data set.

default

false

true, false

Defines if this KieSession is the default one for this module, so
it can be created from the KieContainer without passing any name to it.
In each module there can be at most one default KieSession for each type.

clockType

realtime

realtime, pseudo

Defines if events timestamps are determined by the system clock or by
a psuedo clock controlled by the application. This clock is specially useful for
unit testing temporal rules.

beliefSystem

simple

simple, jtms, defeasible

Defines the type of belief system used by the KieSession.

As outlined in the former kmodule.xml sample, it is also possible to declaratively
create on each KieSession a file (or a console) logger, one or more
WorkItemHandlers and some listeners that can be of 3 different types:
ruleRuntimeEventListener, agendaEventListener and processEventListener

Having defined a kmodule.xml like the one in the former sample, it is now possible
to simply retrieve the KieBases and KieSessions from the KieContainer using their names.

It has to be noted that since KSession2_1 and KSession2_2 are of 2 different types
(the first is stateful, while the second is stateless) it is necessary to invoke 2 different methods on the
KieContainer according to their declared type. If the type of the KieSession
requested to the KieContainer doesn't correspond with the one declared in the
kmodule.xml file the KieContainer will throw a RuntimeException.
Also since a KieBase and a KieSession have been flagged as default
is it possible to get them from the KieContainer without passing any name.

Example 4.5. Retriving default KieBases and KieSessions from the KieContainer

Since a Kie project is also a Maven project the groupId, artifactId and version declared
in the pom.xml file are used to generate a ReleaseId that uniquely identifies
this project inside your application. This allows creation of a new KieContainer from the
project by simply passing its ReleaseId to the KieServices.

Example 4.6. Creating a KieContainer of an existing project by ReleaseId

4.2.2.3. Building with Maven

The KIE plugin for Maven ensures that artifact resources are validated and pre-compiled, it is recommended that this is used at all times. To use the plugin simply add it to the build
section of the Maven pom.xml

Building a KIE module without the Maven plugin will copy all the resources, as is, into the resulting JAR.
When that JAR is loaded by the runtime, it will attempt to build all the resources then. If there are compilation
issues it will return a null KieContainer. It also pushes the compilation overhead to the runtime. In general this
is not recommended, and the Maven plugin should always be used.

4.2.2.4. Defining a KieModule programmatically

It is also possible to define the KieBases and KieSessions
belonging to a KieModule programmatically instead of the declarative definition in the
kmodule.xml file. The same programmatic API also allows in explicitly adding the file containing the
Kie artifacts instead of automatically read them from the resources folder of your project.
To do that it is necessary to create a KieFileSystem, a sort of virtual file
system, and add all the resources contained in your project to it.

Figure 4.9. KieFileSystem

Like all other Kie core components you can obtain an instance of the KieFileSystem from
the KieServices. The kmodule.xml configuration file must be added to the filesystem. This is a
mandatory step. Kie also provides a convenient fluent API, implemented by the KieModuleModel,
to programmatically create this file.

Figure 4.10. KieModuleModel

To do this in practice it is necessary to create a KieModuleModel from the
KieServices, configure it with the desired KieBases and
KieSessions, convert it in XML and add the XML to the KieFileSystem.
This process is shown by the following example:

Example 4.8. Creating a kmodule.xml programmatically and adding it to a KieFileSystem

At this point it is also necessary to add to the KieFileSystem, through its
fluent API, all others Kie artifacts composing your project. These artifacts have to be added
in the same position of a corresponding usual Maven project.

This example shows that it is possible to add the Kie artifacts both as plain Strings and
as Resources. In the latter case the Resources can be created by the
KieResources factory, also provided by the KieServices. The
KieResources provides many convenient factory methods to convert an InputStream,
a URL, a File, or a String representing a path of your file
system to a Resource that can be managed by the KieFileSystem.

Figure 4.11. KieResources

Normally the type of a Resource can be inferred from the extension of the name
used to add it to the KieFileSystem. However it also possible to not follow the Kie
conventions about file extensions and explicitly assign a specific ResourceType
to a Resource as shown below:

Add all the resources to the KieFileSystem and build it by passing the KieFileSystem
to a KieBuilder

Figure 4.12. KieBuilder

When the contents of a KieFileSystem are successfully built, the resulting KieModule
is automatically added to the KieRepository.
The KieRepository is a singleton acting as a repository for all the available KieModules.

Figure 4.13. KieRepository

After this it is possible to create through the KieServices a new
KieContainer for that KieModule using its ReleaseId. However,
since in this case the KieFileSystem doesn't contain any pom.xml file (it is possible to
add one using the KieFileSystem.writePomXML method), Kie cannot determine the
ReleaseId of the KieModule and assign to it a default one. This
default ReleaseId can be obtained from the KieRepository and used
to identify the KieModule inside the KieRepository itself.
The following example shows this whole process.

Example 4.11. Building the contents of a KieFileSystem and creating a KieContainer

At this point it is possible to get KieBases and create new KieSessions
from this KieContainer exactly in the same way as in the case of a KieContainer
created directly from the classpath.

It is a best practice to check the compilation results. The KieBuilder
reports compilation results of 3 different severities: ERROR, WARNING and INFO. An ERROR
indicates that the compilation of the project failed and in the case no KieModule is
produced and nothing is added to the KieRepository. WARNING and INFO results
can be ignored, but are available for inspection.

4.2.2.5. Changing the Default Build Result Severity

In some cases, it is possible to change the default severity of a
type of build result. For instance, when a new rule with the same name
of an existing rule is added to a package, the default behavior is to
replace the old rule by the new rule and report it as an INFO. This is
probably ideal for most use cases, but in some deployments the user
might want to prevent the rule update and report it as an error.

Changing the default severity for a result type, configured
like any other option in Drools, can be done by API
calls, system properties or configuration files. As of this version,
Drools supports configurable result severity for rule updates and function
updates. To configure it using system properties or configuration files,
the user has to use the following properties:

4.2.3. Deploying

4.2.3.1. KieBase

The KieBase is a repository of all the application's knowledge definitions. It will contain
rules, processes, functions, and type models. The KieBase itself does not contain data; instead,
sessions are created from the KieBase into which data can be inserted and from which process
instances may be started. The KieBase can be obtained from the KieContainer containing
the KieModule where the KieBase has been defined.

Figure 4.14. KieBase

Sometimes, for instance in a OSGi environment, the KieBase needs to resolve types that are not in
the default class loader. In this case it will be necessary to create a KieBaseConfiguration with an
additional class loader and pass it to KieContainer when creating a new KieBase from
it.

4.2.3.2. KieSessions and KieBase Modifications

KieSessions will be discussed in more detail in
section "Running". The KieBase creates and returns
KieSession objects, and it may optionally keep
references to those. When KieBase modifications occur
those modifications are applied against the data in the sessions. This
reference is a weak reference and it is also optional, which is controlled
by a boolean flag.

4.2.3.3. KieScanner

The KieScanner allows continuous monitoring of your Maven repository
to check whether a new release of a Kie project has been installed. A new release is deployed in
the KieContainer wrapping that project. The use of the KieScanner
requires kie-ci.jar to be on the classpath.

Figure 4.15. KieScanner

A KieScanner can be registered on a KieContainer
as in the following example.

In this example the KieScanner is configured to run with a fixed
time interval, but it is also possible to run it on demand by invoking the
scanNow() method on it. If the KieScanner finds in the
Maven repository an updated version of the Kie project used by that KieContainer
it automatically downloads the new version and triggers an incremental build of the new
project. From this moment all the new KieBases and KieSessions
created from that KieContainer will use the new project version.

The KieScanner will only pickup changes to deployed jars if it is using a SNAPSHOT, version range, or the LATEST setting.
Fixed versions will not automatically update at runtime.

4.2.3.4. Maven Versions and Dependencies

Maven supports a number of mechanisms to manage versioning and dependencies within applications. Modules can
be published with specific version numbers, or they can use the SNAPSHOT suffix. Dependencies can specify version
ranges to consume, or take avantage of SNAPSHOT mechanism.

StackOverflow provides a very good description for this, which is reproduced below.

If you always want to use the newest version, Maven has two keywords you can use as an alternative to version
ranges. You should use these options with care as you are no longer in control of the plugins/dependencies you are
using.

When you depend on a plugin or a dependency, you can use the a version value of LATEST or RELEASE. LATEST
refers to the latest released or snapshot version of a particular artifact, the most recently deployed artifact in
a particular repository. RELEASE refers to the last non-snapshot release in the repository. In general, it is not
a best practice to design software which depends on a non-specific version of an artifact. If you are developing
software, you might want to use RELEASE or LATEST as a convenience so that you don't have to update version
numbers when a new release of a third-party library is released. When you release software, you should always make
sure that your project depends on specific versions to reduce the chances of your build or your project being
affected by a software release not under your control. Use LATEST and RELEASE with caution, if at all.

If a dependency on that artifact is required, you have the following options (other version ranges can be
specified of course, just showing the relevant ones here): Declare an exact version (will always resolve to
1.0.1):

<version>[1.0.1]</version>

Declare an explicit version (will
always resolve to 1.0.1 unless a collision occurs, when Maven will select a matching version):

<version>1.0.1</version>

Declare a version range for all 1.x (will
currently resolve to 1.1.1):

<version>[1.0.0,2.0.0)</version>

Declare
an open-ended version range (will resolve to 2.0.0):

<version>[1.0.0,)</version>

Declare the version as LATEST (will
resolve to 2.0.0):

<version>LATEST</version>

Declare the version as
RELEASE (will resolve to 1.1.1):

<version>RELEASE</version>

Note that
by default your own deployments will update the "latest" entry in the Maven metadata, but to update the "release"
entry, you need to activate the "release-profile" from the Maven super POM. You can do this with either
"-Prelease-profile" or "-DperformRelease=true"

4.2.3.5. Settings.xml and Remote Repository Setup

The maven settings.xml is used to configure Maven execution. Detailed instructions can be found at the Maven
website:

The settings.xml file can be located in 3 locations, the actual settings used is a merge of those 3
locations.

The Maven install: $M2_HOME/conf/settings.xml

A user's install: ${user.home}/.m2/settings.xml

Folder location specified by the system property kie.maven.settings.custom

The settings.xml is used to specify the location of remote repositories. It is important that you activate the
profile that specifies the remote repository, typically this can be done using "activeByDefault":

4.2.4. Running

4.2.4.1. KieBase

The KieBase is a repository of all the
application's knowledge definitions. It will contain rules, processes,
functions, and type models. The KieBase itself does not contain
data; instead, sessions are created from the KieBase
into which data can be inserted and from which process instances may be
started. The KieBase can be obtained from the KieContainer
containing the KieModule where the KieBase has been defined.

Example 4.16. Getting a KieBase from a KieContainer

KieBase kBase = kContainer.getKieBase();

4.2.4.2. KieSession

The KieSession stores and executes on the
runtime data. It is created from the KieBase.

Figure 4.16. KieSession

Example 4.17. Create a KieSession from a KieBase

KieSession ksession = kbase.newKieSession();

4.2.4.3. KieRuntime

4.2.4.3.1. KieRuntime

The KieRuntime provides methods that
are applicable to both rules and processes, such as setting globals and
registering channels. ("Exit point" is an obsolete synonym for "channel".)

Figure 4.17. KieRuntime

4.2.4.3.1.1. Globals

Globals are named objects that are made visible to the rule engine,
but in a way that is fundamentally different from the one for facts:
changes in the object backing a global do not trigger reevaluation of
rules. Still, globals are useful for providing static information,
as an object offering services that are used in the RHS of a rule, or
as a means to return objects from the rule engine. When you use
a global on the LHS of a rule, make sure it is immutable, or, at least,
don't expect changes to have any effect on the behavior of your rules.

A global must be declared in a rules file, and then it needs to be
backed up with a Java object.

global java.util.List list

With the Knowledge Base now aware of the global identifier and
its type, it is now possible to call ksession.setGlobal()
with the global's name and an object, for any session, to associate
the object with the global. Failure to declare the global type and
identifier in DRL code will result in an exception being thrown from
this call.

List list =newArrayList();ksession.setGlobal("list", list);

Make sure to set any global before it is used in the evaluation
of a rule. Failure to do so results in a NullPointerException.

4.2.4.4. Event Model

The event package provides means to be notified of rule engine
events, including rules firing, objects being asserted, etc. This allows
separation of logging and auditing activities from the
main part of your application (and the rules).

The KieRuntimeEventManager interface is
implemented by the KieRuntime which provides two
interfaces, RuleRuntimeEventManager and
ProcessEventManager. We will only cover the
RuleRuntimeEventManager here.

Figure 4.18. KieRuntimeEventManager

The RuleRuntimeEventManager allows for listeners to
be added and removed, so that events for the working memory and the agenda
can be listened to.

Figure 4.19. RuleRuntimeEventManager

The following code snippet shows how a simple agenda listener is
declared and attached to a session. It will print matches after they
have fired.

Drools also provides DebugRuleRuntimeEventListener
and DebugAgendaEventListener which implement each method with
a debug print statement. To print all Working Memory events, you add a
listener like this:

Example 4.19. Adding a DebugRuleRuntimeEventListener

ksession.addEventListener(newDebugRuleRuntimeEventListener());

All emitted events implement the KieRuntimeEvent
interface which can be used to retrieve the actual
KnowlegeRuntime the event originated from.

Figure 4.20. KieRuntimeEvent

The events currently supported are:

MatchCreatedEvent

MatchCancelledEvent

BeforeMatchFiredEvent

AfterMatchFiredEvent

AgendaGroupPushedEvent

AgendaGroupPoppedEvent

ObjectInsertEvent

ObjectDeletedEvent

ObjectUpdatedEvent

ProcessCompletedEvent

ProcessNodeLeftEvent

ProcessNodeTriggeredEvent

ProcessStartEvent

4.2.4.5. KieRuntimeLogger

The KieRuntimeLogger uses the comprehensive event system in
Drools to create an audit log that can be used to log the execution of an
application for later inspection, using tools such as the Eclipse audit
viewer.

4.2.4.6. Commands and the CommandExecutor

KIE has the concept of stateful or stateless sessions. Stateful sessions have already been
covered, which use the standard KieRuntime, and can be worked with iteratively over time.
Stateless is a one-off execution of a KieRuntime with a provided data set. It may return some
results, with the session being disposed at the end, prohibiting further iterative
interactions. You can think of stateless as treating an engine like a function call with
optional return results.

The foundation for this is the CommandExecutor interface, which both the
stateful and stateless interfaces extend. This returns an
ExecutionResults:

Figure 4.22. CommandExecutor

Figure 4.23. ExecutionResults

The CommandExecutor allows for commands to be executed on those sessions, the
only difference being that the StatelessKieSession executes fireAllRules() at the
end before disposing the session. The commands can be created using the
CommandExecutor .The Javadocs provide the full list of the allowed comands
using the CommandExecutor.

setGlobal and getGlobal are two commands relevant to both Drools and jBPM.

Set Global calls setGlobal underneath. The optional boolean indicates whether the
command should return the global's value as part of the ExecutionResults. If true it uses the
same name as the global name. A String can be used instead of the boolean, if an alternative
name is desired.

All the above examples execute single commands. The BatchExecution
represents a composite command, created from a list of commands. It will iterate over the list
and execute each command in turn. This means you can insert some objects, start a process,
call fireAllRules and execute a query, all in a single execute(...) call, which
is quite powerful.

The StatelessKieSession will execute fireAllRules() automatically at the end.
However the keen-eyed reader probably has already noticed the FireAllRules
command and wondered how that works with a StatelessKieSession. The FireAllRules
command is allowed, and using it will disable the automatic execution at the end; think of
using it as a sort of manual override function.

Any command, in the batch, that has an out identifier set will add its results to the
returned ExecutionResults instance. Let's look at a simple example to see how
this works. The example presented includes command from the Drools and jBPM, for the sake of
illustration. They are covered in more detail in the Drool and jBPM specific sections.

In the above example multiple commands are executed, two of which populate the
ExecutionResults. The query command defaults to use the same identifier as the
query name, but it can also be mapped to a different identifier.

All commands support XML and jSON marshalling using XStream, as well as JAXB marshalling.
This is covered in section
XXX.

4.2.4.7. StatelessKieSession

The StatelessKieSession wraps the
KieSession, instead of extending it. Its main
focus is on the decision service type scenarios. It avoids the need to call
dispose(). Stateless sessions do not support iterative
insertions and the method call fireAllRules() from Java code;
the act of calling execute() is a single-shot method that
will internally instantiate a KieSession, add
all the user data and execute user commands, call
fireAllRules(), and then call dispose(). While
the main way to work with this class is via the
BatchExecution (a subinterface of Command) as
supported by the CommandExecutor interface, two convenience
methods are provided for when simple object insertion is all that's
required. The CommandExecutor and BatchExecution
are talked about in detail in their own section.

Figure 4.24. StatelessKieSession

Our simple example shows a stateless session executing a given
collection of Java objects using the convenience API. It will iterate the
collection, inserting each element in turn.

If you wanted to insert the collection itself, and the collection's
individual elements, then
CommandFactory.newInsert(collection) would do the job.

Methods of the CommandFactory create the supported
commands, all of which can be marshalled using XStream and the
BatchExecutionHelper. BatchExecutionHelper
provides details on the XML format as well as how to use Drools Pipeline
to automate the marshalling of BatchExecution and
ExecutionResults.

StatelessKieSession supports globals, scoped in a
number of ways. We cover the non-command way first, as commands are
scoped to a specific execution call. Globals can be resolved in three
ways.

The StatelessKieSession method getGlobals()
returns a Globals instance which provides access to the session's
globals. These are shared for all execution
calls. Exercise caution regarding mutable globals because execution
calls can be executing simultaneously in different threads.

Example 4.26. Session scoped global

StatelessKieSession ksession = kbase.newStatelessKieSession();//Set a global hbnSession, that can be used for DB interactions in the rules.ksession.setGlobal("hbnSession", hibernateSession );//Executewhile being able to resolve the "hbnSession" identifier.ksession.execute( collection );

Using a delegate is another way of global resolution. Assigning
a value to a global (with setGlobal(String, Object))
results in the value being stored in an internal collection mapping
identifiers to values. Identifiers in this internal collection will
have priority over any supplied delegate. Only if an identifier cannot
be found in this internal collection, the delegate global (if any)
will be used.

The third way of resolving globals is to have execution scoped
globals. Here, a Command to set a global is passed to the
CommandExecutor.

The CommandExecutor interface also offers the ability
to export data via "out" parameters. Inserted facts, globals and query
results can all be returned.

Example 4.27. Out identifiers

//Set up a list of commandsList cmds =newArrayList();cmds.add(CommandFactory.newSetGlobal("list1",newArrayList(),true));cmds.add(CommandFactory.newInsert(newPerson("jon",102),"person"));cmds.add(CommandFactory.newQuery("Get People""getPeople");//Execute the listExecutionResults results = ksession.execute(CommandFactory.newBatchExecution( cmds ));//Retrieve the ArrayListresults.getValue("list1");//Retrieve the inserted Person factresults.getValue("person");//Retrieve the query as a QueryResults instance.results.getValue("Get People");

4.2.4.8. Marshalling

The KieMarshallers are used to marshal and unmarshal
KieSessions.

Figure 4.25. KieMarshallers

An instance of the KieMarshallers can be retrieved from the KieServices.
A simple example is shown below:

However, with marshalling, you will need more flexibility when dealing
with referenced user data. To achieve this use the
ObjectMarshallingStrategy interface. Two implementations are
provided, but users can implement their own. The two supplied strategies
are IdentityMarshallingStrategy and
SerializeMarshallingStrategy.
SerializeMarshallingStrategy is the default, as shown in the
example above, and it just calls the Serializable or
Externalizable methods on a user instance.
IdentityMarshallingStrategy creates an integer id for
each user object and stores them in a Map, while the id is written to the
stream. When unmarshalling it accesses the
IdentityMarshallingStrategy map to retrieve the instance.
This means that if you use the IdentityMarshallingStrategy,
it is stateful for the life of the Marshaller instance and will create ids
and keep references to all objects that it attempts to marshal. Below is
the code to use an Identity Marshalling Strategy.

Im most cases, a single strategy is insufficient. For added flexibility, the
ObjectMarshallingStrategyAcceptor interface can be used.
This Marshaller has a chain of strategies,
and while reading or writing a user object it iterates the
strategies asking if they accept responsibility for marshalling the user
object. One of the provided implementations is
ClassFilterAcceptor. This allows strings and wild cards to be
used to match class names. The default is "*.*", so in the above example
the Identity Marshalling Strategy is used which has a default "*.*"
acceptor.

Assuming that we want to serialize all classes except for one given
package, where we will use identity lookup, we could do the
following:

Note that the acceptance checking order is in the natural order of
the supplied elements.

Also note that if you are using scheduled matches (i.e. some
of your rules use timers or calendars) they are marshallable only if,
before you use it, you configure your KieSession to use a
trackable timer job factory manager as follows:

4.2.4.9. Persistence and Transactions

Longterm out of the box persistence with Java Persistence API (JPA)
is possible with Drools. It is necessary to have some implementation of the
Java Transaction API (JTA) installed. For development purposes
the Bitronix Transaction Manager is suggested, as it's simple to set up and
works embedded, but for production use JBoss Transactions is
recommended.

To use a JPA, the Environment must be set with both the
EntityManagerFactory and the TransactionManager.
If rollback occurs the ksession state is also rolled back, hence it is possible
to continue to use it after a rollback. To load a previously persisted
KieSession you'll need the id, as shown below:

The jdbc JTA data source would have to be configured first. Bitronix
provides a number of ways of doing this, and its documentation should be
consulted for details. For a quick start, here is the programmatic
approach:

Each example is described below, the order starts with the simplest (most of the options are defaulted) and working
its way up to more complex use cases.

The Deploy use cases shown below all involve mvn install. Remote deployment of JARs in
Maven is well covered in Maven literature. Utilize refers to the initial act of loading the
resources and providing access to the KIE runtimes. Where as Run refers to the act of
interacting with those runtimes.

4.2.6.1. Default KieSession

Project: default-kesession.

Summary: Empty kmodule.xml KieModule on the classpath that includes all resources in a
single default KieBase. The example shows the retrieval of the default KieSession from
the classpath.

An empty kmodule.xml will produce a single KieBase that includes all files found under
resources path, be it DRL, BPMN2, XLS etc. That single KieBase is the default and also
includes a single default KieSession. Default means they can be created without knowing their
names.

Example 4.37. Author - kmodule.xml

<kmodulexmlns="http://jboss.org/kie/6.0.0/kmodule"></kmodule>

Example 4.38. Build and Install - Maven

mvn install

ks.getKieClasspathContainer() returns the KieContainer that contains the KieBases deployed
onto the environment classpath. kContainer.newKieSession() creates the default KieSession.
Notice that you no longer need to look up the KieBase, in order to create the KieSession. The
KieSession knows which KieBase it's associated with, and use that, which in this case is the
default KieBase.

4.2.6.2. Named KieSession

Project: named-kiesession.

Summary: kmodule.xml that has one named KieBase and one named KieSession. The examples
shows the retrieval of the named KieSession from the classpath.

kmodule.xml will produce a single named KieBase, 'kbase1' that includes all files found
under resources path, be it DRL, BPMN2, XLS etc. KieSession 'ksession1' is associated with
that KieBase and can be created by name.

ks.getKieClasspathContainer() returns the KieContainer that contains the KieBases deployed
onto the environment classpath. This time the KieSession uses the name 'ksession1'. You do not
need to lookup the KieBase first, as it knows which KieBase 'ksession1' is assocaited
with.

4.2.6.3. KieBase Inheritence

Project: kiebase-inclusion.

Summary: 'kmodule.xml' demonstrates that one KieBase can include the resources from
another KieBase, from another KieModule. In this case it inherits the named KieBase from
the 'name-kiesession' example. The included KieBase can be from the current KieModule or
any other KieModule that is in the pom.xml dependency list.

kmodule.xml will produce a single named KieBase, 'kbase2' that includes all files found
under resources path, be it DRL, BPMN2, XLS etc. Further it will include all the resources
found from the KieBase 'kbase1', due to the use of the 'includes' attribute. KieSession
'ksession2' is associated with that KieBase and can be created by name.

This example requires that the previous example, 'named-kiesession', is built and installed
to the local Maven repository first. Once installed it can be included as a dependency, using
the standard Maven <dependencies> element.

Once 'named-kiesession' is built and installed this example can be built and installed as
normal. Again the act of installing, will force the unit tests to run, demonstrating the use
case.

Example 4.45. Build and Install - Maven

mvn install

ks.getKieClasspathContainer() returns the KieContainer that contains the KieBases deployed
onto the environment classpath. This time the KieSession uses the name 'ksession2'. You do not
need to lookup the KieBase first, as it knows which KieBase 'ksession1' is assocaited with.
Notice two rules fire this time, showing that KieBase 'kbase2' has included the resources from
the dependency KieBase 'kbase1'.

4.2.6.4. Multiple KieBases

Project: 'multiple-kbases.

Summary: Demonstrates that the 'kmodule.xml' can contain any number of KieBase or
KieSession declarations. Introduces the 'packages' attribute to select the folders for the
resources to be included in the KieBase.

kmodule.xml produces 6 different named KieBases. 'kbase1' includes all resources from the
KieModule. The other KieBases include resources from other selected folders, via the
'packages' attribute. Note the use of wildcard '*', to select this package and all packages
below it.

4.2.6.5. KieContainer from KieRepository

Project: kcontainer-from-repository

Summary: The project does not contain a kmodule.xml, nor does the pom.xml have any
dependencies for other KieModules. Instead the Java code demonstrates the loading of a
dynamic KieModule from a Maven repository.

The pom.xml must include kie-ci as a depdency, to ensure Maven is available at runtime.
As this uses Maven under the hood you can also use the standard Maven settings.xml
file.

In the previous examples the classpath KieContainer used. This example creates a dynamic
KieContainer as specified by the ReleaseId. The ReleaseId uses Maven conventions for group
id, artifact id and version. It also obeys LATEST and SNAPSHOT for versions.

4.2.6.6. Default KieSession from File

Summary: Dynamic KieModules can also be loaded from any Resource location. The loaded
KieModule provides default KieBase and KieSession definitions.

No kmodue.xml file exists. The project 'default-kiesession' must be built first, so that
the resulting JAR, in the target folder, can be referenced as a File.

Example 4.53. Build and Install - Maven

mvn install

Any KieModule can be loaded from a Resource location and added to the KieRepository. Once
deployed in the KieRepository it can be resolved via its ReleaseId. Note neither Maven or kie-ci are
needed here. It will not set up a transitive dependency parent classloader.

4.2.6.7. Named KieSession from File

Summary: Dynamic KieModules can also be loaded from any Resource location. The loaded
KieModule provides named KieBase and KieSession definitions.

No kmodue.xml file exists. The project 'named-kiesession' must be built first, so that the
resulting JAR, in the target folder, can be referenced as a File.

Example 4.55. Build and Install - Maven

mvn install

Any KieModule can be loaded from a Resource location and added to the KieRepository. Once
in the KieRepository it can be resolved via its ReleaseId. Note neither Maven or kie-ci are
needed here. It will not setup a transitive dependency parent classloader.

4.2.6.8. KieModule with Dependent KieModule

Summary: Programmatically provide the list of dependant KieModules, without using Maven
to resolve anything.

No kmodue.xml file exists. The projects 'named-kiesession' and 'kiebase-include' must be
built first, so that the resulting JARs, in the target folders, can be referenced as
Files.

Example 4.57. Build and Install - Maven

mvn install

Creates two resources. One is for the main KieModule 'exRes1' the other is for the
dependency 'exRes2'. Even though kie-ci is not present and thus Maven is not available to resolve
the dependencies, this shows how you can manually specify the dependent KieModules, for the
vararg.

4.3. Security

4.3.1. Security Manager

The KIE engine is a platform for the modelling and execution of business behavior, using a multitude of
declarative abstractions and metaphores, like rules, processes, decision tables and etc.

Many times, the authoring of these metaphores is done by third party groups, be it a different group inside the
same company, a group from a partner company, or even anonymous third parties on the internet.

Rules and Processes are designed to execute arbitrary code in order to do their job, but in such cases it might
be necessary to constrain what they can do. For instance, it is unlikely a rule should be allowed to create a
classloader (what could open the system to an attack) and certainly it should not be allowed to make a call to
System.exit().

The Java Platform provides a very comprehensive and well defined security framework that allows users to define
policies for what a system can do. The KIE platform leverages that framework and allow application developers to
define a specific policy to be applied to any execution of user provided code, be it in rules, processes, work item
handlers and etc.

4.3.1.1. How to define a KIE Policy

Rules and processes can run with very restrict permissions, but the engine itself needs to perform many
complex operations in order to work. Examples are: it needs to create classloaders, read system properties, access
the file system, etc.

Once a security manager is installed, though, it will apply restrictions to all the code executing in the JVM
according to the defined policy. For that reason, KIE allows the user to define two different policy files: one
for the engine itself and one for the assets deployed into and executed by the engine.

One easy way to setup the enviroment is to give the engine itself a very permissive policy, while providing a
constrained policy for rules and processes.

Policy files follow the standard policy file syntax as described in the Java documentation. For more details,
see:

Note

When executing the engine inside a container, use your container's documentation to find out how to
configure the Security Manager and how to define the global security policy. Define the kie security policy as
described above and set the kie.security.policy system property in order to configure the engine to
use it.

Note

Please note that unless a Security Manager is configured, the kie.security.policy will be
ignored.

Note

A Security Manager has a high performance impact in the JVM. Applications with strict performance
requirements are strongly discouraged of using a Security Manager. An alternative is the use of other security
procedures like the auditing of rules/processes before testing and deployment to prevent malicious code from
being deployed to the environment.

5.1. Artificial Intelligence

5.1.1. A Little History

Over the last few decades artificial
intelligence (AI) became an unpopular term, with the well-known
"AI
Winter". There were large boasts from scientists and engineers
looking for funding, which never lived up to expectations, resulting in many
failed projects. Thinking
Machines Corporation and the 5th
Generation Computer (5GP) project probably exemplify best the
problems at the time.

Thinking Machines Corporation was one of the leading AI firms in
1990, it had sales of nearly $65 million. Here is a quote from its
brochure:

“Some day we will build a thinking machine. It will be a truly
intelligent machine. One that can see and hear and speak. A machine that
will be proud of us.”

Yet 5 years later it filed for bankruptcy protection under Chapter 11.
The site inc.com has a fascinating article titled "The Rise and
Fall of Thinking Machines". The article covers the growth of the
industry and how a cosy relationship with Thinking Machines and DARPA over-heated
the market, to the point of collapse. It explains how and why commerce
moved away from AI and towards more practical number-crunching super
computers.

The 5th Generation Computer project was a USD 400 million project in Japan to build a next generation
computer. Valves (or Tubes) was the first generation, transistors the second, integrated circuits the third and
finally microprocessors was the fourth. The fifth was intended to be a machine capable of effective Artificial
Intelligence. This project spurred an "arms" race with the UK and USA, that caused much of the AI bubble. The 5GP
would provide massive multi-cpu parallel processing hardware along with powerful knowledge representation and
reasoning software via Prolog; a type of expert system. By 1992 the
project was considered a failure and cancelled. It was the largest and most visible commercial venture for Prolog,
and many of the failures are pinned on the problems of trying to run a logic based programming language
concurrently on multi CPU hardware with effective results. Some believe that the failure of the 5GP project
tainted Prolog and relegated it to academia, see "Whatever Happened to Prolog" by
John C. Dvorak.

However while research funding dried up and the term AI became less
used, many green shoots where planted and continued more quietly under
discipline specific names: cognitive systems,
machine learning, intelligent
systems, knowledge representation and
reasoning. Offshoots of these then made their way into
commercial systems, such as expert systems in the Business
Rules Management System (BRMS) market.

Imperative, system based languages, languages such as C, C++, Java and C#/.Net have
dominated the last 20 years, enabled by the practicality of the languages and ability to run with good performance
on commodity hardware. However many believe there is a renaissance underway in the field of AI, spurred by
advances in hardware capabilities and AI research. In 2005 Heather Havenstein authored "Spring comes to AI
winter" which outlines a case for this resurgence. Norvig and Russel dedicate several pages to what
factors allowed the industry to overcome it's problems and the research that came about as a result:

Recent years have seen a revolution in both the content and
the methodology of work in artificial intelligence. It is now more common
to build on existing theories than to propose brand-new ones, to base
claims on rigorous theorems or hard experimental evidence rather than on
intuition, and to show relevance to real-world applications rather than
toy examples.

--Artificial Intelligence: A Modern Approach

Computer vision, neural networks, machine
learning and knowledge representation and reasoning (KRR) have made great
strides towards becoming practical in commercial environments. For example, vision-based systems can now fully map
out and navigate their environments with strong recognition skills. As a result we now have self-driving cars
about to enter the commercial market. Ontological research, based around description logic,
has provided very rich semantics to represent our world. Algorithms such as the tableaux algorithm have made it
possible to use those rich semantics effectively in large complex ontologies. Early KRR systems, like Prolog in
5GP, were dogged by the limited semantic capabilities and memory restrictions on the size of those
ontologies.

5.1.2. Knowledge Representation and Reasoning

In A Little History talks about AI as a broader subject and touches
on Knowledge Representation and Reasoning (KRR) and also Expert Systems,
I'll come back to Expert Systems later.

KRR is about how we represent our knowledge in symbolic form, i.e. how we describe something. Reasoning is
about how we go about the act of thinking using this knowledge. System based object-oriented languages, like C++,
Java and C#, have data definitions called classes for describing the composition and behaviour of modeled
entities. In Java we call exemplars of these described things beans or instances. However those classification
systems are limited to ensure computational efficiency. Over the years researchers have developed increasingly
sophisticated ways to represent our world. Many of you may already have heard of OWL (Web Ontology Language).
There is always a gap between what can be theoretically represented and what can be used computationally in
practically timely manner, which is why OWL has different sub-languages from Lite to Full. It is not believed that
any reasoning system can support OWL Full. However, algorithmic advances continue to narrow that gap and improve
the expressiveness available to reasoning engines.

There are also many approaches to how these systems go about
thinking. You may have heard discussions comparing the merits of
forward chaining, which is reactive and data driven, with backward chaining,
which is passive and query driven. Many other types of reasoning
techniques exist, each of which enlarges the scope of the problems we can
tackle declaratively. To list just a few: imperfect reasoning (fuzzy
logic, certainty factors), defeasible logic, belief systems, temporal
reasoning and correlation. You don't need to understand all these terms
to understand and use Drools. They are just there to give
an idea of the range of scope of research topics, which is actually far
more extensive, and continues to grow as researchers
push new boundaries.

KRR is often referred to as the core of Artificial Intelligence. Even
when using biological approaches like neural networks, which model the
brain and are more about pattern recognition than thinking, they still
build on KRR theory. My first endeavours with Drools were engineering
oriented, as I had no formal training or understanding of KRR. Learning
KRR has allowed me to get a much wider theoretical background. Allowing me
to better understand both what I've done and where I'm going, as it
underpins nearly all of the theoretical side to our Drools R&D. It
really is a vast and fascinating subject that will pay dividends for those
who take the time to learn. I know it did and still does for me. Bracham and
Levesque have written a seminal piece of work, called "Knowledge
Representation and Reasoning" that is a must read for anyone wanting to build strong
foundations. I would also recommend the Russel and Norvig
book "Artificial Intelligence, a modern approach" which also covers
KRR.

5.1.3. Rule Engines and Production Rule Systems (PRS)

We've now covered a brief history of AI and learnt that the core of AI is formed around KRR. We've shown than
KRR is a vast and fascinating subject which forms the bulk of the theory driving Drools R&D.

The rule engine is the computer program that delivers KRR
functionality to the developer. At a high level it has three
components:

Ontology

Rules

Data

As previously mentioned the ontology is the representation model we
use for our "things". It could use records or Java classes or full-blown
OWL based ontologies. The rules perform the reasoning, i.e., they facilitate
"thinking". The distinction between rules and ontologies blurs a little with
OWL based ontologies, whose richness is rule based.

The term "rules engine" is quite ambiguous in that it can be any system that uses rules, in any form, that can
be applied to data to produce outcomes. This includes simple systems like form validation and dynamic expression
engines. The book "How to Build a Business Rules Engine" (2004) by Malcolm Chisholm exemplifies this ambiguity.
The book is actually about how to build and alter a database schema to hold validation rules. The book then shows
how to generate Visual Basic code from those validation rules to validate data entry. While perfectly valid, this
is very different to what we are talking about.

Drools started life as a specific type of rule engine called a
Production Rule System (PRS) and was based around the Rete algorithm
(usually pronounced as two syllables, e.g., REH-te or RAY-tay). The
Rete algorithm, developed by Charles Forgy in 1974, forms the brain of a
Production Rule System and is able to scale to a large number of rules
and facts. A Production Rule is a two-part structure: the engine matches
facts and data against Production Rules - also called Productions or just
Rules - to infer conclusions which result in actions.

when<conditions>then<actions>;

The process of matching the new or existing facts against Production Rules is called pattern
matching, which is performed by the inference engine. Actions execute in response to changes in data, like a database trigger; we say this is a
data driven approach to reasoning. The actions themselves can change data, which in turn could match against
other rules causing them to fire; this is referred to as forward chaining

Drools 5.x implements and extends the Rete algorithm. This extended Rete algorithm is named ReteOO, signifying that Drools has an enhanced and optimized implementation of the
Rete algorithm for object oriented systems. Other Rete based engines
also have marketing terms for their proprietary enhancements to Rete, like RetePlus and Rete III. The most common
enhancements are covered in "Production Matching for Large Learning Systems" (1995) by Robert B. Doorenbos'
thesis, which presents Rete/UL. Drools 6.x introduces a new lazy algorithm named PHREAK; which is covered in more detail in the PHEAK algorithm section.

The Rules are stored in the Production Memory and the facts that the Inference Engine
matches against are kept in the Working Memory. Facts are asserted into the Working Memory
where they may then be modified or retracted. A system with a large number
of rules and facts may result in many rules being true for the same fact
assertion; these rules are said to be in conflict. The Agenda manages the
execution order of these conflicting rules using a Conflict Resolution
strategy.

Figure 5.1. High-level View of a Production Rule System

5.1.4. Hybrid Reasoning Systems (HRS)

You may have read discussions comparing the merits of forward
chaining (reactive and data driven) or backward chaining (passive query).
Here is a quick explanation of these two main types of reasoning.

Forward chaining is "data-driven" and thus reactionary, with facts
being asserted into working memory, which results in one or more rules
being concurrently true and scheduled for execution by the Agenda. In
short, we start with a fact, it propagates through the rules, and we end in a
conclusion.

Figure 5.2. Forward Chaining

Backward chaining is "goal-driven", meaning that we start with a
conclusion which the engine tries to satisfy. If it can't, then it searches
for conclusions that it can satisfy. These are known as subgoals, that
will help satisfy some unknown part of the current goal. It continues this
process until either the initial conclusion is proven or there are no more
subgoals. Prolog is an example of a Backward Chaining engine. Drools can
also do backward chaining, which we refer to as derivation queries.

Figure 5.3. Backward Chaining

Historically you would have to make a choice between systems like
OPS5 (forward) or Prolog (backward). Nowadays many modern systems provide both
types of reasoning capabilities. There are also many other types of
reasoning techniques, each of which enlarges the scope of the problems we
can tackle declaratively. To list just a few: imperfect reasoning (fuzzy
logic, certainty factors), defeasible logic, belief systems, temporal
reasoning and correlation. Modern systems are merging these capabilities,
and others not listed, to create hybrid reasoning
systems (HRS).

While Drools started out as a PRS, 5.x introduced Prolog style
backward chaining reasoning as well as some functional programming styles.
For this reason we now prefer the term Hybrid Reasoning System when describing Drools.

Drools currently provides crisp reasoning, but imperfect reasoning is
almost ready. Initially this will be imperfect reasoning with fuzzy logic;
later we'll add support for other types of uncertainty. Work is also under
way to bring OWL based ontological reasoning, which will integrate with
our traits system. We also continue to improve our
functional programming capabilities.

5.1.5. Expert Systems

You will often hear the terms expert systems
used to refer to production rule systems or
Prolog-like systems. While this is normally
acceptable, it's technically incorrect as these are frameworks to build expert
systems with, rather than expert systems themselves. It becomes an
expert system once there is an ontological model to represent the domain
and there are facilities for knowledge acquisition and explanation.

Mycin is the most famous expert system, built
during the 70s. It is still heavily covered in academic literature, such
as the recommended book "Expert Systems" by Peter Jackson.

Figure 5.4. Early History of Expert Systems

5.1.6. Recommended Reading

General AI, KRR and Expert System
Books

For those wanting to get a strong theoretical background in KRR and
expert systems, I'd strongly recommend the following books. "Artificial
Intelligence: A Modern Approach" is a must have, for anyone's
bookshelf.

Introduction to Expert Systems

Peter Jackson

Expert Systems: Principles and Programming

Joseph C. Giarratano, Gary D. Riley

Knowledge Representation and Reasoning

Ronald J. Brachman, Hector J. Levesque

Artificial Intelligence : A Modern Approach.

Stuart Russell and Peter Norvig

Figure 5.5. Recommended Reading

Papers

Here are some recommended papers that cover interesting areas
in rule engine research:

5.2. Rete Algorithm

The Rete algorithm was invented by Dr. Charles
Forgy and documented in his PhD thesis in 1978-79. A simplified version of
the paper was published in 1982 (http://citeseer.ist.psu.edu/context/505087/0).
The latin word "rete" means "net" or "network". The Rete algorithm can be
broken into 2 parts: rule compilation and runtime execution.

The compilation algorithm describes how the Rules in the Production
Memory are processed to generate an efficient discrimination network. In
non-technical terms, a discrimination network is used to filter data as it
propagates through the network. The nodes at the top of the network would
have many matches, and as we go down the network, there would be fewer
matches. At the very bottom of the network are the terminal nodes. In Dr.
Forgy's 1982 paper, he described 4 basic nodes: root, 1-input, 2-input and
terminal.

Figure 5.7. Rete Nodes

The root node is where all objects enter the network. From there, it
immediately goes to the ObjectTypeNode. The purpose of the ObjectTypeNode is
to make sure the engine doesn't do more work than it needs to. For example,
say we have 2 objects: Account and Order. If the rule engine tried to
evaluate every single node against every object, it would waste a lot of
cycles. To make things efficient, the engine should only pass the object to
the nodes that match the object type. The easiest way to do this is to
create an ObjectTypeNode and have all 1-input and 2-input nodes descend from
it. This way, if an application asserts a new Account, it won't propagate to
the nodes for the Order object. In Drools when an object is asserted it
retrieves a list of valid ObjectTypesNodes via a lookup in a HashMap from
the object's Class; if this list doesn't exist it scans all the
ObjectTypeNodes finding valid matches which it caches in the list. This
enables Drools to match against any Class type that matches with an
instanceof check.

Figure 5.8. ObjectTypeNodes

ObjectTypeNodes can propagate to AlphaNodes, LeftInputAdapterNodes and
BetaNodes. AlphaNodes are used to evaluate literal conditions. Although the
1982 paper only covers equality conditions, many RETE implementations
support other operations. For example, Account.name == "Mr
Trout" is a literal condition. When a rule has multiple literal
conditions for a single object type, they are linked together. This means
that if an application asserts an Account object, it must first satisfy the
first literal condition before it can proceed to the next AlphaNode. In Dr.
Forgy's paper, he refers to these as IntraElement conditions. The following
diagram shows the AlphaNode combinations for Cheese( name == "cheddar",
strength == "strong" ):

Figure 5.9. AlphaNodes

Drools extends Rete by optimizing the propagation from ObjectTypeNode
to AlphaNode using hashing. Each time an AlphaNode is added to an
ObjectTypeNode it adds the literal value as a key to the HashMap with the
AlphaNode as the value. When a new instance enters the ObjectType node,
rather than propagating to each AlphaNode, it can instead retrieve the
correct AlphaNode from the HashMap,thereby avoiding unnecessary literal
checks.

There are two two-input nodes, JoinNode and NotNode, and both are
types of BetaNodes. BetaNodes are used to compare 2 objects, and their
fields, to each other. The objects may be the same or different types. By
convention we refer to the two inputs as left and right. The left input for
a BetaNode is generally a list of objects; in Drools this is a Tuple. The
right input is a single object. Two Nodes can be used to implement 'exists'
checks. BetaNodes also have memory. The left input is called the Beta Memory
and remembers all incoming tuples. The right input is called the Alpha
Memory and remembers all incoming objects. Drools extends Rete by performing
indexing on the BetaNodes. For instance, if we know that a BetaNode is
performing a check on a String field, as each object enters we can do a hash
lookup on that String value. This means when facts enter from the opposite
side, instead of iterating over all the facts to find valid joins, we do a
lookup returning potentially valid candidates. At any point a valid join is
found the Tuple is joined with the Object; which is referred to as a partial
match; and then propagated to the next node.

Figure 5.10. JoinNode

To enable the first Object, in the above case Cheese, to enter the
network we use a LeftInputNodeAdapter - this takes an Object as an input and
propagates a single Object Tuple.

Terminal nodes are used to indicate a single rule having matched all
its conditions; at this point we say the rule has a full match. A rule with
an 'or' conditional disjunctive connective results in subrule generation for
each possible logically branch; thus one rule can have multiple terminal
nodes.

Drools also performs node sharing. Many rules repeat the same
patterns, and node sharing allows us to collapse those patterns so that they
don't have to be re-evaluated for every single instance. The following two
rules share the first pattern, but not the last:

As you can see below, the compiled Rete network shows that the alpha
node is shared, but the beta nodes are not. Each beta node has its own
TerminalNode. Had the second pattern been the same it would have also been
shared.

Figure 5.11. Node Sharing

5.3. ReteOO Algorithm

The ReteOO was developed throughout the 3, 4 and 5 series releases. It takes the RETE
algorithm and applies well known enhancements, all of which are covered by existing academic literature:

Node sharing

Sharing is applied to both the alpha and beta network. The beta network sharing is always from the root
pattern.

Alpha indexing

Alpha Nodes with many children use a hash lookup mechanism, to avoid testing each result.

Beta indexing

Join, Not and Exist nodes indexing their memories using a hash. This reduces the join attempts for equal
checks. Recently range indexing was added to Not and Exists.

Tree based graphs

Join matches did not contain any references to their parent or children matches. Deletions would have to
recalculate all join matches again, which involves recreating all those join match objects, to be able to find
the parts of the network where the tuples should be deleted. This is called symmetrical propagation. A tree
graph provides parent and children references, so a deletion is just a matter of following those references.
This is asymmetrical propagation. The result is faster and less impact on the GC, and more robust because
changes in values will not cause memory leaks if they happen without the engine being notified.

Modify-in-place

Traditional RETE implements a modify as a delete + insert. This causes all join tuples to be GC'd, many of
which are recreated again as part of the insert. Modify-in-place instead propagates as a single pass, every
node is inspected

Property reactive

Also called "new trigger condition". Allows more fine grained reactivity to updates. A Pattern can react
to changes to specific properties and ignore others. This alleviates problems of recursion and also helps with
performance.

Sub-networks

Not, Exists and Accumulate can each have nested conditional elements, which forms sub networks.

Backward Chaining

Prolog style derivation trees for backward chaining are supported. The implementation is stack based, so
does not have method recursion issues for large graphs.

Lazy Truth Maintenance

Truth maintenance has a runtime cost, which is incurred whether TMS is used or not. Lazy TMS only turns it
on, on first use. Further it's only turned on for that object type, so other object types do not incur the
runtime cost.

Heap based agenda

The agenda uses a binary heap queue to sort rule matches by salience, rather than any linear search or
maintenance approach.

Dynamic Rules

Rules can be added and removed at runtime, while the engine is still populated with data.

5.4. PHREAK Algorithm

Drools 6 introduces a new algorithm, that attempts to address some of the core issues of RETE. The algorithm is
not a rewrite form scratch and incorporates all of the existing code from ReteOO, and all its enhancements. While
PHREAK is an evolution of the RETE algorithm, it is no longer classified as a RETE implementation. In the same way
that once an animal evolves beyond a certain point and key characteristics are changed, the animal becomes
classified as new species. There are two key RETE characteristics that strongly identify any derivative strains,
regardless of optimizations. That it is an eager, data oriented algorithm. Where all work is doing done the insert,
update or delete actions; eagerly producing all partial matches for all rules. PHREAK in contrast is characterised
as a lazy, goal oriented algorithm; where partial matching is aggressively delayed.

This eagerness of RETE can lead to a lot of churn in large systems, and much wasted work. Where wasted work is
classified as matching efforts that do not result in a rule firing.

PHREAK was heavily inspired by a number of algorithms; including (but not limited to) LEAPS, RETE/UL and
Collection-Oriented Match. PHREAK has all enhancements listed in the ReteOO section. In addition it adds the
following set of enhancements, which are explained in more detail in the following paragraphs.

Three layers of contextual memory; Node, Segment and Rule memories.

Rule, segment and node based linking.

Lazy (delayed) rule evaluation.

Isolated rule evaluation.

Set oriented propagations.

Stack based evaluations, with pause and resume.

When the PHREAK engine is started all rules are said to be unlinked, no rule evaluation can happen while rules
are unlinked. The insert, update and deletes actions are queued before entering the beta network. A simple
heuristic, based on the rule most likely to result in firings, is used to select the next rule for evaluation; this
delays the evaluation and firing of the other rules. Only once a rule has all right inputs populated will the rule
be considered linked in, although no work is yet done. Instead a goal is created, that represents the rule, and
placed into a priority queue; which is ordered by salience. Each queue itself is associated with an AgendaGroup.
Only the active AgendaGroup will inspect its queue, popping the goal for the rule with the highest salience and
submitting it for evaluation. So the work done shifts from the insert, update, delete phase to the fireAllRules
phase. Only the rule for which the goal was created is evaluated, other potential rule evaluations from those facts
are delayed. While individual rules are evaluated, node sharing is still achieved through the process of
segmentation, which is explained later.

Each successful join attempt in RETE produces a tuple (or token, or partial match) that will be propagated to
the child nodes. For this reason it is characterised as a tuple oriented algorithm. For each child node that it
reaches it will attempt to join with the other side of the node, again each successful join attempt will be
propagated straight away. This creates a descent recursion effect. Thrashing the network of nodes as it ripples up
and down, left and right from the point of entry into the beta network to all the reachable leaf nodes.

PHREAK propagation is set oriented (or collection-oriented), instead of tuple oriented. For the rule being
evaluated it will visit the first node and process all queued insert, update and deletes. The results are added to a
set and the set is propagated to the child node. In the child node all queued inset, update and deletes are
processed, adding the results to the same set. Once finished that set is propagated to the next child node, and so
on until the terminal node is reached. This creates a single pass, pipeline type effect, that is isolated to the
current rule being evaluated. This creates a batch process effect which can provide performance advantages for
certain rule constructs; such as sub-networks with accumulates. In the future it will leans itself to being able to
exploit multi-core machines in a number of ways.

The Linking and Unlinking uses a layered bit mask system, based on a network segmentation. When the rule network
is built segments are created for nodes that are shared by the same set of rules. A rule itself is made up from a
path of segments, although if there is no sharing that will be a single segment. A bit-mask offset is assigned to
each node in the segment. Also another bit mask (the layering) is assigned to each segment in the rule's path. When
there is at least one input (data propagation) the node's bit is set to on. When each node has its bit set to on
the segment's bit is also set to on. Conversely if any node's bit is set to off, the segment is then also set to
off. If each segment in the rule's path is set to on, the rule is said to be linked in and a goal is created to
schedule the rule for evaluation. The same bit-mask technique is used to also track dirty node, segments and rules;
this allows for a rule already link in to be scheduled for evaluation if it's considered dirty since it was last
evaluated.

This ensures that no rule will ever evaluate partial matches, if it's impossible for it to result in rule
instances because one of the joins has no data. This is possible in RETE and it will merrily churn away producing
martial match attempts for all nodes, even if the last join is empty.

While the incremental rule evaluation always starts from the root node, the dirty bit masks are used to allow
nodes and segments that are not dirty to be skipped.

Using the existence of at at least one items of data per node, is a fairly basic heuristic. Future work would
attempt to delay the linking even further; using techniques such as arc consistency to determine whether or not
matching will result in rule instance firings.

Where as RETE has just a singe unit of memory, the node memory, PHREAK has 3 levels of memory. This allows for
much more contextual understanding during evaluation of a Rule.

Figure 5.12. PHREAK 3 Layered memory system

Example 1 shows a single rule, with three patterns; A, B and C. It forms a single segment, with bits 1, 2 and 4
for the nodes. The single segment has a bit offset of 1.

Figure 5.13. Example1: Single rule, no sharing

Example 2 demonstrates what happens when another rule is added that shares the pattern A. A is placed in its
own segment, resulting in two segments per rule. Those two segments form a path, for their respective rules. The
first segment is shared by both paths. When A is linked the segment becomes linked, it then iterates each path the
segment is shared by, setting the bit 1 to on. If B and C are later turned on, the second segment for path R1 is
linked in; this causes bit 2 to be turned on for R1. With bit 1 and bit 2 set to on for R1, the rule is now linked
and a goal created to schedule the rule for later evaluation and firing.

When a rule is evaluated it is the segments that allow the results of matching to be shared. Each segment has a
staging memory to queue all insert, update and deletes for that segment. If R1 was to evaluated it would process A
and result in a set of tuples. The algorithm detects that there is a segmentation split and will create peered
tuples for each insert, update and delete in the set and add them to R2's staging memory. Those tuples will be
merged with any existing staged tuples and wait for R2 to eventually be evaluated.

Figure 5.14. Example 2: Two rules, with sharing

Example 3 adds a third rule and demonstrates what happens when A and B are shared. Only the bits for the
segments are shown this time. Demonstrating that R4 has 3 segments, R3 has 3 segments and R1 has 2 segments. A and B
are shared by R1, R3 and R4. While D is shared by R3 and R4.

Figure 5.15. Example 3: Three rules, with sharing

Sub-networks are formed when a Not, Exists or Accumulate node contain more than one element. In Example 4 "B
not( C )" forms the sub network, note that "not(C)" is a single element and does not require a sub network and is
merged inside of the Not node.

The sub network gets its own segment. R1 still has a path of two segments. The sub network forms another "inner"
path. When the sub network is linked in, it will link in the outer segment.

Figure 5.16. Example 4 : Single rule, with sub-network and no sharing

Example 5 shows that the sub-network nodes can be shard by a rule that does not have a sub-network. This results
in the sub-network segment being split into two.

Figure 5.17. Example 5: Two rules, one with a sub-network and sharing

Not nodes with constraints and accumulate nodes have special behaviour and can never unlink a segment, and are
always considered to have their bits on.

All rule evaluations are incremental, and will not waste work recomputing matches that it has already
produced.

The evaluation algorithm is stack based, instead of method recursion. Evaluation can be paused and resumed at
any time, via the use of a StackEntry to represent current node being evaluated.

When a rule evaluation reaches a sub-network a StackEntry is created for the outer path segment and the
sub-network segment. The sub-network segment is evaluated first, when the set reaches the end of the sub-network
path it is merged into a staging list for the outer node it feeds into. The previous StackEntry is then resumed
where it can process the results of the sub network. This has the added benefit that all work is processed in a
batch, before propagating to the child node; which is much more efficient for accumulate nodes.

The same stack system can be used for efficient backward chaining. When a rule evaluation reaches a query node
it again pauses the current evaluation, by placing it on the stack. The query is then evaluated which produces a
result set, which is saved in a memory location for the resumed StackEntry to pick up and propagate to the child
node. If the query itself called other queries the process would repeat, with the current query being paused and a
new evaluation setup for the current query node.

One final point on performance. One single rule in general will not evaluate any faster with PHREAK than it does
with RETE. For a given rule and same data set, which using a root context object to enable and disable matching,
both attempt the same amount of matches and produce the same number of rule instances, and take roughly the same
time. Except for the use case with subnetworks and accumulates.

PHREAK can however be considered more forgiving that RETE for poorly written rule bases and with a more graceful
degradation of performance as the number of rules and complexity increases.

RETE will also churn away producing partial machines for rules that do not have data in all the joins; where as
PHREAK will avoid this.

So it's not that PHREAK is faster than RETE, it just won't slow down as much as your system grows :)

AgendaGroups did not help in RETE performance, as all rules where evaluated at all times, regardless of the
group. The same is true for salience. Which is why root context objects are often used, to limit matching attempts.
PHREAK only evaluates rules for the active AgendaGroup, and within that group will attempt to avoid evaluation of
rules (via salience) that do not result in rule instance firings.

With PHREAK AgendaGroups and salience now become useful performance tools. The root context objects are no
longer needed and potentially counter productive to performance, as they force the flushing and recreation of
matches for rules.

6.1. The Basics

6.1.1. Stateless Knowledge Session

So where do we get started? There are so many use cases and so much functionality in a rule engine such as
Drools that it becomes beguiling. Have no fear my intrepid adventurer, the complexity is layered and you can ease
yourself in with simple use cases.

Stateless session, not utilising inference, forms the simplest use
case. A stateless session can be called like a function passing it some
data and then receiving some results back. Some common use cases for
stateless sessions are, but not limited to:

Validation

Is this person eligible for a mortgage?

Calculation

Compute a mortgage premium.

Routing and Filtering

Filter incoming messages, such as emails, into
folders.

Send incoming messages to a destination.

So let's start with a very simple example using a driving license
application.

Now that we have our data model we can write our first rule. We
assume that the application uses rules to reject invalid applications. As
this is a simple validation use case we will add a single rule to
disqualify any applicant younger than 18.

To make the engine aware of data, so it can be processed against the
rules, we have to insert the data, much like with a
database. When the Applicant instance is inserted into the engine it is
evaluated against the constraints of the rules, in this case just two
constraints for one rule. We say two because the type
Applicant is the first object type constraint, and age <
18 is the second field constraint. An object type constraint plus
its zero or more field constraints is referred to as a pattern. When an
inserted instance satisfies both the object type constraint and all the
field constraints, it is said to be matched. The $a is a
binding variable which permits us to reference the matched object in the
consequence. There its properties can be updated. The dollar character
('$') is optional, but it helps to differentiate variable names from field
names. The process of matching patterns against the inserted data is, not
surprisingly, often referred to as pattern matching.

To use this rule it is necessary to put it a Drools file, just a plain
text file with .drl extension , short for "Drools Rule Language". Let's call
this file licenseApplication.drl, and store it in a Kie Project. A Kie Project
has the structure of a normal Maven project with an additional file (kmodule.xml)
defining the KieBases and KieSessions that can be created.
This file has to be placed in the resources/META-INF folder of the Maven project
while all the other Drools artifacts, such as the licenseApplication.drl
containing the former rule, must be stored in the resources folder or in any
other subfolder under it.

Since meaningful defaults have been provided for all configuration aspects, the simplest
kmodule.xml file can contain just an empty kmodule tag like the following:

The above code snippet compiles all the DRL files found on the classpath
and put the result of this compilation, a KieModule, in the KieContainer.
If there are no errors, we are now ready to create our session from the KieContainer
and execute against some data:

The preceding code executes the data against the rules. Since the
applicant is under the age of 18, the application is marked as
invalid.

So far we've only used a single instance, but what if we want to use
more than one? We can execute against any object implementing Iterable,
such as a collection. Let's add another class called
Application, which has the date of the application, and we'll
also move the boolean valid field to the Application
class.

Unfortunately a Java element does not implement the
Iterable interface, so we have to use the JDK converter
method Arrays.asList(...). The code shown below executes
against an iterable list, where all collection elements are inserted
before any matched rules are fired.

CommandFactory supports many other Commands that can be
used in the BatchExecutor like StartProcess,
Query, and SetGlobal.

6.1.2. Stateful Knowledge Session

Stateful Sessions are long lived and allow iterative changes over
time. Some common use cases for Stateful Sessions are, but not limited
to:

Monitoring

Stock market monitoring and analysis for semi-automatic
buying.

Diagnostics

Fault finding, medical diagnostics

Logistics

Parcel tracking and delivery provisioning

Compliance

Validation of legality for market trades.

In contrast to a Stateless Session, the dispose()
method must be called afterwards to ensure there are no memory leaks, as
the KieBase contains references to Stateful Knowledge Sessions when
they are created. Since Stateful Knowledge Session is the most commonly used session type
it is just named KieSession in the KIE API. KieSession also
supports the BatchExecutor interface, like
StatelessKieSession, the only difference being that the
FireAllRules command is not automatically called at the end
for a Stateful Session.

We illustrate the monitoring use case with an example for raising a
fire alarm. Using just four classes, we represent rooms in a house, each
of which has one sprinkler. If a fire starts in a room, we represent that
with a single Fire instance.

In the previous section on Stateless Sessions the concepts of
inserting and matching against data were introduced. That example assumed
that only a single instance of each object type was ever inserted and thus
only used literal constraints. However, a house has many rooms, so rules
must express relationships between objects, such as a sprinkler being in a
certain room. This is best done by using a binding variable as a
constraint in a pattern. This "join" process results in what is called
cross products, which are covered in the next section.

When a fire occurs an instance of the Fire class is
created, for that room, and inserted into the session. The rule uses a
binding on the room field of the Fire object to
constrain matching to the sprinkler for that room, which is currently off.
When this rule fires and the consequence is executed the sprinkler is
turned on.

Whereas the Stateless Session uses standard Java syntax to modify a
field, in the above rule we use the modify statement,
which acts as a sort of "with" statement. It may contain a series of comma
separated Java expressions, i.e., calls to setters of the object selected
by the modify statement's control expression. This
modifies the data, and makes the engine aware of those changes so it can
reason over them once more. This process is called inference, and it's
essential for the working of a Stateful Session. Stateless Sessions
typically do not use inference, so the engine does not need to be aware of
changes to data. Inference can also be turned off explicitly by using the
sequential mode.

So far we have rules that tell us when matching data exists, but
what about when it does not exist? How do we
determine that a fire has been extinguished, i.e., that there isn't a
Fire object any more? Previously the constraints have been
sentences according to Propositional Logic, where the engine is
constraining against individual instances. Drools also has support for
First Order Logic that allows you to look at sets of data. A pattern under
the keyword not matches when something does not exist.
The rule given below turns the sprinkler off as soon as the fire in that
room has disappeared.

While there is one sprinkler per room, there is just a single alarm
for the building. An Alarm object is created when a fire
occurs, but only one Alarm is needed for the entire building,
no matter how many fires occur. Previously not was
introduced to match the absence of a fact; now we use its complement
exists which matches for one or more instances of some
category.

rule "Raise the alarm when we have one or more fires"
when
exists Fire()
then
insert( new Alarm() );
System.out.println( "Raise the alarm" );
end

Likewise, when there are no fires we want to remove the alarm, so
the not keyword can be used again.

rule "Cancel the alarm when all the fires have gone"
when
not Fire()
$alarm : Alarm()
then
delete( $alarm );
System.out.println( "Cancel the alarm" );
end

Finally there is a general health status message that is printed
when the application first starts and after the alarm is removed and all
sprinklers have been turned off.

rule "Status output when things are ok"
when
not Alarm()
not Sprinkler( on == true )
then
System.out.println( "Everything is ok" );
end

As we did in the Stateless Session example, the above rules should be placed
in a single DRL file and saved into the resouces folder of your Maven project
or any of its subfolder. As before, we can then obtain a KieSession from
the KieContainer. The only difference is that this time we
create a Stateful Session, whereas before we created a Stateless Session.

With the session created it is now possible to iteratively work with
it over time. Four Room objects are created and inserted, as
well as one Sprinkler object for each room. At this point the
engine has done all of its matching, but no rules have fired yet. Calling
ksession.fireAllRules() allows the matched rules to fire, but
without a fire that will just produce the health message.

We now create two fires and insert them; this time a reference is
kept for the returned FactHandle. A Fact Handle is an
internal engine reference to the inserted instance and allows instances to
be retracted or modified at a later point in time. With the fires now in
the engine, once fireAllRules() is called, the alarm is
raised and the respective sprinklers are turned on.

> Raise the alarm
> Turn on the sprinkler for room kitchen
> Turn on the sprinkler for room office

After a while the fires will be put out and the Fire
instances are retracted. This results in the sprinklers being turned off,
the alarm being cancelled, and eventually the health message is printed
again.

> Cancel the alarm
> Turn off the sprinkler for room office
> Turn off the sprinkler for room kitchen
> Everything is ok

Everyone still with me? That wasn't so hard and already I'm hoping
you can start to see the value and power of a declarative rule
system.

6.1.3. Methods versus Rules

People often confuse methods and rules, and new rule users often ask, "How do I call a rule?" After the last
section, you are now feeling like a rule expert and the answer to that is obvious, but let's summarize the
differences nonetheless.

Rules execute by matching against any data as long it is
inserted into the engine.

Rules can never be called directly.

Specific instances cannot be passed to a rule.

Depending on the matches, a rule may fire once or several times,
or not at all.

6.1.4. Cross Products

Earlier the term "cross product" was mentioned, which is the result of a join. Imagine for a moment that the
data from the fire alarm example were used in combination with the following rule where there are no field
constraints:

These cross products can obviously become huge, and they may very
well contain spurious data. The size of cross products is often the source
of performance problems for new rule authors. From this it can be seen
that it's always desirable to constrain the cross products, which is done
with the variable constraint.

6.2. Execution Control

6.2.1. Agenda

The Agenda is a Rete feature. It maintains set
of rules that are able to execute, its job is to schedule that execution
in a deterministic order.

During actions on the RuleRuntime, rules may become fully matched and eligible for execution; a
single Rule Runtime Action can result in multiple eligible rules. When a rule is fully matched a Rule Match is
created, referencing the rule and the matched facts, and placed onto the Agenda. The Agenda controls the execution
order of these Matches using a Conflict Resolution strategy.

The engine cycles repeatedly through two phases:

Rule Runtime Actions. This is where most of the work takes place, either in the Consequence (the RHS
itself) or the main Java application process. Once the Consequence has finished or the main Java application
process calls fireAllRules() the engine switches to the Agenda Evaluation phase.

Agenda Evaluation. This attempts to select a rule to fire. If no rule is found it exits, otherwise it
fires the found rule, switching the phase back to Rule Runtime Actions.

Figure 6.1. Two Phase Execution

The process repeats until the agenda is clear, in which case control returns to the calling application. When
Rule Runtime Actions are taking place, no rules are being fired.

6.2.2. Rule Matches and Conflict Sets.

6.2.2.1. Cashflow Example

So far the data and the matching process has been simple and
small. To mix things up a bit a new example will be explored that
handles cashflow calculations over date periods. The state of the engine
will be illustratively shown at key stages to help get a better
understanding of what is actually going on under the hood. Three classes
will be used, as shown below. This will help us grow our understanding
of pattern matching and joins further. We will then use this to
illustate different techniques for execution control.

By now you already know how to create KieBases and how to instantiate facts to populate the
KieSession, so tables will be used to show the state of the inserted data, as it makes things
clearer for illustration purposes. The tables below show that a single fact was inserted for the
Account. Also inserted are a series of debits and credits as CashFlow objects for
that account, extending over two quarters.

Figure 6.2. CashFlows and Account

Two rules can be used to determine the debit and credit for that
quarter and update the Account balance. The two rules below constrain
the cashflows for an account for a given time period. Notice the
"&&" which use short cut syntax to avoid repeating the field
name twice.

Earlier we showed how rules would equate to SQL, which can often
help people with an SQL background to understand rules. The two rules
above can be represented with two views and a trigger for each view, as
below:

If the AccountPeriod is set to the first quarter we
constrain the rule "increase balance for credits" to fire on two rows of
data and "decrease balance for debits" to act on one row of data.

Figure 6.3. AccountingPeriod, CashFlows and Account

The two cashflow tables above represent the matched data for the two rules. The data is matched during the
insertion stage and, as you discovered in the previous chapter, does not fire straight away, but only after
fireAllRules() is called. Meanwhile, the rule plus its matched data is placed on the Agenda and
referred to as an RuIe Match or Rule Instance. The Agenda is a table of Rule Matches that are able to fire and
have their consequences executed, as soon as fireAllRules() is called. Rule Matches on the Agenda are referred
to as a conflict set and their execution is determine by a conflict resolution strategy.
Notice that the order of execution so far is considered arbitrary.

Figure 6.4. CashFlows and Account

After all of the above activations are fired, the account has a
balance of -25.

Figure 6.5. CashFlows and Account

If the AccountPeriod is updated to the second quarter, we have just a single matched row of
data, and thus just a single Rule Match on the Agenda.

The firing of that Activation results in a balance of 25.

Figure 6.6. CashFlows and Account

Figure 6.7. CashFlows and Account

6.2.2.2. Conflict Resolution

What if you don't want the order of rule execution to be arbitrary? When there is one or more Rule Match on
the Agenda they are said to be in conflict, and a conflict resolution strategy is used to determine the order of
execution. The Drools strategy is very simple and based around a salience value, which assigns a priority to a
rule. Each rule has a default value of 0, the higher the value the higher the priority.

As a general rule, it is a good idea not to count on rules firing
in any particular order, and to author the rules without worrying about
a "flow". However when a flow is needed a number of possibilities exist
beyond salience: agenda groups, rule flow groups, activation groups and
control/semaphore facts.

As of Drools 6.0 rule definition order in the source file is used to set priority after salience.

6.2.2.3. Salience

To illustrate Salience we add a rule to print the account balance,
where we want this rule to be executed after all the debits and credits
have been applied for all accounts. We achieve this by assigning a
negative salience to this rule so that it fires after all rules with the
default salience 0.

6.2.2.5. Rule Flow

Drools also features ruleflow-group attributes which allows
workflow diagrams to declaratively specify when rules are allowed to
fire. The screenshot below is taken from Eclipse using the Drools
plugin. It has two ruleflow-group nodes which ensures that the
calculation rules are executed before the reporting rules.

6.2.3. Declarative Agenda

Warning

Declarative Agenda is experimental, and all aspects are highly likely to change in the future.
@Eager and @Direct are temporary annotations to control the behaviour of rules, which will also
change as Declarative Agenda evolves. Annotations instead of attributes where chosen, to reflect
their experimental nature.

The declarative agenda allows to use rules to control which other rules can fire and when.
While this will add a lot more overhead than the simple use of salience, the advantage is it is declarative and
thus more readable and maintainable and should allow more use cases to be achieved in a simpler fashion.

This feature is off by default and must be explicitly enabled, that is because it is considered highly
experimental for the moment and will be subject to change, but can be activated on a given KieBase by adding the
declarativeAgenda='enabled' attribute in the corresponding kbase tag of the kmodule.xml file as in the following example.

All rule's Matches are inserted into WorkingMemory as facts. So you can now do pattern matching against a
Match. The rule's metadata and declarations are available as fields on the Match object.

You can use the kcontext.blockMatch( Match match ) for the current rule to block the selected
match. Only when that rule becomes false will the match be eligible for firing. If it is already
eligible for firing and is later blocked, it will be removed from the agenda until it is unblocked.

A match may have multiple blockers and a count is kept. All blockers must became false for the
counter to reach zero to enable the Match to be eligible for firing.

kcontext.unblockAllMatches( Match match ) is an over-ride rule that will remove all blockers
regardless

An activation may also be cancelled, so it never fires with cancelMatch

The @Direct annotations allows a rule to fire as soon as it's matched, this is to be used for
rules that block/unblock matches, it is not desirable for these rules to have side effects that impact
else where.

Here is a basic example that will block all matches from rules that have metadata @department('sales').
They will stay blocked until the blockerAllSalesRules rule becomes false, i.e. "go2" is retracted.

Warning

Further than annotate the blocking rule with @Direct, it is also necessary to annotate all the rules that
could be potentially blocked by it with @Eager. This is because, since the Match has to be evaluated by
the pattern matching of the blocking rule, the potentially blocked ones cannot be evaluated lazily, otherwise
won't be any Match to be evaluated.

This example shows how you can use active property to count the number of active or inactive (already fired)
matches.

6.3. Inference

6.3.1. Bus Pass Example

Inference has a bad name these days, as something not relevant to business use cases and just too complicated
to be useful. It is true that contrived and complicated examples occur with inference, but that should not detract
from the fact that simple and useful ones exist too. But more than this, correct use of inference can crate more
agile and less error prone business rules, which are easier to maintain.

So what is inference? Something is inferred when we gain knowledge
of something from using previous knowledge. For example, given a Person
fact with an age field and a rule that provides age policy control, we can
infer whether a Person is an adult or a child and act on this.

Due to the preceding rule, every Person who is 18 or over will have an
instance of IsAdult inserted for them. This fact is special in that it is known
as a relation. We can use this inferred relation in any rule:

$p : Person()
IsAdult( person == $p )

So now we know what inference is, and have a basic example, how does
this facilitate good rule design and maintenance?

Let's take a government department that are responsible for issuing
ID cards when children become adults, henceforth referred to as ID
department. They might have a decision table that includes logic like
this, which says when an adult living in London is 18 or over, issue the
card:

However the ID department does not set the policy on who an adult
is. That's done at a central government level. If the central government
were to change that age to 21, this would initiate a change management process.
Someone would have to liaise with the ID department and make sure their systems
are updated, in time for the law going live.

This change management process and communication between departments
is not ideal for an agile environment, and change becomes costly and error
prone. Also the card department is managing more information than it needs
to be aware of with its "monolithic" approach to rules management which is
"leaking" information better placed elsewhere. By this I mean that it
doesn't care what explicit "age >= 18" information determines whether
someone is an adult, only that they are an adult.

In contrast to this, let's pursue an approach where we split (de-couple)
the authoring responsibilities, so that both the central government and the ID
department maintain their own rules.

It's the central government's job to determine who is an adult.
If they change the law they just update their central repository with the
new rules, which others use:

The IsAdult fact, as discussed previously, is inferred from the
policy rules. It encapsulates the seemingly arbitrary piece of logic "age
>= 18" and provides semantic abstractions for its meaning. Now if
anyone uses the above rules, they no longer need to be aware of explicit
information that determines whether someone is an adult or not. They can
just use the inferred fact:

While the example is very minimal and trivial it illustrates some
important points. We started with a monolithic and leaky approach to our
knowledge engineering. We created a single decision table that had all
possible information in it and that leaks information from central government
that the ID department did not care about and did not want to
manage.

We first de-coupled the knowledge process so each department was
responsible for only what it needed to know. We then encapsulated this
leaky knowledge using an inferred fact IsAdult. The use of the term
IsAdult also gave a semantic abstraction to the previously arbitrary logic
"age >= 18".

So a general rule of thumb when doing your knowledge engineering
is:

Bad

Monolithic

Leaky

Good

De-couple knowledge responsibilities

Encapsulate knowledge

Provide semantic abstractions for those
encapsulations

6.4. Truth Maintenance with Logical Objects

6.4.1. Overview

After regular inserts you have to retract facts explicitly. With
logical assertions, the fact that was asserted will
be automatically retracted when the conditions that asserted it in the
first place are no longer true. Actually, it's even cleverer then that,
because it will be retracted only if there isn't any single condition that
supports the logical assertion.

Normal insertions are said to be stated, i.e.,
just like the intuitive meaning of "stating a fact" implies. Using a
HashMap and a counter, we track how many times a particular
equality is stated; this means we count how many
different instances are equal.

When we logically insert an object during a RHS
execution we are said to justify it, and it is
considered to be justified by the firing rule. For each logical insertion
there can only be one equal object, and each subsequent equal logical
insertion increases the justification counter for this logical assertion.
A justification is removed by the LHS of the creating rule becoming
untrue, and the counter is decreased accordingly. As soon as we have no
more justifications the logical object is automatically retracted.

If we try to logically insert an object when
there is an equal stated object, this will fail and
return null. If we state an object that has an
existing equal object that is justified we override
the Fact; how this override works depends on the configuration setting
WM_BEHAVIOR_PRESERVE. When the property is set to discard we
use the existing handle and replace the existing instance with the new
Object, which is the default behavior; otherwise we override it to
stated but we create an new
FactHandle.

This can be confusing on a first read, so hopefully the flow charts
below help. When it says that it returns a new FactHandle,
this also indicates the Object was propagated through the
network.

Figure 6.9. Stated Insertion

Figure 6.10. Logical Insertion

6.4.1.1. Bus Pass Example With Inference and TMS

The previous example was issuing ID cards to over 18s, in this
example we now issue bus passes, either a child or adult pass.

A "insertLogical" is part of the Drools Truth Maintenance System (TMS). When a fact is logically inserted,
this fact is dependant on the truth of the "when" clause. It means that when the rule becomes false the fact is
automatically retracted. This works particularly well as the two rules are mutually exclusive. So in the above
rules if the person is under 16 it inserts an IsChild fact, once the person is 16 or over the IsChild fact is
automatically retracted and the IsAdult fact inserted.

Returning to the code to issue bus passes, these two rules can + logically insert the ChildBusPass and
AdultBusPass facts, as the TMS + supports chaining of logical insertions for a cascading set of retracts.

Now when a person changes from being 15 to 16, not only is the IsChild fact automatically retracted, so is
the person's ChildBusPass fact. For bonus points we can combine this with the 'not' conditional element to
handle notifications, in this situation, a request for the returning of the pass. So when the TMS automatically
retracts the ChildBusPass object, this rule triggers and sends a request to the person:

6.4.1.2. Important note: Equality for Java objects

It is important to note that for Truth Maintenance (and logical
assertions) to work at all, your Fact objects (which may be JavaBeans)
must override equals and hashCode methods (from java.lang.Object)
correctly. As the truth maintenance system needs to know when two
different physical objects are equal in value, both
equals and hashCode must be overridden correctly, as per the Java
standard.

Two objects are equal if and only if their equals methods return
true for each other and if their hashCode methods return the same
values. See the Java API for more details (but do keep in mind you
MUST override both equals and hashCode).

TMS behaviour is not affected by theruntime configuration of
Identity vs Equality, TMS is always equality.

6.5. Decision Tables in Spreadsheets

Decision tables are a "precise yet compact" (ref. Wikipedia) way of representing conditional logic, and are well
suited to business level rules.

Drools supports managing rules in a spreadsheet format. Supported formats are Excel (XLS), and CSV, which means
that a variety of spreadsheet programs (such as Microsoft Excel, OpenOffice.org Calc amongst others) can be utilized.
It is expected that web based decision table editors will be included in a near future release.

Decision tables are an old concept (in software terms) but have proven useful over the years. Very briefly
speaking, in Drools decision tables are a way to generate rules driven from the data entered into a spreadsheet. All
the usual features of a spreadsheet for data capture and manipulation can be taken advantage of.

6.5.1. When to Use Decision Tables

Consider decision tables as a course of action if rules exist that can be expressed as rule templates and
data: each row of a decision table provides data that is combined with a template to generate a rule.

Many businesses already use spreadsheets for managing data, calculations, etc. If you are happy to continue
this way, you can also manage your business rules this way. This also assumes you are happy to manage packages of
rules in .xls or .csv files. Decision tables are not recommended for rules
that do not follow a set of templates, or where there are a small number of rules (or if there is a dislike towards
software like Excel or OpenOffice.org). They are ideal in the sense that there can be control over what
parameters of rules can be edited, without exposing the rules directly.

Decision tables also provide a degree of insulation from the underlying object model.

6.5.2. Overview

Here are some examples of real world decision tables (slightly edited to protect the
innocent).

Figure 6.11. Using Excel to edit a decision table

Figure 6.12. Multiple actions for a rule row

Figure 6.13. Using OpenOffice.org

In the above examples, the technical aspects of the decision table have been collapsed
away (using a standard spreadsheet feature).

The rules start from row 17, with each row resulting in a rule. The conditions are in
columns C, D, E, etc., the actions being off-screen. The values in the cells are quite simple,
and their meaning is indicated by the headers in Row 16. Column B is just a description. It is
customary to use color to make it obvious what the different areas of the table mean.

Note

Note that although the decision tables look like they process top down, this is not
necessarily the case. Ideally, rules are authored without regard for the order of rows,
simply because this makes maintenance easier, as rows will not need to be shifted around all
the time.

As each row is a rule, the same principles apply. As the rule engine processes the facts,
any rules that match may fire. (Some people are confused by this. It is possible to clear the
agenda when a rule fires and simulate a very simple decision table where only the first match
effects an action.) Also note that you can have multiple tables on one spreadsheet. This way,
rules can be grouped where they share common templates, yet at the end of the day they are all
combined into one rule package. Decision tables are essentially a tool to generate DRL rules
automatically.

Figure 6.14. A real world example using multiple tables for grouping like rules

6.5.3. How Decision Tables Work

The key point to keep in mind is that in a decision table each row is a rule, and each
column in that row is either a condition or action for that rule.

Figure 6.15. Rows and columns

The spreadsheet looks for the RuleTable keyword to indicate the
start of a rule table (both the starting row and column). Other keywords are also used to
define other package level attributes (covered later). It is important to keep the keywords in
one column. By convention the second column ("B") is used for this, but it can be any column
(convention is to leave a margin on the left for notes). In the following diagram, C is
actually the column where it starts. Everything to the left of this is ignored.

If we expand the hidden sections, it starts to make more sense how it works; note the
keywords in column C.

Figure 6.16. Expanded for rule templates

Now the hidden magic which makes it work can be seen. The RuleSet keyword indicates the
name to be used in the rule package that will encompass all the rules.
This name is optional, using a default, but it must have the
RuleSet keyword in the cell immediately to the right.

The other keywords visible in Column C are Import and Sequential which will be covered
later. The RuleTable keyword is important as it indicates that a chunk of rules will follow,
based on some rule templates. After the RuleTable keyword there is a name, used to prefix the
names of the generated rules. The sheet name and row numbers are appended to guarantee unique
rule names.

Warning

The RuleTable name combined with the sheet name must be unique across all spreadsheet
files in the same KieBase. If that's not the case, some rules might have the same name
and only 1 of them will be applied. To show such ignored rules, raise the severity of such rule name
conflicts.

The column of RuleTable indicates the column in which the rules start; columns to the
left are ignored.

Note

In general the keywords make up name-value pairs.

Referring to row 14 (the row immediately after RuleTable), the keywords CONDITION and
ACTION indicate that the data in the columns below are for either the LHS or the RHS parts of
a rule. There are other attributes on the rule which can also be optionally set this
way.

Row 15 contains declarations of ObjectTypes. The content in this
row is optional, but if this option is not in use, the row must be left blank; however this
option is usually found to be quite useful. When using this row, the values in the cells below
(row 16) become constraints on that object type. In the above case, it generates
Person(age=="42") and Cheese(type=="stilton"), where 42 and
"stilton" come from row 18. In the above example, the "==" is implicit; if just a field name
is given the translator assumes that it is to generate an exact match.

Note

An ObjectType declaration can span columns (via merged cells), meaning that all columns
below the merged range are to be combined into one set of constraints within a single
pattern matching a single fact at a time, as opposed to non-merged cells containing the same
ObjectType, but resulting in different patterns, potentially matching different or identical
facts.

Row 16 contains the rule templates themselves. They can use the "$param" placeholder to
indicate where data from the cells below should be interpolated. (For multiple insertions, use
"$1", "$2", etc., indicating parameters from a comma-separated list in a cell below.) Row 17
is ignored; it may contain textual descriptions of the column's purpose.

Rows 18 and 19 show data, which will be combined (interpolated) with the templates in row
15, to generate rules. If a cell contains no data, then its template is ignored. (This would
mean that some condition or action does not apply for that rule row.) Rule rows are read until
there is a blank row. Multiple RuleTables can exist in a sheet. Row 20 contains another
keyword, and a value. The row positions of keywords like this do not matter (most people put
them at the top) but their column should be the same one where the RuleTable or RuleSet
keywords should appear. In our case column C has been chosen to be significant, but any other
column could be used instead.

In the above example, rules would be rendered like the following (as it uses the
"ObjectType" row):

Note

The constraints age=="42" and type=="stilton" are interpreted
as single constraints, to be added to the respective ObjectType in the cell above. If the
cells above were spanned, then there could be multiple constraints on one "column".

Warning

Very large decision tables may have very large memory requirements.

6.5.4. Spreadsheet Syntax

6.5.4.1. Spreadsheet Structure

There are two types of rectangular areas defining data that is used for generating a DRL file. One, marked
by a cell labelled RuleSet, defines all DRL items except rules. The other one may occur repeatedly
and is to the right and below a cell whose contents begin with RuleTable. These areas represent the
actual decision tables, each area resulting in a set of rules of similar structure.

A Rule Set area may contain cell pairs, one below the RuleSet cell and containing a keyword
designating the kind of value contained in the other one that follows in the same row.

The columns of a Rule Table area define patterns and constraints for the left hand sides of the rules
derived from it, actions for the consequences of the rules, and the values of individual rule attributes. Thus, a
Rule Table area should contain one or more columns, both for conditions and actions, and an arbitrary selection of
columns for rule attributes, at most one column for each of these. The first four rows following the row with the
cell marked with RuleTable are earmarked as header area, mostly used for the definition of code to
construct the rules. It is any additional row below these four header rows that spawns another rule, with its data
providing for variations in the code defined in the Rule Table header.

All keywords are case insensitive.

Only the first worksheet is examined for decision tables.

6.5.4.2. Rule Set Entries

Entries in a Rule Set area may define DRL constructs (except rules), and specify rule attributes. While
entries for constructs may be used repeatedly, each rule attribute may be given at most once, and it applies to
all rules unless it is overruled by the same attribute being defined within the Rule Table area.

Entries must be given in a vertically stacked sequence of cell pairs. The first one contains a keyword and
the one to its right the value, as shown in the table below. This sequence of cell pairs may be interrupted by
blank rows or even a Rule Table, as long as the column marked by RuleSet is upheld as the one
containing the keyword.

Table 6.5. Entries in the Rule Set area

Keyword

Value

Usage

RuleSet

The package name for the generated DRL file. Optional, the default is
rule_table.

Must be First entry.

Sequential

"true" or "false". If "true", then salience is used to ensure that rules fire from the top
down.

Optional, at most once. If omitted, no firing order is imposed.

EscapeQuotes

"true" or "false". If "true", then quotation marks are escaped so that they appear literally in the
DRL.

Optional, at most once. If omitted, quotation marks are escaped.

Import

A comma-separated list of Java classes to import.

Optional, may be used repeatedly.

Variables

Declarations of DRL globals, i.e., a type followed by a variable name. Multiple global definitions
must be separated with a comma.

Optional, may be used repeatedly.

Functions

One or more function definitions, according to DRL syntax.

Optional, may be used repeatedly.

Queries

One or more query definitions, according to DRL syntax.

Optional, may be used repeatedly.

Declare

One or more declarative types, according to DRL syntax.

Optional, may be used repeatedly.

Warning

In some locales, MS Office, LibreOffice and OpenOffice will encode a double quoth "
differently, which will cause a compilation error. The difference is often hard to see. For example:
“A” will fail, but "A" will work.

For defining rule attributes that apply to all rules in the generated DRL file you can use any of the
entries in the following table. Notice, however, that the proper keyword must be used. Also, each of these
attributes may be used only once.

Table 6.6. Rule attribute entries in the Rule Set area

Keyword

Initial

Value

PRIORITY

P

An integer defining the "salience" value for the rule. Overridden by the "Sequential" flag.

DURATION

D

A long integer value defining the "duration" value for the rule.

TIMER

T

A timer definition. See "Timers and Calendars".

ENABLED

B

A Boolean value. "true" enables the rule; "false" disables the rule.

CALENDARS

E

A calendars definition. See "Timers and Calendars".

NO-LOOP

U

A Boolean value. "true" inhibits looping of rules due to changes made by its consequence.

LOCK-ON-ACTIVE

L

A Boolean value. "true" inhibits additional activations of all rules with this flag set within the
same ruleflow or agenda group.

AUTO-FOCUS

F

A Boolean value. "true" for a rule within an agenda group causes activations of the rule to
automatically give the focus to the group.

ACTIVATION-GROUP

X

A string identifying an activation (or XOR) group. Only one rule within an activation group will
fire, i.e., the first one to fire cancels any existing activations of other rules within the same
group.

AGENDA-GROUP

G

A string identifying an agenda group, which has to be activated by giving it the "focus", which is
one way of controlling the flow between groups of rules.

RULEFLOW-GROUP

R

A string identifying a rule-flow group.

6.5.4.3. Rule Tables

All Rule Tables begin with a cell containing "RuleTable", optionally followed by a string within the same
cell. The string is used as the initial part of the name for all rules derived from this Rule Table, with the row
number appended for distinction. (This automatic naming can be overridden by using a NAME column.) All other cells
defining rules of this Rule Table are below and to the right of this cell.

The next row defines the column type, with each column resulting in a part of the condition or the
consequence, or providing some rule attribute, the rule name or a comment. The table below shows which column
headers are available; additional columns may be used according to the table showing rule attribute entries given
in the preceding section. Note that each attribute column may be used at most once. For a column header, either
use the keyword or any other word beginning with the letter given in the "Initial" column of these tables.

Table 6.7. Column Headers in the Rule Table

Keyword

Initial

Value

Usage

NAME

N

Provides the name for the rule generated from that row. The default is constructed from the text
following the RuleTable tag and the row number.

At most one column

DESCRIPTION

I

A text, resulting in a comment within the generated rule.

At most one column

CONDITION

C

Code snippet and interpolated values for constructing a constraint within a pattern in a
condition.

At least one per rule table

ACTION

A

Code snippet and interpolated values for constructing an action for the consequence of the
rule.

At least one per rule table

METADATA

@

Code snippet and interpolated values for constructing a metadata entry for the rule.

Optional, any number of columns

Given a column headed CONDITION, the cells in successive lines result in a conditional element.

Text in the first cell below CONDITION develops into a pattern for the rule condition, with the snippet
in the next line becoming a constraint. If the cell is merged with one or more neighbours, a single pattern
with multiple constraints is formed: all constraints are combined into a parenthesized list and appended to
the text in this cell. The cell may be left blank, which means that the code snippet in the next row must
result in a valid conditional element on its own.

To include a pattern without constraints, you can write the pattern in front of the text for another
pattern.

The pattern may be written with or without an empty pair of parentheses. A "from" clause may be appended
to the pattern.

If the pattern ends with "eval", code snippets are supposed to produce boolean expressions for inclusion
into a pair of parentheses after "eval".

Text in the second cell below CONDITION is processed in two steps.

The code snippet in this cell is modified by interpolating values from cells farther down in the
column. If you want to create a constraint consisting of a comparison using "==" with the value from the
cells below, the field selector alone is sufficient. Any other comparison operator must be specified as
the last item within the snippet, and the value from the cells below is appended. For all other constraint
forms, you must mark the position for including the contents of a cell with the symbol
$param. Multiple insertions are possible by using the symbols $1,
$2, etc., and a comma-separated list of values in the cells below.

A text according to the pattern
forall(delimiter){snippet}
is expanded by repeating the snippet once for each of the values of the
comma-separated list of values in each of the cells below, inserting the value in place of the symbol
$ and by joining these expansions by the given delimiter. Note that the
forall construct may be surrounded by other text.

If the cell in the preceding row is not empty, the completed code snippet is added to the
conditional element from that cell. A pair of parentheses is provided automatically, as well as a
separating comma if multiple constraints are added to a pattern in a merged cell.

If the cell above is empty, the interpolated result is used as is.

Text in the third cell below CONDITION is for documentation only. It should be used to indicate the
column's purpose to a human reader.

From the fourth row on, non-blank entries provide data for interpolation as described above. A blank
cell results in the omission of the conditional element or constraint for this rule.

Given a column headed ACTION, the cells in successive lines result in an action statement.

Text in the first cell below ACTION is optional. If present, it is interpreted as an object
reference.

Text in the second cell below ACTION is processed in two steps.

The code snippet in this cell is modified by interpolating values from cells farther down in the
column. For a singular insertion, mark the position for including the contents of a cell with the symbol
$param. Multiple insertions are possible by using the symbols $1,
$2, etc., and a comma-separated list of values in the cells below.

A method call without interpolation can be achieved by a text without any marker symbols. In this
case, use any non-blank entry in a row below to include the statement.

The forall construct is available here, too.

If the first cell is not empty, its text, followed by a period, the text in the second cell and a
terminating semicolon are stringed together, resulting in a method call which is added as an action
statement for the consequence.

If the cell above is empty, the interpolated result is used as is.

Text in the third cell below ACTION is for documentation only. It should be used to indicate the
column's purpose to a human reader.

From the fourth row on, non-blank entries provide data for interpolation as described above. A blank
cell results in the omission of the action statement for this rule.

Note

Using $1 instead of $param works in most cases, but it will fail if the
replacement text contains a comma: then, only the part preceding the first comma is inserted. Use this
"abbreviation" judiciously.

Given a column headed METADATA, the cells in successive lines result in a metadata annotation for the
generated rules.

Text in the first cell below METADATA is ignored.

Text in the second cell below METADATA is subject to interpolation, as described above, using values
from the cells in the rule rows. The metadata marker character @ is prefixed automatically, and
thus it should not be included in the text for this cell.

Text in the third cell below METADATA is for documentation only. It should be used to indicate the
column's purpose to a human reader.

From the fourth row on, non-blank entries provide data for interpolation as described above. A blank
cell results in the omission of the metadata annotation for this rule.

6.5.4.4. Examples

The various interpolations are illustrated in the following example.

Example 6.5. Interpolating cell data

If the template is Foo(bar == $param) and the cell is 42,
then the result is Foo(bar == 42).

If the template is Foo(bar < $1, baz == $2) and the cell contains
42,43, the result will be Foo(bar < 42, baz ==43).

The next example demonstrates the joint effect of a cell defining the pattern type and
the code snippet below it.

This spreadsheet section shows how the Person type declaration
spans 2 columns, and thus both constraints will appear as Person(age == ..., type ==
...). Since only the field names are present in the snippet, they imply an equality
test.

In the following example the marker symbol $param is used.

The result of this column is the pattern Person(age == "42")).
You may have noticed that the marker and the operator "==" are redundant.

The next example illustrates that a trailing insertion marker can be omitted.

Here, appending the value from the cell is implied, resulting in
Person(age < "42")).

You can provide the definition of a binding variable, as in the example below. .

Here, the result is c: Cheese(type == "stilton"). Note that the
quotes are provided automatically. Actually, anything can be placed in the object type row.
Apart from the definition of a binding variable, it could also be an additional pattern that
is to be inserted literally.

A simple construction of an action statement with the insertion of a single value is
shown below.

The cell below the ACTION header is left blank. Using this style, anything can
be placed in the consequence, not just a single method call. (The same technique is
applicable within a CONDITION column as well.)

Below is a comprehensive example, showing the use of various column headers. It is not
an error to have no value below a column header (as in the NO-LOOP column): here, the
attribute will not be applied in any of the rules.

Figure 6.17. Example usage of keywords for imports, headers, etc.

And, finally, here is an example of Import, Variables and Functions.

Figure 6.18. Example usage of keywords for functions, etc.

Multiple package names within the same cell must be separated by a comma. Also,
the pairs of type and variable names must be comma-separated. Functions, however, must be
written as they appear in a DRL file. This should appear in the same column as the "RuleSet"
keyword; it could be above, between or below all the rule rows.

Note

It may be more convenient to use Import, Variables, Functions and Queries repeatedly
rather than packing several definitions into a single cell.

6.5.5. Creating and integrating Spreadsheet based Decision Tables

The API to use spreadsheet based decision tables is in the drools-decisiontables module. There is really only
one class to look at: SpreadsheetCompiler. This class will take spreadsheets in various formats,
and generate rules in DRL (which you can then use in the normal way). The SpreadsheetCompiler can
just be used to generate partial rule files if it is wished, and assemble it into a complete rule package after the
fact (this allows the separation of technical and non-technical aspects of the rules if needed).

To get started, a sample spreadsheet can be used as a base. Alternatively, if the plug-in
is being used (Rule Workbench IDE), the wizard can generate a spreadsheet from a template (to
edit it an xls compatible spreadsheet editor will need to be used).

Figure 6.19. Wizard in the IDE

6.5.6. Managing Business Rules in Decision Tables

6.5.6.1. Workflow and Collaboration

Spreadsheets are well established business tools (in use for over 25 years). Decision tables lend themselves
to close collaboration between IT and domain experts, while making the business rules clear to business analysts,
it is an ideal separation of concerns.

Typically, the whole process of authoring rules (coming up with a new decision table) would be something
like:

Business analyst takes a template decision table (from a repository, or from IT)

Decision table business language descriptions are entered in the table(s)

Decision table rules (rows) are entered (roughly)

Decision table is handed to a technical resource, who maps the business language (descriptions) to
scripts (this may involve software development of course, if it is a new application or data model)

Technical person hands back and reviews the modifications with the business analyst.

The business analyst can continue editing the rule rows as needed (moving columns around is also fine
etc).

In parallel, the technical person can develop test cases for the rules (liaising with business analysts)
as these test cases can be used to verify rules and rule changes once the system is running.

6.5.6.2. Using spreadsheet features

Features of applications like Excel can be used to provide assistance in entering data
into spreadsheets, such as validating fields. Lists that are stored in other worksheets can
be used to provide valid lists of values for cells, like in the following diagram.

<title> Wizard in the IDE </title>

Figure 6.20.

Some applications provide a limited ability to keep a history of changes, but it is recommended to use an
alternative means of revision control. When changes are being made to rules over time, older versions are archived
(many open source solutions exist for this, such as Subversion or Git).

6.5.7. Rule Templates

Related to decision tables (but not necessarily requiring a spreadsheet) are "Rule
Templates" (in the drools-templates module). These use any tabular data source as a source of
rule data - populating a template to generate many rules. This can allow both for more
flexible spreadsheets, but also rules in existing databases for instance (at the cost of
developing the template up front to generate the rules).

With Rule Templates the data is separated from the rule and there are no restrictions on
which part of the rule is data-driven. So whilst you can do everything you could do in
decision tables you can also do the following:

store your data in a database (or any other format)

conditionally generate rules based on the values in the data

use data for any part of your rules (e.g. condition operator, class name, property
name)

run different templates over the same data

As an example, a more classic decision table is shown, but without any hidden rows for the
rule meta data (so the spreadsheet only contains the raw data to generate the rules).

Figure 6.21. Template data

See the ExampleCheese.xls in the examples download for the above
spreadsheet.

If this was a regular decision table there would be hidden rows before row 1 and between
rows 1 and 2 containing rule metadata. With rule templates the data is completely separate
from the rules. This has two handy consequences - you can apply multiple rule templates to the
same data and your data is not tied to your rules at all. So what does the template look
like?

Lines 2-4: Following the header is the list of columns in the order they appear in
the data. In this case we are calling the first column age, the second
type and the third log.

Line 5: An empty line signifies the end of the column definitions.

Lines 6-9: Standard rule header text. This is standard rule DRL and will appear at
the top of the generated DRL. Put the package statement and any imports and global and
function definitions into this section.

Line 10: The keyword template signals the start of a rule template.
There can be more than one template in a template file, but each template should have a
unique name.

Lines 11-18: The rule template - see below for details.

Line 20: The keywords end template signify the end of the
template.

The rule templates rely on MVEL to do substitution using the syntax @{token_name}. There
is currently one built-in expression, @{row.rowNumber} which gives a unique number for each
row of data and enables you to generate unique rule names. For each row of data a rule will be
generated with the values in the data substituted for the tokens in the template. With the
example data above the following rule file would be generated:

6.6. Logging

One way to illuminate the black box that is a rule engine, is to play with the logging level.

Everything is logged to SLF4J, which is a simple logging facade
that can delegate any log to Logback, Apache Commons Logging, Log4j or java.util.logging. Add a dependency to the
logging adaptor for your logging framework of choice. If you're not using any logging framework yet, you can use
Logback by adding this Maven dependency:

7.1. Overview

Drools has a "native" rule language.
This format is very light in terms of punctuation, and supports
natural and domain specific languages via "expanders" that allow the
language to morph to your problem domain. This chapter is mostly concerted
with this native rule format. The diagrams used to present the syntax are
known as "railroad" diagrams, and they are basically flow charts for the
language terms. The
technically very keen may also refer to DRL.g which is
the Antlr3
grammar for the rule language. If you use the Rule Workbench, a lot of the
rule structure is done for you with content assistance, for example, type
"ru" and press ctrl+space, and it will build the rule structure for
you.

7.1.1. A rule file

A rule file is typically a file with a .drl extension. In a DRL file
you can have multiple rules, queries and functions, as well as some
resource declarations like imports, globals and attributes that are
assigned and used by your rules and queries. However, you are also able to
spread your rules across multiple rule files (in that case, the extension
.rule is suggested, but not required) - spreading rules across files can
help with managing large numbers of rules. A DRL file is simply a text
file.

The overall structure of a rule file is:

Example 7.1. Rules file

package package-nameimportsglobalsfunctionsqueriesrules

The order in which the elements are declared is not important,
except for the package name that, if declared, must be the first element
in the rules file. All elements are optional, so you will use only those
you need. We will discuss each of them in the following sections.

7.1.2. What makes a rule

For the inpatients, just as an early view, a rule has the following
rough structure:

rule"name"attributeswhenLHSthenRHSend

It's really that simple. Mostly punctuation is not needed,
even the double quotes for "name" are optional, as are newlines.
Attributes are simple (always optional) hints to how the rule should
behave. LHS is the conditional parts of the rule, which follows a certain
syntax which is covered below. RHS is basically a block that allows
dialect specific semantic code to be executed.

It is important to note that white space is not important,
except in
the case of domain specific languages, where lines are processed
one by one and spaces may be significant to the domain language.

7.2. Keywords

Drools 5 introduces the concept of hard and
soft keywords.

Hard keywords are reserved, you cannot use any hard keyword when
naming your domain objects, properties, methods, functions and other
elements that are used in the rule text.

Here is the list of hard keywords that must be avoided as identifiers
when writing rules:

true

false

null

Soft keywords are just recognized in their context, enabling you to
use these words in any other place if you wish, although, it is still
recommended to avoid them, to avoid confusions, if possible. Here is a list
of the soft keywords:

lock-on-active

date-effective

date-expires

no-loop

auto-focus

activation-group

agenda-group

ruleflow-group

entry-point

duration

package

import

dialect

salience

enabled

attributes

rule

extend

when

then

template

query

declare

function

global

eval

not

in

or

and

exists

forall

accumulate

collect

from

action

reverse

result

end

over

init

Of course, you can have these (hard and soft) words as part of a
method name in camel case, like notSomething() or accumulateSomething() -
there are no issues with that scenario.

Although the 3 hard keywords above are unlikely to be used in your
existing domain models, if you absolutely need to use them as identifiers
instead of keywords, the DRL language provides the ability to escape hard
keywords on rule text. To escape a word, simply enclose it in grave accents,
like this:

7.3. Comments

Comments are sections of text that are ignored by the rule engine.
They are stripped out when they are encountered, except inside semantic code
blocks, like the RHS of a rule.

7.3.1. Single line comment

To create single line comments, you can use '//'. The parser will
ignore anything in the line after the comment symbol. Example:

rule "Testing Comments"
when
// this is a single line comment
eval( true ) // this is a comment in the same line of a pattern
then
// this is a comment inside a semantic code block
end

Warning

'#' for comments has been removed.

7.3.2. Multi-line comment

Figure 7.1. Multi-line comment

Multi-line comments are used to comment blocks of text, both in and
outside semantic code blocks. Example:

rule "Test Multi-line Comments"
when
/* this is a multi-line comment
in the left hand side of a rule */
eval( true )
then
/* and this is a multi-line comment
in the right hand side of a rule */
end

7.4. Error Messages

Drools 5 introduces standardized error messages. This standardization
aims to help users to find and resolve problems in a easier and faster way.
In this section you will learn how to identify and interpret those error
messages, and you will also receive some tips on how to solve the problems
associated with them.

7.4.1. Message format

The standardization includes the error message format and to better
explain this format, let's use the following example:

Figure 7.2. Error Message Format

1st Block: This area identifies the
error code.

2nd Block: Line and column
information.

3rd Block: Some text describing the
problem.

4th Block: This is the first
context. Usually indicates the rule, function, template or query where the
error occurred. This block is not mandatory.

5th Block: Identifies the pattern
where the error occurred. This block is not mandatory.

7.4.2. Error Messages Description

7.4.2.1. 101: No viable alternative

Indicates the most common errors, where the parser came to a
decision point but couldn't identify an alternative. Here are some
examples:

Example 7.2.

1: rule one
2: when
3: exists Foo()
4: exits Bar()
5: then
6: end

The above example generates this message:

[ERR 101] Line 4:4 no viable alternative at input 'exits' in
rule one

At first glance this seems to be valid syntax, but it is not
(exits != exists). Let's take a look at next example:

The above code misses to close the quotes and because of this the
parser generates this error message:

[ERR 101] Line 0:-1 no viable alternative at input
'<eof>' in rule simple_rule in pattern Student

Note

Usually the Line and Column information are accurate, but in
some cases (like unclosed quotes), the parser generates a 0:-1
position. In this case you should check whether you didn't forget to
close quotes, apostrophes or parentheses.

7.4.2.2. 102: Mismatched input

This error indicates that the parser was looking for a particular
symbol that it didn't ﬁnd at the current input position. Here are some
samples:

7.4.2.5. 105: Early Exit

The recognizer came to a subrule in the grammar that must match an
alternative at least once, but the subrule did not match anything.
Simply put: the parser has entered a branch from where there is no way
out. This example illustrates it:

To fix this problem it is necessary to remove the numeric value as
it is neither a valid data type which might begin a new template slot
nor a possible start for any other rule file construct.

7.4.3. Other Messages

Any other message means that something bad has happened, so please
contact the development team.

7.5. Package

A package is a collection of rules and other related constructs, such
as imports and globals. The package members are typically related to each
other - perhaps HR rules, for instance. A package represents a namespace,
which ideally is kept unique for a given grouping of rules. The package name
itself is the namespace, and is not related to files or folders in any
way.

It is possible to assemble rules from multiple rule sources, and have
one top level package configuration that all the rules are kept under (when
the rules are assembled). Although, it is not possible to merge into the
same package resources declared under different names. A single Rulebase
may, however, contain multiple packages built on it. A common structure is to
have all the rules for a package in the same file as the package declaration
(so that is it entirely self-contained).

The following railroad diagram shows all the components that may make
up a package. Note that a package must have a namespace and be declared
using standard Java conventions for package names; i.e., no spaces, unlike
rule names which allow spaces. In terms of the order of elements, they can
appear in any order in the rule file, with the exception of the package
statement, which must be at the top of the file. In all cases, the semicolons are
optional.

Figure 7.3. package

Notice that any rule attribute (as described the section Rule Attributes)
may also be written at package level, superseding the attribute's default value.
The modified default may still be replaced by an attribute setting within
a rule.

7.5.1. import

Figure 7.4. import

Import statements work like import statements in Java. You need to
specify the fully qualified paths and type names for any objects you want
to use in the rules. Drools automatically imports classes from the
Java package of the same name, and also from the package
java.lang.

7.5.2. global

Figure 7.5. global

With global you define global variables. They are used to make
application objects available to the rules. Typically, they are used
to provide data or services that the rules use, especially application
services used in rule consequences, and to return data from the rules,
like logs or values added in rule consequences, or for the rules to
interact with the application, doing callbacks. Globals are not
inserted into the Working Memory, and therefore a global should never be
used to establish conditions in rules except when it has a
constant immutable value. The engine cannot be notified about value
changes of globals and does not track their changes. Incorrect use
of globals in constraints may yield surprising results - surprising
in a bad way.

If multiple packages declare globals with the same identifier they
must be of the same type and all of them will reference the same global
value.

In order to use globals you must:

Declare your global variable in your rules file and use it in
rules. Example:

Note that these are just named instances of objects that you pass in
from your application to the working memory. This means you can pass in
any object you want: you could pass in a service locator, or perhaps a
service itself. With the new from element it is now common to pass a
Hibernate session as a global, to allow from to pull data from a named
Hibernate query.

One example may be an instance of a Email service. In your
integration code that is calling the rule engine, you obtain your
emailService object, and then set it in the working memory. In the DRL,
you declare that you have a global of type EmailService, and give it the
name "email". Then in your rule consequences, you can use things like
email.sendSMS(number, message).

Globals are not designed to share data between rules and they should
never be used for that purpose. Rules always reason and react to the
working memory state, so if you want to pass data from rule to rule, assert
the data as facts into the working memory.

It is strongly discouraged to set or change a global value from
inside your rules. We recommend to you always set the value from your
application using the working memory interface.

7.6. Function

Figure 7.6. function

Functions are a way to put semantic code in your rule source file, as
opposed to in normal Java classes. They can't do anything more than what you
can do with helper classes. (In fact, the compiler generates the helper class
for you behind the scenes.) The main advantage of using functions in a rule
is that you can keep the logic all in one place, and you can change the
functions as needed (which can be a good or a bad thing). Functions are most
useful for invoking actions on the consequence (then) part of a rule,
especially if that particular action is used over and over again, perhaps
with only differing parameters for each rule.

A typical function declaration looks like:

function String hello(String name) {
return "Hello "+name+"!";
}

Note that the function keyword is used, even though its not really
part of Java. Parameters to the function are defined as for a method, and
you don't have to have parameters if they are not needed. The return type
is defined just like in a regular method.

Alternatively, you could use a static method in a helper class,
e.g., Foo.hello(). Drools supports the use of
function imports, so all you would need to do is:

import function my.package.Foo.hello

Irrespective of the way the function is defined or imported, you
use a function by calling it by its name, in the consequence or inside
a semantic code block. Example:

7.7. Type Declaration

Figure 7.7. meta_data

Figure 7.8. type_declaration

Type declarations have two main goals in the rules engine: to allow
the declaration of new types, and to allow the declaration of metadata for
types.

Declaring new types: Drools works
out of the box with plain Java objects as facts. Sometimes, however,
users may want to define the model directly to the rules engine, without
worrying about creating models in a lower level language like Java. At
other times, there is a domain model already built, but eventually the
user wants or needs to complement this model with additional entities
that are used mainly during the reasoning process.

Declaring metadata: facts may
have meta information associated to them. Examples of meta information
include any kind of data that is not represented by the fact attributes
and is consistent among all instances of that fact type. This meta
information may be queried at runtime by the engine and used in the
reasoning process.

7.7.1. Declaring New Types

To declare a new type, all you need to do is use the keyword
declare, followed by the list of fields, and the
keyword end. A new fact must have a list of fields,
otherwise the engine will look for an existing fact class in the classpath
and raise an error if not found.

Example 7.10. Declaring a new fact type: Address

declare Address
number : int
streetName : String
city : String
end

The previous example declares a new fact type called
Address. This fact type will have three attributes:
number, streetName and city. Each
attribute has a type that can be any valid Java type, including any other
class created by the user or even other fact types previously
declared.

When you declare a new fact type, Drools will, at compile time,
generate bytecode that implements a Java class representing the fact type.
The generated Java class will be a one-to-one Java Bean mapping of the
type definition. So, for the previous example, the generated Java class
would be:

7.7.2. Declaring Metadata

Metadata may be assigned to several different constructions in
Drools: fact types, fact attributes and rules. Drools uses the at sign
('@') to introduce metadata, and it always uses the form:

@metadata_key( metadata_value )

The parenthesized metadata_value is
optional.

For instance, if you want to declare a metadata attribute like
author, whose value is Bob, you could
simply write:

Example 7.15. Declaring a metadata attribute

@author( Bob )

Drools allows the declaration of any arbitrary metadata attribute,
but some will have special meaning to the engine, while others are simply
available for querying at runtime. Drools allows the declaration of
metadata both for fact types and for fact attributes. Any metadata that is
declared before the attributes of a fact type are assigned to the fact
type, while metadata declared after an attribute are assigned to that
particular attribute.

In the previous example, there are two metadata items declared for
the fact type (@author and @dateOfCreation) and
two more defined for the name attribute (@key and
@maxLength). Please note that the @key metadata
has no required value, and so the parentheses and the value were
omitted.:

7.7.2.1. Predefined class level annotations

Some annotations have predefined semantics that are interpreted by
the engine. The following is a list of some of these predefined
annotations and their meaning.

7.7.2.1.1. @role( <fact | event> )

The @role annotation defines how the engine should handle instances of that type:
either as regular facts or as events. It accepts two possible values:

fact : this is the default, declares that the type is to be
handled as a regular fact.

event : declares that the type is to be handled as an
event.

The following example declares that the fact type StockTick in a stock broker
application is to be handled as an event.

Example 7.17. declaring a fact type as an event

import some.package.StockTick
declare StockTick
@role( event )
end

The same applies to facts declared inline. If StockTick was a fact type declared in
the DRL itself, instead of a previously existing class, the code would be:

7.7.2.1.2. @typesafe( <boolean> )

By default all type declarations are compiled with type safety
enabled; @typesafe( false ) provides a means to override this
behaviour by permitting a fall-back, to type unsafe evaluation where
all constraints are generated as MVEL constraints and executed
dynamically. This can be important when dealing with collections that
do not have any generics or mixed type collections.

7.7.2.1.3. @timestamp( <attribute name> )

Every event has an associated timestamp assigned to it. By default,
the timestamp for a given event is read from the Session Clock and
assigned to the event at the time the event is inserted into the working
memory. Although, sometimes, the event has the timestamp as one of its
own attributes. In this case, the user may tell the engine to use the
timestamp from the event's attribute instead of reading it from the
Session Clock.

@timestamp( <attributeName> )

To tell the engine what attribute to use as the source of the
event's timestamp, just list the attribute name as a parameter to the
@timestamp tag.

Example 7.19. declaring the VoiceCall timestamp attribute

declare VoiceCall
@role( event )
@timestamp( callDateTime )
end

7.7.2.1.4. @duration( <attribute name> )

Drools supports both event semantics: point-in-time events and
interval-based events. A point-in-time event is represented as an
interval-based event whose duration is zero. By default, all events have
duration zero. The user may attribute a different duration for an event by
declaring which attribute in the event type contains the duration of the
event.

7.7.2.1.5. @expires( <time interval> )

Important

This tag is only considered when running the engine in STREAM
mode. Also, additional discussion on the effects of using this tag is
made on the Memory Management section. It is included here for
completeness.

Events may be automatically expired after some time in the working
memory. Typically this happens when, based on the existing rules in the
knowledge base, the event can no longer match and activate any rules.
Although, it is possible to explicitly define when an event should
expire.

@expires( <timeOffset> )

The value of timeOffset is a temporal interval
in the form:

[#d][#h][#m][#s][#[ms]]

Where [ ] means an optional parameter and
# means a numeric value.

So, to declare that the VoiceCall facts should be expired after 1
hour and 35 minutes after they are inserted into the working memory, the
user would write:

Example 7.21. declaring the expiration offset for the VoiceCall events

The @expires policy will take precedence and override the implicit
expiration offset calculated from temporal constraints and sliding windows
in the knowledge base.

7.7.2.1.6. @propertyChangeSupport

Facts that implement support for property changes as defined in
the Javabean(tm) spec, now can be annotated so that the engine
register itself to listen for changes on fact properties. The boolean
parameter that was used in the insert() method in the Drools 4 API is
deprecated and does not exist in the drools-api module.

7.7.2.1.7. @propertyReactive

7.7.2.2. Predefined attribute level annotations

As noted before, Drools also supports annotations in type
attributes. Here is a list of predefined attribute annotations.

7.7.2.2.1. @key

Declaring an attribute as a key attribute has 2 major effects on
generated types:

The attribute will be used as a key identifier for the
type, and as so, the generated class will implement the equals()
and hashCode() methods taking the attribute into account when
comparing instances of this type.

Drools will generate a constructor using all the key
attributes as parameters.

For the previous example, Drools will generate equals() and
hashCode() methods that will check the firstName and lastName
attributes to determine if two instances of Person are equal to each
other, but will not check the age attribute. It will also generate a
constructor taking firstName and lastName as parameters, allowing one
to create instances with a code like this:

Example 7.24. creating an instance using the key constructor

Person person = new Person( "John", "Doe" );

7.7.2.2.2. @position

Patterns support positional arguments on type declarations.

Positional arguments are ones where you don't need to specify the field name, as the
position maps to a known named field. i.e. Person( name == "mark" ) can be rewritten as
Person( "mark"; ). The semicolon ';' is important so that the engine knows that everything
before it is a positional argument. Otherwise we might assume it was a boolean expression,
which is how it could be interpreted after the semicolon. You can mix positional and named
arguments on a pattern by using the semicolon ';' to separate them. Any variables used in
a positional that have not yet been bound will be bound to the field that maps to that
position.

declare Cheese
name : String
shop : String
price : int
end

The default order is the declared order, but this can be overridden using
@position

The @Position annotation, in the org.drools.definition.type package, can be used to
annotate original pojos on the classpath. Currently only fields on classes can be
annotated. Inheritance of classes is supported, but not interfaces of methods yet.

Example patterns, with two constraints and a binding. Remember semicolon ';' is used
to differentiate the positional section from the named argument section. Variables and
literals and expressions using just literals are supported in positional arguments, but
not variables.

@Position is inherited when beans extend each other; while not recommended, two fields
may have the same @position value, and not all consecutive values need be declared. If a
@position is repeated, the conflict is solved using inheritance (fields in the superclass
have the precedence) and the declaration order. If a @position value is missing, the first
field without an explicit @position (if any) is selected to fill the gap. As always,
conflicts are resolved by inheritance and declaration order.

In the example, the field order would be : price (@position 0 in the superclass),
year (@position 0 in the subclass), name (first field with no @position), shop
(@position 2), country (second field without @position), origin.

7.7.3. Declaring Metadata for Existing Types

Drools allows the declaration of metadata attributes for existing
types in the same way as when declaring metadata attributes for new fact
types. The only difference is that there are no fields in that
declaration.

For instance, if there is a class org.drools.examples.Person, and
one wants to declare metadata for it, it's possible to write the following
code:

Instead of using the import, it is also possible to reference the
class by its fully qualified name, but since the class will also be
referenced in the rules, it is usually shorter to add the import and use
the short class name everywhere.

7.7.5. Non Typesafe Classes

@typesafe( <boolean>) has been added to type declarations. By
default all type declarations are compiled with type safety enabled;
@typesafe( false ) provides a means to override this behaviour by
permitting a fall-back, to type unsafe evaluation where all constraints
are generated as MVEL constraints and executed dynamically. This can be
important when dealing with collections that do not have any generics or
mixed type collections.

7.7.6. Accessing Declared Types from the Application Code

Declared types are usually used inside rules files, while Java
models are used when sharing the model between rules and applications.
Although, sometimes, the application may need to access and handle facts
from the declared types, especially when the application is wrapping the
rules engine and providing higher level, domain specific user interfaces
for rules management.

In such cases, the generated classes can be handled as usual with
the Java Reflection API, but, as we know, that usually requires a lot of
work for small results. Therefore, Drools provides a simplified API for
the most common fact handling the application may want to do.

The first important thing to realize is that a declared fact will
belong to the package where it was declared. So, for instance, in the
example below, Person will belong to the
org.drools.examples package, and so the fully qualified name
of the generated class will be
org.drools.examples.Person.

Declared types, as discussed previously, are generated at knowledge
base compilation time, i.e., the application will only have access to them
at application run time. Therefore, these classes are not available for
direct reference from the application.

Drools then provides an interface through which users can handle
declared types from the application code:
org.drools.definition.type.FactType. Through this interface,
the user can instantiate, read and write fields in the declared fact
types.

7.7.8. Traits

WARNING : this feature is still experimental and subject to changes

The same fact may have multiple dynamic types which do not fit naturally in a class
hierarchy. Traits allow to model this very common scenario. A trait is an interface that can
be applied (and eventually removed) to an individual object at runtime. To create a trait
rather than a traditional bean, one has to declare them explicitly as in the following
example:

At runtime, this declaration results in an interface, which can be used to write patterns,
but can not be instantiated directly. In order to apply a trait to an object, we provide the
new don keyword, which can be used as simply as this:

when a core object dons a trait, a proxy class is created on the fly (one such class will
be generated lazily for each core/trait class combination). The proxy instance, which wraps
the core object and implements the trait interface, is inserted automatically and will
possibly activate other rules. An immediate advantage of declaring and using interfaces,
getting the implementation proxy for free from the engine, is that multiple inheritance
hierarchies can be exploited when writing rules. The core classes, however, need not implement
any of those interfaces statically, also facilitating the use of legacy classes as cores. In
fact, any object can don a trait, provided that they are declared as @Traitable. Notice that
this annotation used to be optional, but now is mandatory.

The only connection between core classes and trait interfaces is at the proxy level: a
trait is not specifically tied to a core class. This means that the same trait can be applied
to totally different objects. For this reason, the trait does not transparently expose the
fields of its core object. So, when writing a rule using a trait interface, only the fields of
the interface will be available, as usual. However, any field in the interface that
corresponds to a core object field, will be mapped by the proxy class:

In this case, the code and balance would be read from the underlying Customer object.
Likewise, the setAccount will modify the underlying object, preserving a strongly typed access
to the data structures. A hard field must have the same name and type both in the core class
and all donned interfaces. The name is used to establish the mapping: if two fields have the
same name, then they must also have the same declared type. The annotation
@org.drools.core.factmodel.traits.Alias allows to relax this restriction. If an @Alias is
provided, its value string will be used to resolve mappings instead of the original field
name. @Alias can be applied both to traits and core beans.

More work is being done on reaxing this constraint (see the experimental section on
"logical" traits later). Now, one might wonder what happens when a core class does NOT provide
the implementation for a field defined in an interface. We call hard fields those trait fields
which are also core fields and thus readily available, while we define soft those fields which
are NOT provided by the core class. Hidden fields, instead, are fields in the core class not
exposed by the interface.

So, while hard field management is intuitive, there remains the problem of soft and hidden
fields. Hidden fields are normally only accessible using the core class directly. However, the
"fields" Map can be used on a trait interface to access a hidden field. If the field can't be
resolved, null will be returned. Notice that this feature is likely to change in the
future.

Example 7.34.

when
$sc : GoldenCustomer( fields[ "age" ] > 18 ) // age is declared by the underlying core class, but not by GoldenCustomer
then

Soft fields, instead, are stored in a Map-like data structure that is specific to each
core object and referenced by the proxy(es), so that they are effectively shared even when an
object dons multiple traits.

A core object also holds a reference to all its proxies, so that it is possible to track
which type(s) have been added to an object, using a sort of dynamic "instanceof" operator,
which we called isA. The operator can accept a String, a class literal or a list of class
literals. In the latter case, the constraint is satisfied only if all the traits have been
donned.

Eventually, the business logic may require that a trait is removed from a wrapped object.
To this end, we provide two options. The first is a "logical don", which will result in a
logical insertion of the proxy resulting from the traiting operation. The TMS will ensure that
the trait is removed when its logical support is removed in the first place.

The second is the use of the "shed" keyword, which causes the removal of any type that is
a subtype (or equivalent) of the one passed as an argument. Notice that, as of version 5.5,
shed would only allow to remove a single specific trait.

This operation returns another proxy implementing the org.drools.core.factmodel.traits.Thing interface, where
the getFields() and getCore()
methods are defined. Internally, in fact, all declared traits are generated to extend this interface (in addition
to any others specified). This allows to preserve the wrapper with the soft fields which would otherwise be lost.

A trait and its proxies are also correlated in another way. Starting from version 5.6,
whenever a core object is "modified", its proxies are "modified" automatically as well, to
allow trait-based patterns to react to potential changes in hard fields. Likewise, whenever a
trait proxy (mached by a trait pattern) is modified, the modification is propagated to the
core class and the other traits. Morover, whenever a don operation is performed, the core
object is also modified automatically, to reevaluate any "isA" operation which may be
triggered.

Potentially, this may result in a high number of modifications, impacting performance (and
correctness) heavily. So two solutions are currently implemented. First, whenever a core
object is modified, only the most specific traits (in the sense of inheritance between trait
interfaces) are updated and an internal blocking mechanism is in place to ensure that each
potentially matching pattern is evaluated once and only once. So, in the following
situation:

a modification of an object that is both a GoldenCustomer, a NationalGoldenCustomer and a
SeniorGoldenCustomer wold cause only the latter two proxies to be actually modified. The
first would match any pattern for GoldenCustomer and NationalGoldenCustomer; the latter would
instead be prevented from rematching GoldenCustomer, but would be allowed to match
SeniorGoldenCustomer patterns. It is not necessary, instead, to modify the GoldenCustomer
proxy since it is already covered by at least one other more specific trait.

The second method, up to the usr, is to mark traits as @PropertyReactive. Property
reactivity is trait-enabled and takes into account the trait field mappings, so to block
unnecessary propagations.

7.7.8.1. Cascading traits

WARNING : This feature is extremely experimental and
subject to changes

Normally, a hard field must be exposed with its original type by all traits donned by an
object, to prevent situations such as

Should a Person don both Customer and Patient, the type of the hard field id would be
ambiguous. However, consider the following example, where GoldenCustomers refer their best
friends so that they become Customers as well:

Aside from the @Alias, a Person-as-GoldenCustomer's best friend might be compatible with
the requirements of the trait GoldenCustomer, provided that they are some kind of Customer
themselves. Marking a Person as "logically traitable" - i.e. adding the annotation
@Traitable( logical = true ) - will instruct the engine to try and preserve the logical
consistency rather than throwing an exception due to a hard field with different type
declarations (Person vs Customer). The following operations would then work:

Notice that, by the time p1 becomes GoldenCustomer, p2 must have already become a
Customer themselves, otherwise a runtime exception will be thrown since the very definition
of GoldenCustomer would have been violated.

In some cases, however, one might want to infer, rather than verify, that p2 is a
Customer by virtue that p1 is a GoldenCustomer. This modality can be enabled by marking
Customer as "logical", using the annotation @org.drools.core.factmodel.traits.Trait( logical
= true ). In this case, should p2 not be a Customer by the time that p1 becomes a
GoldenCustomer, it will be automatically don the trait Customer to preserve the logical
integrity of the system.

Notice that the annotation on the core class enables the dynamic type management for its
fields, whereas the annotation on the traits determines whether they will be enforced as
integrity constraints or cascaded dynamically.

7.8. Rule

Figure 7.9. rule

A rule specifies that when a particular set of
conditions occur, specified in the Left Hand Side (LHS),
then do what queryis 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.

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
enclosed in double quotes (it is best to always use double quotes).

Attributes - described below - are optional. They are best written one
per line.

The LHS of the rule follows the when keyword
(ideally on a new line), similarly the RHS follows the
then keyword (again, ideally on a newline). The rule is
terminated by the keyword end. Rules cannot be
nested.

Example 7.43. Rule Syntax Overview

rule "<name>"
<attribute>*
when
<conditional element>*
then
<action>*
end

7.8.1. Rule Attributes

Rule attributes provide a declarative way to influence the behavior
of the rule. Some are quite simple, while others are part of complex
subsystems such as ruleflow. To get the most from Drools you should make
sure you have a proper understanding of each attribute.

Figure 7.10. rule attributes

no-loop

default value: false

type: Boolean

When a rule's consequence modifies a fact it may cause the
rule to activate again, causing an infinite loop. Setting no-loop to
true will skip the creation of another Activation for the rule with
the current set of facts.

ruleflow-group

default value: N/A

type: String

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.

lock-on-active

default value: false

type: Boolean

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.

salience

default value: 0

type: integer

Each rule has an integer salience attribute 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.

Drools also supports dynamic salience where you can use an
expression involving bound variables.

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.

auto-focus

default value: false

type: Boolean

When a rule is activated where the auto-focus
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.

activation-group

default value: N/A

type: String

Rules that belong to the same activation-group, identified by
this attribute's string value, will only fire exclusively. More
precisely, the first rule in an activation-group to fire will
cancel all pending activations of all rules in the group, i.e., stop
them from firing.

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.

dialect

default value: as specified by the package

type: String

possible values: "java" or "mvel"

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.

date-effective

default value: N/A

type: String, containing a date and time definition

A rule can only activate if the current date and time is after
date-effective attribute.

date-expires

default value: N/A

type: String, containing a date and time definition

A rule cannot activate if the current date and time is after
the date-expires attribute.

duration

default value: no default value

type: long

The duration dictates that the rule will fire after a
specified duration, if it is still true.

Example 7.46. Some attribute examples

rule "my rule"
salience 42
agenda-group "number 1"
when ...

7.8.2. Timers and Calendars

Rules now support both interval and cron based timers, which replace
the now deprecated duration attribute.

A rule controlled by a timer becomes active when it matches, and
once for each individual match. Its consequence is executed
repeatedly, according to the timer's settings. This stops as soon
as the condition doesn't match any more.

Consequences are executed even after control returns from a call
to fireUntilHalt. Moreover, the Engine remains reactive to any
changes made to the Working Memory. For instance, removing a fact
that was involved in triggering the timer rule's execution causes
the repeated execution to terminate, or inserting a fact so that
some rule matches will cause that rule to fire. But the Engine is
not continually active, only after a rule fires, for whatever
reason. Thus, reactions to an insertion done asynchronously will
not happen until the next execution of a timer-controlled rule.
Disposing a session puts an end to all timer activity.

Conversely when the rule engine runs in passive mode (i.e.: using fireAllRules
instead of fireUntilHalt) by default it doesn't fire consequences of timed rules
unless fireAllRules isn't invoked again. However it is possible to change this
default behavior by configuring the KieSession with a TimedRuleExectionOption
as shown in the following example.

It is also possible to have a finer grained control on the timed rules that have to be
automatically executed. To do this it is necessary to set a FILTEREDTimedRuleExectionOption that allows to define a callback to filter those
rules, as done in the next example.

Example 7.50. Configuring a filter to choose which timed rules should be automatically executed

For what regards interval timers it is also possible to define both the delay
and interval as an expression instead of a fixed value. To do that it is necessary to
use an expression timer (indicated by "expr:") as in the following example:

The expressions, $d and $p in this case, can use any variable defined in the
pattern matching part of the rule and can be any String that can be parsed in a time
duration or any numeric value that will be internally converted in a long representing
a duration expressed in milliseconds.

Both interval and expression timers can have 3 optional parameters named
"start", "end" and "repeat-limit". When one or more of these parameters are used the first
part of the timer definition must be followed by a semicolon ';' and the parameters have
to be separated by a comma ',' as in the following example:

Example 7.52. An Interval Timer with a start and an end

timer (int:30s 10s; start=3-JAN-2010, end=5-JAN-2010)

The value for start and end parameters can be a Date, a String representing
a Date or a long, or more in general any Number, that will be transformed in a Java Date
applying the following conversion:

newDate(((Number) n).longValue())

Conversely the repeat-limit can be only an integer and it defines the maximum
number of repetitions allowed by the timer. If both the end and the repeat-limit parameters
are set the timer will stop when the first of the two will be matched.

The using of the start parameter implies the definition of a phase for the timer,
where the beginning of the phase is given by the start itself plus the eventual delay.
In other words in this case the timed rule will then be scheduled at times:

start + delay + n*period

for up to repeat-limit times and no later than the end timestamp (whichever first).
For instance the rule having the following interval timer

timer (int:30s 1m; start="3-JAN-2010")

will be scheduled at the 30th second of every minute after the midnight of the
3-JAN-2010. This also means that if for example you turn the system on at midnight of
the 3-FEB-2010 it won't be scheduled immediately but will preserve the phase defined by
the timer and so it will be scheduled for the first time 30 seconds after the midnight.
If for some reason the system is paused (e.g. the session is serialized and then deserialized
after a while) the rule will be scheduled only once to recover from missing activations
(regardless of how many activations we missed) and subsequently it will be scheduled
again in phase with the timer.

Calendars are used to control when rules can fire. The Calendar API
is modelled on Quartz:

7.8.3. Left Hand Side (when) syntax

7.8.3.1. What is the Left Hand Side?

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 empty, it will be considered as a condition element that is
always true and it will be activated once, when a new WorkingMemory
session is created.

Conditional elements work on one or more
patterns (which are described below). The most
common conditional element is "and". Therefore it is
implicit when you have multiple patterns in the LHS of a rule that are
not connected in any way:

Note

An "and" cannot have a leading declaration
binding (unlike for example or). This is obvious,
since a declaration can only reference a single fact at a time, and
when the "and" is satisfied it matches both facts -
so which fact would the declaration bind to?

7.8.3.2. Pattern (conditional element)

7.8.3.2.1. What is a pattern?

A pattern element is the most important Conditional Element. It
can potentially match on each fact that is inserted in the working
memory.

A pattern contains of zero or more constraints and has an
optional pattern binding. The railroad diagram below shows the syntax
for this.

Figure 7.12. Pattern

In its simplest form, with no constraints, a pattern matches
against a fact of the given type. In the following case the type is
Cheese, which means that the pattern will match against
all Person objects in the Working Memory:

Person()

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.

Object() // matches all objects in the working memory

Inside of the pattern parenthesis is where all the action
happens: it defines the constraints for that pattern. For example,
with a age related constraint:

Person( age == 100 )

Note

For backwards compatibility reasons it's allowed to suffix
patterns with the ; character. But it is not
recommended to do that.

7.8.3.2.2. Pattern binding

For referring to the matched object, use a pattern binding
variable such as $p.

The prefixed dollar symbol ($) is just a
convention; it can be useful in complex rules where it helps to easily
differentiate between variables and fields, but it is not
mandatory.

7.8.3.3. Constraint (part of a pattern)

7.8.3.3.1. What is a constraint?

A constraint is an expression that returns
true or false. This example has
a constraint that states 5 is smaller than
6:

Person( 5 < 6 ) // just an example, as constraints like this would be useless in a real pattern

In essence, it's a Java expression with some enhancements (such
as property access) and a few differences (such as
equals() semantics for ==).
Let's take a deeper look.

7.8.3.3.2. Property access on Java Beans (POJO's)

Any bean property can be used directly. A bean property is
exposed using a standard Java bean getter: a method
getMyProperty() (or
isMyProperty() for a primitive boolean) which takes
no arguments and return something. For example: the age property is
written as age in DRL instead of the getter
getAge():

Person( age == 50 )
// this is the same as:
Person( getAge() == 50 )

Drools uses the standard JDK Introspector
class to do this mapping, so it follows the standard Java bean
specification.

Note

We recommend using property access (age)
over using getters explicitly (getAge()) because
of performance enhancements through field indexing.

Warning

Property accessors must not 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.

public int getAge() {
age++; // Do NOT do this
return age;
}

public int getAge() {
Date now = DateUtil.now(); // Do NOT do this
return DateUtil.differenceInYears(now, birthday);
}

To solve this latter case, insert a fact that wraps the
current date into working memory and update that fact between
fireAllRules as needed.

Note

The following fallback applies: if the getter of a property
cannot be found, the compiler will resort to using the property name
as a method name and without arguments:

Person( age == 50 )
// If Person.getAge() does not exists, this falls back to:
Person( age() == 50 )

Warning

In a stateful session, 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. Either consider them
immutable while any of their parent references are inserted into the
Working Memory. Or, instead, if you wish to modify a nested value
you should mark all of the outer facts as updated. In the above
example, when the houseNumber changes, any
Person with that Address must
be marked as updated.

7.8.3.3.3. Java expression

You can use any Java expression that returns a
boolean as a constraint inside the parentheses of a
pattern. Java expressions can be mixed with other expression
enhancements, such as property access:

Person( age == 50 )

It is possible to change the evaluation priority by using
parentheses, as in any logic or mathematical expression:

Person( age > 100 && ( age % 10 == 0 ) )

It is possible to reuse Java methods:

Person( Math.round( weight / ( height * height ) ) < 25.0 )

Warning

As for property accessors, methods must not change the state
of the object in a way that may affect the rules. Any method
executed on a fact in the LHS should be a read
only method.

Person( incrementAndGetAge() == 10 ) // Do NOT do this

Warning

The state of a fact should not change between rule invocations
(unless those facts are marked as updated to the working memory on
every change):

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:

Person( age == "10" ) // "10" is coerced to 10

7.8.3.3.4. Comma separated AND

The comma character (',') is used to separate
constraint groups. It has implicit AND connective
semantics.

Note

Although the && and
, operators have the same semantics, they are
resolved with different priorities: The
&& operator precedes the
|| operator. Both the
&& and || operator
precede the , operator. See the operator
precedence list below.

The comma operator should be preferred at the top level
constraint, as it makes constraints easier to read and the engine
will often be able to optimize them better.

The comma (,) operator cannot be embedded in
a composite constraint expression, such as parentheses:

Bound variable restrictions using the operator
== provide for very fast execution as it use hash
indexing to improve performance.

7.8.3.3.6. Unification

Drools does not allow bindings to the same declaration. However
this is an important aspect to derivation query unification. While
positional arguments are always processed with unification a special
unification symbol, ':=', was introduced for named arguments named
arguments. The following "unifies" the age argument across two
people.

Person( $age := age )
Person( $age := age)

In essence unification will declare a binding for the first
occurrence and constrain to the same value of the bound field for
sequence occurrences.

7.8.3.3.7. Grouped accessors for nested objects

Often it happens that it is necessary to access multiple properties
of a nested object as in the following example

These accessors to nested objects can be grouped with a '.(...)'
syntax providing more readable rules as in

Person( name== "mark", address.( city == "london", country == "uk") )

Note the '.' prefix, this is necessary to differentiate the nested
object constraints from a method call.

7.8.3.3.8. Inline casts and coercion

When dealing with nested objects, it also quite common the need to
cast to a subtype. It is possible to do that via the # symbol as in:

Person( name=="mark", address#LongAddress.country == "uk" )

This example casts Address to LongAddress, making its getters available.
If the cast is not possible (instanceof returns false), the evaluation will
be considered false. Also fully qualified names are supported:

7.8.3.3.9. Special literal support

7.8.3.3.9.1. Date literal

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
drools.dateformat. If more control is required, use a
restriction.

7.8.3.3.12. Special DRL operators

Coercion to the correct value for the evaluator and the field
will be attempted.

7.8.3.3.12.1. The operators <<=>>=

These operators can be used on properties with natural
ordering. For example, for Date fields, <
means before, for String
fields, it means alphabetically lower.

Person( firstName < $otherFirstName )

Person( birthDate < $otherBirthDate )

Only applies on Comparable
properties.

7.8.3.3.12.2. Null-safe dereferencing operator

The !. operator allows to derefencing in a null-safe way.
More in details the matching algorithm requires the value to the left
of the !. operator to be not null in order to give a positive result
for pattern matching itself. In other words the pattern:

Person( $streetName : address!.street )

will be internally translated in:

Person( address != null, $streetName : address.street )

7.8.3.3.12.3. The operator matches

Matches a field against any valid Java Regular Expression. Typically that regexp is a string
literal, but variables that resolve to a valid regexp are also
allowed.

Example 7.60. Regular Expression Constraint

Cheese( type matches "(Buffalo)?\\S*Mozarella" )

Note

Like in Java, regular expressions written as string literals
need to escape '\'.

Only applies on String properties.
Using matches against a null value
always evaluates to false.

7.8.3.3.12.4. The operator not matches

The operator returns true if the String does not match the
regular expression. The same rules apply as for the
matches operator. Example:

Example 7.61. Regular Expression Constraint

Cheese( type not matches "(Buffulo)?\\S*Mozarella" )

Only applies on String properties.
Using not matches against a null value
always evaluates to true.

7.8.3.3.12.5. The operator contains

The operator contains is used to check
whether a field that is a Collection or elements contains the specified
value.

7.8.3.3.12.6. The operator not contains

The operator not contains is used to check
whether a field that is a Collection or elements does not
contain the specified value.

Example 7.63. Literal Constraint with Collections

CheeseCounter( cheeses not contains "cheddar" ) // not contains with a String literal
CheeseCounter( cheeses not contains $var ) // not contains with a variable

Only applies on Collection
properties.

Note

For backward compatibility, the
excludes operator is supported as a synonym
for not contains.

7.8.3.3.12.7. The operator memberOf

The operator memberOf is used to check
whether a field is a member of a collection or elements; that
collection must be a variable.

Example 7.64. Literal Constraint with Collections

CheeseCounter( cheese memberOf $matureCheeses )

7.8.3.3.12.8. The operator not memberOf

The operator not memberOf is used to check
whether a field is not a member of a collection or elements; that
collection must be a variable.

Example 7.65. Literal Constraint with Collections

CheeseCounter( cheese not memberOf $matureCheeses )

7.8.3.3.12.9. The operator soundslike

This operator is similar to matches, but it
checks whether a word has almost the same sound (using English
pronunciation) as the given value. This is based on the Soundex
algorithm (see
http://en.wikipedia.org/wiki/Soundex).

7.8.3.3.12.10. The operator str

This operator str is used to check whether
a field that is a String starts with or ends with
a certain value. It can also be used to check the length of the
String.

Message( routingValue str[startsWith] "R1" )

Message( routingValue str[endsWith] "R2" )

Message( routingValue str[length] 17 )

7.8.3.3.12.11. The operators in and not
in (compound value restriction)

The compound value restriction is used where there is more
than one possible value to match. Currently only the
in and not in 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
==.

7.8.3.3.13. Inline eval operator (deprecated)

Figure 7.17. Inline Eval Expression

An 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
eval's.

This example will find all male-female pairs where the male is 2
years older than the female; the variable age is
auto-created in the second pattern by the autovivification
process.

Note

Inline eval's are effectively obsolete as their inner syntax
is now directly supported. It's recommended not to use them. Simply
write the expression without wrapping eval() around it.

7.8.3.3.14. Operator precedence

The operators are evaluated in this precedence:

Table 7.1. Operator precedence

Operator type

Operators

Notes

(nested / null safe) property access

.!.

Not normal Java semantics

List/Map access

[ ]

Not normal Java semantics

constraint binding

:

Not normal Java semantics

multiplicative

*/%

additive

+-

shift

<<>>>>>

relational

<><=>=instanceof

equality

==!=

Does not use normal Java (not)
same semantics: uses
(not) equals
semantics instead.

non-short circuiting AND

&

non-short circuiting exclusive OR

^

non-short circuiting inclusive OR

|

logical AND

&&

logical OR

||

ternary

? :

Comma separated AND

,

Not normal Java semantics

7.8.3.4. Positional Arguments

Patterns now support positional arguments on type
declarations.

Positional arguments are ones where you don't need to specify the
field name, as the position maps to a known named field. i.e. Person(
name == "mark" ) can be rewritten as Person( "mark"; ). The semicolon
';' is important so that the engine knows that everything before it is a
positional argument. Otherwise we might assume it was a boolean
expression, which is how it could be interpreted after the semicolon.
You can mix positional and named arguments on a pattern by using the
semicolon ';' to separate them. Any variables used in a positional that
have not yet been bound will be bound to the field that maps to that
position.

declare Cheese
name : String
shop : String
price : int
end

Example patterns, with two constraints and a binding. Remember
semicolon ';' is used to differentiate the positional section from the
named argument section. Variables and literals and expressions using
just literals are supported in positional arguments, but not variables.
Positional arguments are always resolved using unification.

Positional arguments that are given a previously declared binding
will constrain against that using unification; these are referred to as
input arguments. If the binding does not yet exist, it will create the
declaration binding it to the field represented by the position
argument; these are referred to as output arguments.

7.8.3.5. Fine grained property change listeners

When you call modify() (see the modify statement section) on a given object it will trigger a revaluation of all
patterns of the matching object type in the knowledge base. This can can lead to unwanted and useless evaluations
and in the worst cases to infinite recursions. The only workaround to avoid it was to split up your objects into
smaller ones having a 1 to 1 relationship with the original object.

This feature allows the pattern matching to only react to modification of properties actually
constrained or bound inside of a given pattern. That will help with performance and recursion and avoid artificial
object splitting.

By default this feature is off in order to make the behavior of the rule engine backward compatible with the
former releases. When you want to activate it on a specific bean you have to annotate it with @propertyReactive.
This annotation works both on DRL type declarations:

you won't have to add the no-loop attribute to it in order to avoid an infinite recursion because the engine
recognizes that the pattern matching is done on the 'firstName' property while the RHS of the rule modifies the
'male' one. Note that this feature does not work for update(), and this is one of the reasons why we promote
modify() since it encapsulates the field changes within the statement. Moreover, on Java classes, you can also
annotate any method to say that its invocation actually modifies other properties. For instance in the former
Person class you could have a method like:

it will correctly recognize that the values of both properties 'firstName' and 'lastName' could have
potentially been modified and act accordingly, not missing of reevaluating the patterns constrained on them. At
the moment the usage of @Modifies is not allowed on fields but only on methods. This is coherent with the most
common scenario where the @Modifies will be used for methods that are not related with a class field as in the
Person.setName() in the former example. Also note that @Modifies is not transitive, meaning that if another method
internally invokes the Person.setName() one it won't be enough to annotate it with @Modifies( { "name" } ), but it
is necessary to use @Modifies( { "firstName", "lastName" } ) even on it. Very likely @Modifies transitivity will
be implemented in the next release.

For what regards nested accessors, the engine will be notified only for top level fields. In other words a
pattern matching like:

Person ( address.city.name == "London )

will be revaluated only for modification of the 'address' property of a Person object. In the same way the
constraints analysis is currently strictly limited to what there is inside a pattern. Another example could help
to clarify this. An LHS like the following:

$p : Person( )
Car( owner = $p.name )

will not listen on modifications of the person's name, while this one will do:

Person( $name : name )
Car( owner = $name )

To overcome this problem it is possible to annotate a pattern with @watch as it follows:

$p : Person( ) @watch ( name )
Car( owner = $p.name )

Indeed, annotating a pattern with @watch allows you to modify the inferred set of properties for which that
pattern will react. Note that the properties named in the @watch annotation are actually added to the ones
automatically inferred, but it is also possible to explicitly exclude one or more of them prepending their name
with a ! and to make the pattern to listen for all or none of the properties of the type used in the pattern
respectively with the wildcrds * and !*. So, for example, you can annotate a pattern in the LHS of a rule
like:

Since doesn't make sense to use this annotation on a pattern using a type not annotated with
@PropertyReactive the rule compiler will raise a compilation error if you try to do so. Also the duplicated usage
of the same property in @watch (for example like in: @watch( firstName, ! firstName ) ) will end up in a
compilation error. In a next release we will make the automatic detection of the properties to be listened smarter
by doing analysis even outside of the pattern.

It also possible to enable this feature by default on all the types of your model or to completely disallow
it by using on option of the KnowledgeBuilderConfiguration. In particular this new PropertySpecificOption can have
one of the following 3 values:

- DISABLED => the feature is turned off and all the other related annotations are just ignored
- ALLOWED => this is the default behavior: types are not property reactive unless they are not annotated with @PropertySpecific
- ALWAYS => all types are property reactive by default

So, for example, to have a KnowledgeBuilder generating property reactive types by default you could
do:

Note

The symbol || (as an alternative to
or) is deprecated. But it is still supported in
the syntax for backwards compatibility.

Figure 7.21. prefixOr

Prefix or is also supported:

(or Person( sex == "f", age > 60 )
Person( sex == "m", age > 65 )

Note

The behavior of the Conditional Element or
is different from the connective || for
constraints and restrictions in field constraints. The engine
actually has no understanding of the Conditional Element
or. Instead, via a number of different logic
transformations, a rule with or is rewritten as a
number of subrules. This process ultimately results in a rule that
has a single or 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.

The Conditional Element or 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:

Since the conditional element or 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.

The best way to think of the conditional element
or 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.

7.8.3.6.3. Conditional Element not

Figure 7.22. not

The CE not 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...".

The keyword not may 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.

7.8.3.6.4. Conditional Element exists

Figure 7.23. exists

The CE exists 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
exists 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 exists
pattern. Since only the existence matters, no bindings will be
established.

The keyword exists must be followed by
parentheses around the CEs that it applies to. In the simplest case of
a single pattern (like below) you may omit the parentheses.

7.8.3.7. Advanced conditional elements

7.8.3.7.1. Conditional Element forall

Figure 7.24. forall

The Conditional Element forall completes the
First Order Logic support in Drools. The Conditional Element
forall evaluates to true when all facts that match
the first pattern match all the remaining patterns. Example:

In the above rule, we "select" all Bus objects whose type is
"english". Then, for each fact that matches this pattern we evaluate
the following patterns and if they match, the forall CE will evaluate
to true.

To state that all facts of a given type in the working memory
must match a set of constraints, forall can be
written with a single pattern for simplicity. Example:

Forall can be nested inside other CEs. For instance,
forall can be used inside a not
CE. Note that only single patterns have optional parentheses, so that
with a nested forall parentheses must be
used:

Also, it is important to note that forall is
a scope delimiter. Therefore, it can use any
previously bound variable, but no variable bound inside it will be
available for use outside of it.

7.8.3.7.2. Conditional Element from

Figure 7.25. from

The Conditional Element from 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.

The expression used to define the object source is any
expression that follows regular MVEL syntax. Therefore, it allows you
to easily use object property navigation, execute method calls and
access maps and collections elements.

Here is a simple example of reasoning and binding on another
pattern sub-field:

Previous examples were evaluations using a single pattern. The
CE from also support object sources that return a
collection of objects. In that case, from 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:

rule "apply 10% discount to all items over US$ 100,00 in an order"
when
$order : Order()
$item : OrderItem( value > 100 ) from $order.items
then
// apply discount to $item
end

The above example will cause the rule to fire once for each item
whose value is greater than 100 for each given order.

You must take caution, however, when using
from, especially in conjunction with the
lock-on-active rule attribute as it may produce
unexpected results. Consider the example provided earlier, but now
slightly modified as follows:

rule "Assign people in North Carolina (NC) to sales region 1"
ruleflow-group "test"
lock-on-active true
when
$p : Person( )
$a : Address( state == "NC") from $p.address
then
modify ($p) {} // Assign person to sales region 1 in a modify block
end
rule "Apply a discount to people in the city of Raleigh"
ruleflow-group "test"
lock-on-active true
when
$p : Person( )
$a : Address( city == "Raleigh") from $p.address
then
modify ($p) {} // Apply discount to person in a modify block
end

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.

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 lock-on-active 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 from returns a new fact for all intents and
purposes each time it is evaluated.

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 modify 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 no-loop
attribute is ineffective, as it would only prevent a rule from
activating itself recursively. Hence, you resort to
lock-on-active.

There are several ways to address this issue:

Avoid the use of from when you can assert
all facts into working memory or use nested object references in
your constraint expressions (shown below).

Place the variable assigned used in the modify block as the
last sentence in your condition (LHS).

Avoid the use of lock-on-active when you
can explicitly manage how rules within the same rule-flow group
place activations on one another (explained below).

The preferred solution is to minimize use of
from 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:

rule "Assign people in North Carolina (NC) to sales region 1"
ruleflow-group "test"
lock-on-active true
when
$p : Person(address.state == "NC" )
then
modify ($p) {} // Assign person to sales region 1 in a modify block
end
rule "Apply a discount to people in the city of Raleigh"
ruleflow-group "test"
lock-on-active true
when
$p : Person(address.city == "Raleigh" )
then
modify ($p) {} //Apply discount to person in a modify block
end

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 from to reason over the
collection.

There are several ways to use from to achieve
this and not all of them exhibit an issue with the use of
lock-on-active. For example, the following use of
from causes both rules to fire as expected:

In the above example, the $addresses variable is returned from
the use of from. 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.

Though the above examples demonstrate how to combine the use of
from with lock-on-active 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.

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 from would not be
necessary.

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
lock-on-active. An alternative to
lock-on-active 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.

7.8.3.7.3. Conditional Element collect

Figure 7.26. collect

The Conditional Element collect 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:

import java.util.ArrayList
rule "Raise priority if system has more than 3 pending alarms"
when
$system : System()
$alarms : ArrayList( size >= 3 )
from collect( Alarm( system == $system, status == 'pending' ) )
then
// Raise priority, because system $system has
// 3 or more alarms pending. The pending alarms
// are $alarms.
end

In the above example, the rule will look for all pending alarms
in the working memory for each given system and group them in
ArrayLists. If 3 or more alarms are found for a given system, the rule
will fire.

The result pattern of collect can be any
concrete class that implements the java.util.Collection
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
java.util.Collection interface and provide a default
no-arg public constructor.

Both source and result patterns can be constrained as any other
pattern.

Variables bound before the collect 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
collect is a scope delimiter for bindings, so that
any binding made inside of it is not available for use outside of
it.

Collect accepts nested from CEs. The
following example is a valid use of "collect":

import java.util.LinkedList;
rule "Send a message to all mothers"
when
$town : Town( name == 'Paris' )
$mothers : LinkedList()
from collect( Person( gender == 'F', children > 0 )
from $town.getPeople()
)
then
// send a message to all mothers
end

7.8.3.7.4. Conditional Element accumulate

Figure 7.27. accumulate

The Conditional Element accumulate is a more flexible and powerful form of
collect, in the sense that it can be used to do what collect does and
also achieve results that the CE collect is not capable of achieving. Accumulate 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.

Accumulate supports both the use of pre-defined accumulate
functions, or the use of inline custom code. Inline custom code should
be avoided though, as it is harder for rule authors to maintain, and
frequently leads to code duplication. Accumulate functions are easier
to test and reuse.

The Accumulate CE also supports multiple different syntaxes. The
preferred syntax is the top level accumulate, as noted bellow, but all
other syntaxes are supported for backward compatibility.

7.8.3.7.4.1. Accumulate CE (preferred syntax)

The top level accumulate syntax is the most compact and
flexible syntax. The simplified syntax is as follows:

accumulate( <source pattern>; <functions> [;<constraints>] )

For instance, a rule to calculate the minimum, maximum and
average temperature reading for a given sensor and that raises an
alarm if the minimum temperature is under 20C degrees and the
average is over 70C degrees could be written in the following way,
using Accumulate:

Note

The DRL language defines "acc" as a synonym of "accumulate". The author
might prefer to use "acc" as a less verbose keyword or the full keyword
"accumulate" for legibility.

Accumulate Functions are all pluggable. That means that if needed, custom, domain specific functions can
easily be added to the engine and rules can start to use them without any restrictions. To implement a new
Accumulate Function all one needs to do is to create a Java class that implements the
org.drools.core.runtime.rule.TypedAccumulateFunction interface. As an example of an
Accumulate Function implementation, the following is the implementation of the average
function:

The code for the function is very simple, as we could expect, as all the "dirty" integration work is
done by the engine. Finally, to use the function in the rules, the author can import it using the "import
accumulate" statement:

import accumulate <class_name> <function_name>

For instance, if one implements the class some.package.VarianceFunction function that
implements the variance function and wants to use it in the rules, he would do the
following:

Example 7.77. Example of importing and using the custom "variance" accumulate function

Note

The built in functions (sum, average, etc) are imported automatically by the engine. Only user-defined
custom accumulate functions need to be explicitly imported.

Note

For backward compatibility, Drools still supports the configuration of accumulate functions through
configuration files and system properties, but this is a deprecated method. In order to configure the
variance function from the previous example using the configuration file or system property, the user
would set a property like this:

drools.accumulate.function.variance = some.package.VarianceFunction

Please note that "drools.accumulate.function." is a prefix that must always be used,
"variance" is how the function will be used in the drl files, and
"some.package.VarianceFunction" is the fully qualified name of the class that implements
the function behavior.

7.8.3.7.4.2. Alternate Syntax: single function with return type

The accumulate syntax evolved over time with the goal of
becoming more compact and expressive. Nevertheless, Drools still
supports previous syntaxes for backward compatibility
purposes.

In case the rule is using a single accumulate function on a
given accumulate, the author may add a pattern for the result object
and use the "from" keyword to link it to the accumulate result.
Example: a rule to apply a 10% discount on orders over $100 could be
written in the following way:

In the above example, the accumulate element is using only one
function (sum), and so, the rules author opted to explicitly write a
pattern for the result type of the accumulate function (Number) and
write the constraints inside it. There are no problems in using this
syntax over the compact syntax presented before, except that is is a
bit more verbose. Also note that it is not allowed to use both the
return type and the functions binding in the same accumulate statement.

7.8.3.7.4.3. Accumulate with inline custom code

Warning

The use of accumulate with inline custom code is not a good
practice for several reasons, including difficulties on maintaining
and testing rules that use them, as well as the inability of
reusing that code. Implementing your own accumulate functions is
very simple and straightforward, they are easy to unit test and to
use. This form of accumulate is supported for backward
compatibility only.

Another possible syntax for the accumulate is to define inline
custom code, instead of using accumulate functions. As noted on the
previous warned, this is discouraged though for the stated
reasons.

<source pattern>: the source
pattern is a regular pattern that the engine will try to match
against each of the source objects.

<init code>: 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.

<action code>: this is a
semantic block of code in the selected dialect that will be
executed for each of the source objects.

<reverse code>: 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 <action
code> block, so that the engine can do decremental
calculation when a source object is modified or deleted,
hugely improving performance of these operations.

<result expression>: this is a
semantic expression in the selected dialect that is executed
after all source objects are iterated.

<result pattern>: this is a
regular pattern that the engine tries to match against the
object returned from the <result
expression>. If it matches, the
accumulate conditional element evaluates to
true and the engine proceeds with the
evaluation of the next CE in the rule. If it does not matches,
the accumulate CE evaluates to
false and the engine stops evaluating CEs
for that rule.

In the above example, for each Order in the
Working Memory, the engine will execute the init
code initializing the total variable to zero. Then it
will iterate over all OrderItem objects for that order,
executing the action for each one (in the
example, it will sum the value of all items into the total
variable). After iterating over all OrderItem objects,
it will return the value corresponding to the result
expression (in the above example, the value of variable
total). Finally, the engine will try to match the
result with the Number pattern, and if the double value
is greater than 100, the rule will fire.

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.

As mentioned before, the reverse code is
optional, but it is strongly recommended that the user writes it in
order to benefit from the improved performance on update
and delete.

The accumulate CE can be used to execute
any action on source objects. The following example instantiates and
populates a custom object:

7.8.3.8. Conditional Element eval

Figure 7.28. eval

The conditional element eval 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 eval 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.

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.

For folks who are familiar with Drools 2.x lineage, the old Drools
parameter and condition tags are equivalent to binding a variable to an
appropriate type, and then using it in an eval node.

7.8.3.9. Railroad diagrams

7.8.4. The Right Hand Side (then)

7.8.4.1. Usage

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, delete or 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.

update(object,
handle); 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.

update(object);
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
update() when the object changes.). After a fact's field
values have changed you must call update before changing another fact,
or you will cause problems with the indexing within the rule engine. The
modify keyword avoids this problem.

insert(newSomething()); will place a new
object of your creation into the Working Memory.

insertLogical(newSomething()); is similar to
insert, but the object will be automatically deleted when there are no
more facts to support the truth of the currently firing rule.

delete(handle);
removes an object from Working Memory.

These convenience methods are basically macros that provide short
cuts to the KnowledgeHelper instance that lets you access
your Working Memory from rules files. The predefined variable
drools of type KnowledgeHelper lets you call
several other useful methods. (Refer to the KnowledgeHelper
interface documentation for more advanced operations).

The call drools.halt() terminates rule execution
immediately. This is required for returning control to the point
whence the current session was put to work with
fireUntilHalt().

Methods insert(Object o), update(Object
o) and delete(Object o) can be called on
drools as well, but due to their frequent use they can
be called without the object reference.

drools.getRule().getName(), called from a rule's
RHS, returns the name of the rule.

drools.getTuple() returns the Tuple that matches
the currently executing rule, and
drools.getActivation() delivers the corresponding
Activation. (These calls are useful for logging and debugging
purposes.)

The full Knowledge Runtime API is exposed through another
predefined variable, kcontext, of type
KieContext. Its method getKieRuntime() delivers
an object of type KieRuntime, which, in turn, provides access to a
wealth of methods, many of which are quite useful for coding RHS
logic.

The accessor getAgenda() returns a reference to
this session's Agenda, 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:

// give focus to the agenda group CleanUpkcontext.getKieRuntime().getAgenda().getAgendaGroup("CleanUp").setFocus();

(You can achieve the same using drools.setFocus(
"CleanUp" ).)

To run a query, you call getQueryResults(String
query), whereupon you may process the results, as explained
in section Query.

A set of methods dealing with event management lets you, among
other things, add and remove event listeners for the Working Memory
and the Agenda.

Method getKieBase() returns the
KieBase object, the backbone of all the Knowledge
in your system, and the originator of the current session.

You can manage globals with setGlobal(...),
getGlobal(...) and getGlobals().

Method getEnvironment() returns the runtime's
Environment which works much like what you know as your
operating system's environment.

7.8.4.2. The modify Statement

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
modify statement:

modify ( <fact-expression> ) {<expression> [ ,<expression> ]*
}

The parenthesized <fact-expression>
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.

Anyway this feature makes it possible to define more labelled consequences
other than the default one in a single rule, so, for example, the 2 former rules
can be compacted in only one like it follows:

This last rule has 2 consequences, the usual default one, plus another one
named "giveDiscount" that is activated, using the keyword do, as soon as a customer
older than 60 is found in the knowledge base, regardless of the fact that he owns a
car or not. The activation of a named consequence can be also guarded by an additional
condition like in this further example:

The condition in the if statement is always evaluated on the pattern immediately
preceding it. In the end this last, a bit more complicated, example shows how it is
possible to switch over different conditions using a nested if/else statement:

Here the purpose is to give a 10% discount AND a free parking to Golden customers
over 60, but only a 5% discount (without free parking) to the Silver ones. This result
is achieved by activating the consequence named "giveDiscount5" using the keyword break
instead of do. In fact do just schedules a consequence in the agenda, allowing the
remaining part of the LHS to continue of being evaluated as per normal, while break also
blocks any further pattern matching evaluation. Note, of course, that the activation of
a named consequence not guarded by any condition with break doesn't make sense (and
generates a compile time error) since otherwise the LHS part following it would be never
reachable.

7.8.6. A Note on Auto-boxing and Primitive Types

Drools attempts to preserve numbers in their primitive or object
wrapper form, so a variable bound to an int primitive when used in a code
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.

7.9. Query

Figure 7.29. query

A query is a simple way to search the working memory for facts that
match the stated conditions. Therefore, it contains only the structure of
the LHS of a rule, so that you specify neither "when" nor "then". A query
has an optional set of parameters, each of which can be optionally typed. If
the type is not given, the type Object is assumed. The engine will attempt
to coerce the values as needed. Query names are global to the KieBase;
so do not add queries of the same name to different packages for the same
RuleBase.

To return the results use
ksession.getQueryResults("name"), where "name" is the query's
name. This returns a list of query results, which allow you to retrieve the
objects that matched the query.

The first example presents a simple query for all the people over the
age of 30. The second one, using parameters, combines the age limit with a
location.

We iterate over the returned QueryResults using a standard "for" loop.
Each element is a QueryResultsRow which we can use to access each of the
columns in the tuple. These columns can be accessed by bound declaration
name or index position.

Support for positional syntax has been added for more compact code. By
default the declared type order in the type declaration matches the argument
position. But it possible to override these using the @position annotation.
This allows patterns to be used with positional arguments, instead of the
more verbose named arguments.

The @Position annotation, in the org.drools.definition.type package,
can be used to annotate original pojos on the classpath. Currently only
fields on classes can be annotated. Inheritance of classes is supported, but
not interfaces or methods. The isContainedIn query below demonstrates the
use of positional arguments in a pattern; Location(x, y;)
instead of Location( thing == x, location == y).

Queries can now call other queries, this combined with optional query
arguments provides derivation query style backward chaining. Positional and
named syntax is supported for arguments. It is also possible to mix both
positional and named, but positional must come first, separated by a semi
colon. Literal expressions can be passed as query arguments, but at this
stage you cannot mix expressions with variables. Here is an example of a
query that calls another query. Note that 'z' here will always be an 'out'
variable. The '?' symbol means the query is pull only, once the results are
returned you will not receive further results as the underlying data
changes.

As previously mentioned you can use live "open" queries to reactively
receive changes over time from the query results, as the underlying data it
queries against changes. Notice the "look" rule calls the query without
using '?'.

Drools supports unification for derivation queries, in short this
means that arguments are optional. It is possible to call queries from Java
leaving arguments unspecified using the static field
org.drools.core.runtime.rule.Variable.v - note you must use 'v' and not an
alternative instance of Variable. These are referred to as 'out' arguments.
Note that the query itself does not declare at compile time whether an
argument is in or an out, this can be defined purely at runtime on each use.
The following example will return all objects contained in the
office.

The algorithm uses stacks to handle recursion, so the method stack
will not blow up.

The following is not yet supported:

List and Map unification

Variables for the fields of facts

Expression unification - pred( X, X + 1, X * Y / 7 )

7.10. Domain Specific Languages

Domain Specific Languages (or DSLs) are a way of creating a rule
language that is dedicated to your problem domain. A set of DSL definitions
consists of transformations from DSL "sentences" to DRL constructs, which lets
you use of all the underlying rule language and engine features. Given a
DSL, you write rules in DSL rule (or DSLR) files, which will be translated
into DRL files.

DSL and DSLR files are plain text files, and you can use any text
editor to create and modify them. But there are also DSL and DSLR editors,
both in the IDE as well as in the web based BRMS, and you can use those
as well, although they may not provide you with the full DSL functionality.

7.10.1. When to Use a DSL

DSLs can serve as a layer of separation between rule authoring (and
rule authors) and the technical intricacies resulting from the modelling
of domain object and the rule engine's native language and methods. If your
rules need to be read and validated by domain experts (such as business
analysts, for instance) who are not programmers, you should consider
using a DSL; it hides implementation details and focuses on the rule logic
proper. DSL sentences can also act as "templates" for conditional elements and
consequence actions that are used repeatedly in your rules, possibly with
minor variations. You may define DSL sentences as being mapped to these
repeated phrases, with parameters providing a means for accommodating those
variations.

DSLs have no impact on the rule engine at runtime, they are just a
compile time feature, requiring a special parser and transformer.

7.10.2. DSL Basics

The Drools DSL mechanism allows you to customise conditional
expressions and consequence actions. A global substitution mechanism
("keyword") is also available.

Example 7.82. Example DSL mapping

[when]Something is {colour}=Something(colour=="{colour}")

In the preceding example, [when] indicates the scope of
the expression, i.e., whether it is valid for the LHS or the RHS of a rule. The
part after the bracketed keyword is the expression that you use in the rule;
typically a natural language expression, but it doesn't have to be. The
part to the right of the equal sign ("=") is the mapping of the expression into
the rule language. The form of this string depends on its destination, RHS or
LHS. If it is for the LHS, then it ought to be a term according to the regular
LHS syntax; if it is for the RHS then it might be a Java statement.

Whenever the DSL parser matches a line from the rule file written in the
DSL with an expression in the DSL definition, it performs three steps of
string manipulation. First, it extracts the string values appearing where the
expression contains variable names in braces (here: {colour}). Then,
the values obtained from these captures are then interpolated wherever that name,
again enclosed in braces, occurs on the right hand side of the mapping. Finally, the
interpolated string replaces whatever was matched by the entire expression
in the line of the DSL rule file.

Note that the expressions (i.e., the strings on the left hand side of the
equal sign) are used as regular expressions in a pattern matching operation
against a line of the DSL rule file, matching all or part of a line. This means
you can use (for instance) a '?' to indicate that the preceding character is
optional. One good reason to use this is to overcome variations in natural language
phrases of your DSL. But, given that these expressions are regular
expression patterns, this also means that all "magic" characters of Java's
pattern syntax have to be escaped with a preceding backslash ('\').

It is important to note that the compiler transforms DSL rule files
line by line. In the above example, all the text after "Something is " to
the end of the line is captured as the replacement value for "{colour}",
and this is used for interpolating the target string. This may not be exactly
what you want. For instance, when you intend to merge different DSL
expressions to generate a composite DRL pattern, you need to transform a DSLR
line in several independent operations. The best way to achieve this is to
ensure that the captures are surrounded by characteristic text - words or
even single characters. As a result,
the matching operation done by the parser plucks out a substring from
somewhere within the line. In the example below, quotes are used as
distinctive characters. Note that the characters that surround the capture
are not included during interpolation, just the contents between them.

As a rule of thumb, use quotes for textual data that a rule editor
may want to enter. You can also enclose the capture with words to ensure
that the text is correctly matched. Both is illustrated by the following
example. Note that a single line such as Something is "green" and
another solid thing is now correctly expanded.

It is a good idea to avoid punctuation (other than quotes or
apostrophes) in your DSL expressions as much as possible. The main reason
is that punctuation is easy to forget for rule authors using your DSL.
Another reason is that parentheses, the period and the question mark are magic
characters, requiring escaping in the DSL definition.

In a DSL mapping, the braces "{" and "}" should only be used to
enclose a variable definition or reference, resulting in a capture. If they
should occur literally, either in the expression or within the replacement
text on the right hand side, they must be escaped with a preceding backslash
("\"):

[then]do something= if (foo) \{ doSomething(); \}

Note

If braces "{" and "}" should appear in the replacement string of a
DSL definition, escape them with a backslash ('\').

Example 7.84. Examples of DSL mapping entries

# This is a comment to be ignored.
[when]There is a person with name of "{name}"=Person(name=="{name}")
[when]Person is at least {age} years old and lives in "{location}"=
Person(age >= {age}, location=="{location}")
[then]Log "{message}"=System.out.println("{message}");
[when]And = and

Given the above DSL examples, the following examples show the expansion of various
DSLR snippets:

Example 7.85. Examples of DSL expansions

There is a person with name of "Kitty"
==> Person(name="Kitty")
Person is at least 42 years old and lives in "Atlanta"
==> Person(age >= 42, location="Atlanta")
Log "boo"
==> System.out.println("boo");
There is a person with name of "Bob" and Person is at least 30 years old and lives in "Utah"
==> Person(name="Bob") and Person(age >= 30, location="Utah")

Note

Don't forget that if you are capturing plain text from a DSL rule line
and want to use it as a string literal in the expansion, you must provide
the quotes on the right hand side of the mapping.

You can chain DSL expressions together on one line, as long as it is
clear to the parser where one ends and the next one begins and where the
text representing a parameter ends. (Otherwise you risk getting all the
text until the end of the line as a parameter value.) The DSL expressions are
tried, one after the other, according to their order in the DSL definition
file. After any match, all remaining DSL expressions are investigated,
too.

The resulting DRL text may consist of more than one line. Line ends
are in the replacement text are written as \n.

7.10.3. Adding Constraints to Facts

A common requirement when writing rule conditions is to be able to
add an arbitrary combination of constraints to a pattern. Given that a
fact type may have many fields, having to provide an individual DSL
statement for each combination would be plain folly.

The DSL facility allows you to add constraints to a pattern by a
simple convention: if your DSL expression starts with a hyphen
(minus character, "-") it is assumed to be a field constraint and,
consequently, is is added to the last pattern line preceding it.

For an example, lets take look at class Cheese,
with the following fields: type, price, age and country. We can
express some LHS condition in normal DRL like the following

Cheese(age < 5, price == 20, type=="stilton", country=="ch")

The DSL definitions given below result in three DSL phrases which
may be used to create any combination of constraint involving these fields.

[when]There is a Cheese with=Cheese()
[when]- age is less than {age}=age<{age}
[when]- type is '{type}'=type=='{type}'
[when]- country equal to '{country}'=country=='{country}'

You can then write rules with conditions like the following:

There is a Cheese with
- age is less than 42
- type is 'stilton'

The parser will pick up a line
beginning with "-" and add it as a constraint to the preceding pattern,
inserting a comma when it is required. For the preceding example, the
resulting DRL is:

Cheese(age<42, type=='stilton')

Combining all all numeric fields with all relational operators
(according to the DSL expression "age is less than..." in the preceding
example) produces an unwieldy amount of DSL entries. But you can define
DSL phrases for the various operators and even a generic expression
that handles any field constraint, as shown below. (Notice that
the expression definition contains a regular expression in addition
to the variable name.)

Given these DSL definitions, you can write rules with conditions
such as:

There is a Cheese with
- age is less than 42
- rating is greater than 50
- type equals 'stilton'

In this specific case, a phrase such as "is less than" is replaced by
<, and then the line matches the last DSL entry. This
removes the hyphen, but the final result is still added as a constraint
to the preceding pattern. After processing all of the lines, the resulting
DRL text is:

Cheese(age<42, rating > 50, type=='stilton')

Note

The order of the entries in the DSL is important if separate DSL
expressions are intended to match the same line, one after the other.

7.10.4. Developing a DSL

A good way to get started is to write representative samples of the
rules your application requires, and to test them as you develop. This will
provide you with a stable framework of conditional elements and their
constraints. Rules, both in DRL and in DSLR, refer to entities according
to the data model representing the application data that should be subject
to the reasoning process defined in rules. Notice that writing rules
is generally easier if most of the data model's types are facts.

Given an initial set of rules, it should be possible to identify
recurring or similar code snippets and to mark variable parts as
parameters. This provides reliable leads as to what might be a handy
DSL entry. Also, make sure you have a full grasp of the jargon the
domain experts are using, and base your DSL phrases on this vocabulary.

You may postpone implementation decisions concerning conditions
and actions during this first design phase by leaving certain conditional
elements and actions in their DRL form by prefixing a line with a
greater sign (">"). (This is also handy for inserting debugging
statements.)

During the next development phase, you should find that the DSL
configuration stabilizes pretty quickly. New rules can be written by
reusing the existing DSL definitions, or by adding a parameter to an
existing condition or consequence entry.

Try to keep the number of DSL entries small. Using parameters
lets you apply the same DSL sentence for similar rule patterns or
constraints. But do not exaggerate: authors using the DSL should still
be able to identify DSL phrases by some fixed text.

7.10.5. DSL and DSLR Reference

A DSL file is a text file in a line-oriented format. Its
entries are used for transforming a DSLR file into a file according
to DRL syntax.

A line starting with "#" or "//"
(with or without preceding white space) is treated as a comment.
A comment line starting with "#/" is scanned for
words requesting a debug option, see below.

Any line starting with an opening bracket ("[") is assumed to
be the first line of a DSL entry definition.

Any other line is appended to the preceding DSL entry
definition, with the line end replaced by a space.

A DSL entry consists of the following four parts:

A scope definition, written as one of the keywords
"when" or "condition", "then" or "consequence", "*"
and "keyword", enclosed in brackets ("[" and "]"). This indicates
whether the DSL entry is valid for the condition or the
consequence of a rule, or both. A scope indication of "keyword"
means that the entry has global significance, i.e., it is
recognized anywhere in a DSLR file.

A type definition, written as a Java class name,
enclosed in brackets. This part is optional unless the
the next part begins with an opening bracket. An empty
pair of brackets is valid, too.

A DSL expression consists of a (Java) regular expression,
with any number of embedded variable definitions,
terminated by an equal sign ("="). A variable definition is enclosed
in braces ("{" and "}"). It
consists of a variable name and two optional attachments, separated
by colons (":"). If there is one attachment, it is a regular expression
for matching text that is to be assigned to the variable; if there
are two attachments, the first one is a hint for the GUI
editor and the second one the regular expression.

Note that all characters that are "magic" in regular
expressions must be escaped with a preceding backslash ("\")
if they should occur literally within the expression.

The remaining part of the line after the delimiting equal
sign is the replacement text for any DSLR text matching the
regular expression. It may contain variable references, i.e.,
a variable name enclosed in braces. Optionally, the variable name
may be followed by an exclamation mark ("!") and a transformation
function, see below.

Note that braces ("{" and "}") must be escaped with a
preceding backslash ("\") if they should occur literally
within the replacement string.

Debugging of DSL expansion can be turned on, selectively,
by using a comment line starting with "#/" which
may contain one or more words from the table presented below.
The resulting output is written to standard output.

Table 7.2. Debug options for DSL expansion

Word

Description

result

Prints the resulting DRL text, with line numbers.

steps

Prints each expansion step of condition and consequence
lines.

keyword

Dumps the internal representation of all DSL entries with
scope "keyword".

when

Dumps the internal representation of all DSL entries with
scope "when" or "*".

then

Dumps the internal representation of all DSL entries with
scope "then" or "*".

usage

Displays a usage statistic of all DSL entries.

Below are some sample DSL definitions, with comments describing the
language features they illustrate.

Each of the "keyword" entries is applied to the entire text.
First, the regular expression from the keyword definition is modified
by replacing white space sequences with a pattern matching any number
of white space characters, and by replacing variable definitions with
a capture made from the regular expression provided with the definition,
or with the default (".*?"). Then, the DSLR text is searched exhaustively
for occurrences of strings matching the modified regular expression.
Substrings of a matching string corresponding to variable captures are
extracted and replace variable references in the corresponding
replacement text, and this text replaces the matching string in the
DSLR text.

Sections of the DSLR text between "when" and "then", and
"then" and "end", respectively, are located and processed in a
uniform manner, line by line, as described below.

For a line, each DSL entry pertaining to the line's section
is taken in turn, in the order it appears in the DSL file. Its
regular expression part is modified: white space is replaced by
a pattern matching any number of white space characters; variable
definitions with a regular expression are replaced by a capture
with this regular expression, its default being ".*?".
If the resulting regular expression matches all or part of the
line, the matched part is replaced by the suitably modified
replacement text.

Modification of the replacement text is done by replacing
variable references with the text corresponding to the regular
expression capture. This text may be modified according to the
string transformation function given in the variable reference;
see below for details.

If there is a variable reference naming a variable that is not
defined in the same entry, the expander substitutes a value bound to
a variable of that name, provided it was defined in one of the
preceding lines of the current rule.

If a DSLR line in a condition is written with a leading
hyphen, the expanded result is inserted into the last line, which
should contain a pattern CE, i.e., a type name followed by a pair
of parentheses. if this pair is empty, the expanded line (which
should contain a valid constraint) is simply inserted, otherwise
a comma (",") is inserted beforehand.

If a DSLR line in a consequence is written with a leading
hyphen, the expanded result is inserted into the last line, which
should contain a "modify" statement, ending in a pair of braces
("{" and "}"). If this pair is empty, the expanded line (which
should contain a valid method call) is simply inserted, otherwise
a comma (",") is inserted beforehand.

Note

It is currently not possible to use a line
with a leading hyphen to insert text into other conditional element
forms (e.g., "accumulate") or it may only work for the first insertion
(e.g., "eval").

All string transformation functions are described in the following
table.

Table 7.3. String transformation functions

Name

Description

uc

Converts all letters to upper case.

lc

Converts all letters to lower case.

ucfirst

Converts the first letter to upper case, and
all other letters to lower case.

num

Extracts all digits and "-" from the string. If the
last two digits in the original string are preceded by "." or
",", a decimal period is inserted in the corresponding position.

a?b/c

Compares the string with string a, and if they
are equal, replaces it with b, otherwise with
c. But c can be another triplet
a, b, c, so
that the entire structure is, in fact, a translation table.

The following DSL examples show how to use string transformation functions.

A file containing a DSL definition has to be put under the resources folder
or any of its subfolders like any other drools artifact. It must have the extension
.dsl, or alternatively be marked with type ResourceType.DSL.
when programmatically added to a KieFileSystem. For a file using DSL
definition, the extension .dslr should be used, while it can be
added to a KieFileSystem with type ResourceType.DSLR.

For parsing and expanding a DSLR file the DSL configuration is read
and supplied to the parser. Thus, the parser can "recognize" the DSL
expressions and transform them into native rule language expressions.

8.1. Complex Event Processing

There is no broadly accepted definition on the term Complex Event Processing. The term Event
by itself is frequently overloaded and used to refer to several different things, depending on
the context it is used. Defining terms is not the goal of this guide and as so, lets adopt a
loose definition that, although not formal, will allow us to proceed with a common
understanding.

So, in the scope of this guide:

Important

Event, is a record of a significant change of state in the
application domain at a given point in time.

For instance, on a Stock Broker application, when a sale operation is executed, it causes a
change of state in the domain. This change of state can be observed on several entities in the
domain, like the price of the securities that changed to match the value of the operation, the
ownership of the traded assets that changed from the seller to the buyer, the balance of the
accounts from both seller and buyer that are credited and debited, etc. Depending on how the
domain is modelled, this change of state may be represented by a single event, multiple atomic
events or even hierarchies of correlated events. In any case, in the context of this guide,
Event is the record of the change of a particular piece of data in the domain.

Events are processed by computer systems since they were invented, and
throughout the history, systems responsible for that were given different
names and different methodologies were employed. It wasn't until the 90's
though, that a more focused work started on EDA (Event Driven Architecture)
with a more formal definition on the requirements and goals for event
processing. Old messaging systems started to change to address such
requirements and new systems started to be developed with the single purpose
of event processing. Two trends were born under the names of Event Stream
Processing and Complex Event Processing.

In the very beginnings, Event Stream Processing was focused on the capabilities of
processing streams of events in (near) real time, while the main focus of Complex Event
Processing was on the correlation and composition of atomic events into complex (compound)
events. An important (maybe the most important) milestone was the publishing of Dr. David
Luckham's book "The Power of Events" in 2002. In the book, Dr Luckham introduces the concept of
Complex Event Processing and how it can be used to enhance systems that deal with events. Over
the years, both trends converged to a common understanding and today these systems are all
referred to as CEP systems.

This is a very simplistic explanation to a really complex and fertile field of research, but
sets a high level and common understanding of the concepts that this guide will
introduce.

The current understanding of what Complex Event Processing is may be
briefly described as the following quote from Wikipedia:

Important

"Complex Event
Processing, or CEP, is primarily an event processing concept
that deals with the task of processing multiple events with the goal of
identifying the meaningful events within the event cloud. CEP employs
techniques such as detection of complex patterns of many events, event
correlation and abstraction, event hierarchies, and relationships
between events such as causality, membership, and timing, and
event-driven processes."

In other words, CEP is about detecting and selecting the interesting
events (and only them) from an event cloud, finding their relationships and
inferring new data from them and their relationships.

Note

For the remaining of this guide, we will use the terms
Complex Event Processing
and CEP as a broad reference for any of
the related technologies
and techniques, including but not limited to, CEP, Complex Event Processing,
ESP, Event Stream Processing and Event Processing in general.

8.2. Drools Fusion

Event Processing use cases, in general, share several requirements and
goals with Business Rules use cases. These overlaps happen both on the
business side and on the technical side.

On the Business side:

Business rules are frequently defined based on the occurrence of
scenarios triggered by events. Examples could be:

On an algorithmic trading application: take an action if the
security price increases X% compared to the day opening price, where
the price increases are usually denoted by events on a Stock Trade
application.

On a monitoring application: take an action if the temperature
on the server room increases X degrees in Y minutes, where sensor
readings are usually denoted by events.

Both business rules and event processing queries change frequently
and require immediate response for the business to adapt itself to new
market conditions, new regulations and new enterprise policies.

Both have functional requirements like pattern matching and
non-functional requirements like response time and query/rule
explanation.

Even sharing requirements and goals, historically, both fields were
born appart and although the industry evolved and one can find good products
on the market, they either focus on event processing or on business rules
management. That is due not only because of historical reasons but also
because, even overlapping in part, use cases do have some different
requirements.

Important

Drools was also born as a rules engine several years ago, but
following the vision of becoming a single platform for behavioral
modelling, it soon realized that it could only achieve this goal by
crediting the same importance to the three complementary business
modelling techniques:

Business Rules Management

Business Processes Management

Complex Event Processing

In this context, Drools Fusion is the module responsible for adding
event processing capabilities into the platform.

Supporting Complex Event Processing, though, is much more than simply
understanding what an event is. CEP scenarios share several common and
distinguishing characteristics:

Usually required to process huge volumes of events, but only a
small percentage of the events are of real interest.

Events are usually immutable, since they are a record of state
change.

Usually the rules and queries on events must run in reactive
modes, i.e., react to the detection of event patterns.

Usually there are strong temporal relationships between related
events.

Individual events are usually not important. The system is
concerned about patterns of related events and their
relationships.

Usually, the system is required to perform composition and
aggregation of events.

Based on this general common characteristics, Drools Fusion defined a
set of goals to be achieved in order to support Complex Event Processing
appropriately:

Support Events, with their proper semantics, as first class
citizens.

Allow detection, correlation, aggregation and composition of
events.

Support processing of Streams of events.

Support temporal constraints in order to model the temporal
relationships between events.

Support sliding windows of interesting events.

Support a session scoped unified clock.

Support the required volumes of events for CEP use cases.

Support to (re)active rules.

Support adapters for event input into the engine
(pipeline).

The above list of goals are based on the requirements not covered by
Drools Expert itself, since in a unified platform, all features of one
module are leveraged by the other modules. This way, Drools Fusion is born
with enterprise grade features like Pattern Matching, that is paramount to a
CEP product, but that is already provided by Drools Expert. In the same way,
all features provided by Drools Fusion are leveraged by Drools Flow (and
vice-versa) making process management aware of event processing and
vice-versa.

For the remaining of this guide, we will go through each of the
features Drools Fusion adds to the platform. All these features are
available to support different use cases in the CEP world, and the user is
free to select and use the ones that will help him model his business use
case.

8.3. Event Semantics

An event is a fact that present a few
distinguishing characteristics:

Usually immutables: since, by the
previously discussed definition, events are a record of a state change
in the application domain, i.e., a record of something that already
happened, and the past can not be "changed", events are immutables. This
constraint is an important requirement for the development of several
optimizations and for the specification of the event lifecycle. This
does not mean that the Java object representing the object must be
immutable. Quite the contrary, the engine does not enforce immutability
of the object model, because one of the most common use cases for rules
is event data enrichment.

Note

As a best practice, the application is allowed to populate
un-populated event attributes (to enrich the event with inferred data),
but already populated attributes should never be changed.

Strong temporal constraints:
rules involving events usually require the correlation of multiple
events, specially temporal correlations where events are said to happen
at some point in time relative to other events.

Managed lifecycle: due to their
immutable nature and the temporal constraints, events usually will only
match other events and facts during a limited window of time, making it
possible for the engine to manage the lifecycle of the events
automatically. In other words, one an event is inserted into the working
memory, it is possible for the engine to find out when an event can no
longer match other facts and automatically delete it, releasing its
associated resources.

Use of sliding windows: since all
events have timestamps associated to them, it is possible to define and
use sliding windows over them, allowing the creation of rules on
aggregations of values over a period of time. Example: average of an
event value over 60 minutes.

Drools supports the declaration and usage of events with both
semantics: point-in-time events and
interval-based events.

Note

A simplistic way to understand the unitification of the semantics is
to consider a point-in-time event as an
interval-based event whose duration is
zero.

8.4. Event Processing Modes

Rules engines in general have a well known way of processing data and
rules and provide the application with the results. Also, there is not many
requirements on how facts should be presented to the rules engine, specially
because in general, the processing itself is time independent. That is a
good assumption for most scenarios, but not for all of them. When the
requirements include the processing of real time or near real time events,
time becomes and important variable of the reasoning process.

The following sections will explain the impact of time on rules
reasoning and the two modes provided by Drools for the reasoning process.

8.4.1. Cloud Mode

The CLOUD processing mode is the default processing mode. Users of
rules engine are familiar with this mode because it behaves in exactly the
same way as any pure forward chaining rules engine, including previous
versions of Drools.

When running in CLOUD mode, the engine sees all facts in the working
memory, does not matter if they are regular facts or events, as a whole.
There is no notion of flow of time, although events have a timestamp as
usual. In other words, although the engine knows that a given event was
created, for instance, on January 1st 2009, at 09:35:40.767, it is not
possible for the engine to determine how "old" the event is, because there
is no concept of "now".

In this mode, the engine will apply its usual many-to-many pattern
matching algorithm, using the rules constraints to find the matching tuples,
activate and fire rules as usual.

This mode does not impose any kind of additional requirements on
facts. So for instance:

There is no notion of time. No requirements clock synchronization.

There is no requirement on event ordering. The engine looks at the
events as an unordered cloud against which the engine tries to match
rules.

On the other hand, since there is no requirements, some benefits are
not available either. For instance, in CLOUD mode, it is not possible to use
sliding windows, because sliding windows are based on the concept of "now"
and there is no concept of "now" in CLOUD mode.

Since there is no ordering requirement on events, it is not possible
for the engine to determine when events can no longer match and as so, there
is no automatic life-cycle management for events. I.e., the application must
explicitly delete events when they are no longer necessary, in the same way
the application does with regular facts.

Cloud mode is the default execution mode for Drools, but in any case,
as any other configuration in Drools, it is possible to change this behavior
either by setting a system property, using configuration property files or
using the API. The corresponding property is:

8.4.2. Stream Mode

The STREAM processing mode is the mode of choice when the application
needs to process streams of events. It adds a few common requirements to the
regular processing, but enables a whole lot of features that make stream
event processing a lot simpler.

The main requirements to use STREAM mode are:

Events in each stream must be time-ordered. I.e., inside a given
stream, events that happened first must be inserted first into the
engine.

The engine will force synchronization between streams through the
use of the session clock, so, although the application does not need to
enforce time ordering between streams, the use of non-time-synchronized
streams may result in some unexpected results.

Given that the above requirements are met, the application may enable
the STREAM mode using the following API:

When using the STREAM, the engine knows the concept of flow of time
and the concept of "now", i.e., the engine understands how old events are
based on the current timestamp read from the Session Clock. This
characteristic allows the engine to provide the following additional
features to the application:

Sliding Window support

Automatic Event Lifecycle Management

Automatic Rule Delaying when using Negative Patterns

All these features are explained in the following sections.

8.4.2.1. Role of Session Clock in Stream mode

When running the engine in CLOUD mode, the session clock is used
only to time stamp the arriving events that don't have a previously
defined timestamp attribute. Although, in STREAM mode, the Session Clock
assumes an even more important role.

In STREAM mode, the session clock is responsible for keeping the
current timestamp, and based on it, the engine does all the temporal
calculations on event's aging, synchronizes streams from multiple sources,
schedules future tasks and so on.

Check the documentation on the Session Clock section to know how to
configure and use different session clock implementations.

8.4.2.2. Negative Patterns in Stream Mode

Negative patterns behave different in STREAM mode when compared to
CLOUD mode. In CLOUD mode, the engine assumes that all facts and events
are known in advance (there is no concept of flow of time) and so,
negative patterns are evaluated immediately.

When running in STREAM mode, negative patterns with temporal
constraints may require the engine to wait for a time period before
activating a rule. The time period is automatically calculated by the
engine in a way that the user does not need to use any tricks to achieve
the desired result.

The above rule has no temporal constraints that would require
delaying the rule, and so, the rule activates immediately. The following
rule on the other hand, must wait for 10 seconds before activating, since
it may take up to 10 seconds for the sprinklers to activate:

Example 8.2. a rule that automatically delays activation due to temporal
constraints

This behaviour allows the engine to keep consistency when
dealing with negative patterns and temporal constraints at the same time.
The above would be the same as writing the rule as below, but does not
burden the user to calculate and explicitly write the appropriate duration
parameter:

The following rule expects every 10 seconds at least one
“Heartbeat” event, if not the rule fires. The special case in this rule
is that we use the same type of the object in the first pattern and in
the negative pattern. The negative pattern has the temporal constraint to
wait between 0 to 10 seconds before firing and it excludes the Heartbeat
bound to $h. Excluding the bound Heartbeat is important since the
temporal constraint [0s, ...] does not exclude by itself the bound event
$h from being matched again, thus preventing the rule to fire.

Example 8.4. excluding bound events in negative patterns

rule "Sound the alarm"
when
$h: Heartbeat( ) from entry-point "MonitoringStream"
not( Heartbeat( this != $h, this after[0s,10s] $h ) from entry-point "MonitoringStream" )
then
// Sound the alarm
end

8.5. Session Clock

Reasoning over time requires a reference clock. Just to mention one
example, if a rule reasons over the average price of a given stock over the
last 60 minutes, how the engine knows what stock price changes happened over
the last 60 minutes in order to calculate the average? The obvious response
is: by comparing the timestamp of the events with the "current time". How
the engine knows what time is now? Again,
obviously, by querying the Session Clock.

The session clock implements a strategy pattern, allowing different
types of clocks to be plugged and used by the engine. This is very important
because the engine may be running in an elements of different scenarios that
may require different clock implementations. Just to mention a few:

Rules testing: testing always
requires a controlled environment, and when the tests include rules with
temporal constraints, it is necessary to not only control the input
rules and facts, but also the flow of time.

Regular execution: usually, when
running rules in production, the application will require a real time
clock that allows the rules engine to react immediately to the time
progression.

Special environments: specific
environments may have specific requirements on time control. Cluster
environments may require clock synchronization through heart beats, or
JEE environments may require the use of an AppServer provided clock,
etc.

Rules replay or simulation: to
replay scenarios or simulate scenarios it is necessary that the
application also controls the flow of time.

8.5.1. Available Clock Implementations

Drools 5 provides 2 clock implementations out of the box. The default
real time clock, based on the system clock, and an optional pseudo clock,
controlled by the application.

8.5.1.1. Real Time Clock

By default, Drools uses a real time clock implementation that
internally uses the system clock to determine the current
timestamp.

To explicitly configure the engine to use the real time clock, just
set the session configuration parameter to real time:

8.5.1.2. Pseudo Clock

Drools also offers out of the box an implementation of a clock that
is controlled by the application that is called Pseudo Clock. This clock
is specially useful for unit testing temporal rules since it can be
controlled by the application and so the results become
deterministic.

8.6. Sliding Windows

Sliding Windows are a way to scope the events of interest by defining
a window that is constantly moving. The two most common types of sliding
window implementations are time based windows and length based
windows.

The next sections will detail each of them.

Important

Sliding Windows are only available when running the engine in STREAM
mode. Check the Event Processing Mode section for details on how the
STREAM mode works.

Important

Sliding windows start to match immediately and defining a sliding
window does not imply that the rule has to wait for the sliding window to
be "full" in order to match. For instance, a rule that calculates the
average of an event property on a window:length(10) will start calculating
the average immediately, and it will start at 0 (zero) for no-events, and
will update the average as events arrive one by one.

8.6.1. Sliding Time Windows

Sliding Time Windows allow the user to write rules that will only
match events occurring in the last X time units.

For instance, if the user wants to consider only the Stock Ticks that
happened in the last 2 minutes, the pattern would look like this:

StockTick() over window:time( 2m )

Drools uses the "over" keyword to associate windows to
patterns.

On a more elaborate example, if the user wants to sound an alarm in
case the average temperature over the last 10 minutes read from a sensor is
above the threshold value, the rule would look like:

The engine will automatically disregard any SensorReading older than
10 minutes and keep the calculated average consistent.

Important

Please note that time based windows are considered when calculating
the interval an event remains in the working memory before being expired,
but an event falling off a sliding window does not mean by itself that the
event will be discarded from the working memory, as there might be other
rules that depend on that event. The engine will discard events only when
no other rules depend on that event and the expiration policy for that
event type is fulfilled.

8.6.2. Sliding Length Windows

Sliding Length Windows work the same way as Time Windows, but consider
events based on order of their insertion into the session instead of flow of
time.

For instance, if the user wants to consider only the last 10 RHT Stock
Ticks, independent of how old they are, the pattern would look like
this:

StockTick( company == "RHT" ) over window:length( 10 )

As you can see, the pattern is similar to the one presented in the
previous section, but instead of using window:time to define the sliding
window, it uses window:length.

Using a similar example to the one in the previous section, if the
user wants to sound an alarm in case the average temperature over the last
100 readings from a sensor is above the threshold value, the rule would look
like:

The engine will keep only consider the last 100 readings to calculate
the average temperature.

Important

Please note that falling off a length based window is not criteria
for event expiration in the session. The engine disregards events that
fall off a window when calculating that window, but does not remove the
event from the session based on that condition alone as there might be
other rules that depend on that event.

Important

Please note that length based windows do not define temporal
constraints for event expiration from the session, and the engine will not
consider them. If events have no other rules defining temporal constraints
and no explicit expiration policy, the engine will keep them in the
session indefinitely.

8.7. Streams Support

Most CEP use cases have to deal with streams of events. The streams
can be provided to the application in various forms, from JMS queues to flat
text files, from database tables to raw sockets or even through web service
calls. In any case, the streams share a common set of
characteristics:

events in the stream are ordered by a timestamp. The timestamp may
have different semantics for different streams but they are always
ordered internally.

volumes of events are usually high.

atomic events are rarely useful by themselves. Usually meaning is
extracted from the correlation between multiple events from the stream
and also from other sources.

streams may be homogeneous, i.e. contain a single type of events,
or heterogeneous, i.e. contain multiple types of events.

Drools generalized the concept of a stream as an "entry point" into
the engine. An entry point is for drools a gate from which facts come. The
facts may be regular facts or special facts like events.

In Drools, facts from one entry point (stream) may join with facts
from any other entry point or event with facts from the working memory.
Although, they never mix, i.e., they never lose the reference to the entry
point through which they entered the engine. This is important because one
may have the same type of facts coming into the engine through several entry
points, but one fact that is inserted into the engine through entry point A
will never match a pattern from a entry point B, for example.

8.7.1. Declaring and Using Entry Points

Entry points are declared implicitly in Drools by directly making use
of them in rules. I.e. referencing an entry point in a rule will make the
engine, at compile time, to identify and create the proper internal
structures to support that entry point.

So, for instance, lets imagine a banking application, where
transactions are fed into the system coming from streams. One of the streams
contains all the transactions executed in ATM machines. So, if one of the
rules says: a withdraw is authorized if and only if the account balance is
over the requested withdraw amount, the rule would look like:

In the previous example, the engine compiler will identify that
the pattern is tied to the entry point "ATM Stream" and will both create all
the necessary structures for the rulebase to support the "ATM Stream" and
will only match WithdrawRequests coming from the "ATM Stream". In the
previous example, the rule is also joining the event from the stream with a
fact from the main working memory (CheckingAccount).

Now, lets imagine a second rule that states that a fee of $2 must be
applied to any account for which a withdraw request is placed at a bank
branch:

The previous rule will match events of the exact same type as
the first rule (WithdrawRequest), but from two different streams, so an
event inserted into "ATM Stream" will never be evaluated against the pattern
on the second rule, because the rule states that it is only interested in
patterns coming from the "Branch Stream".

So, entry points, besides being a proper abstraction for streams, are
also a way to scope facts in the working memory, and a valuable tool for
reducing cross products explosions. But that is a subject for another
time.

Inserting events into an entry point is equally simple. Instead of
inserting events directly into the working memory, insert them into the
entry point as shown in the example below:

The previous example shows how to manually insert facts into a given
entry point. Although, usually, the application will use one of the many
adapters to plug a stream end point, like a JMS queue, directly into the
engine entry point, without coding the inserts manually. The Drools pipeline
API has several adapters and helpers to do that as well as examples on how
to do it.

8.8. Memory Management for Events

Important

The automatic memory management for events is only performed when
running the engine in STREAM mode. Check the Event Processing Mode section
for details on how the STREAM mode works.

One of the benefits of running the engine in STREAM mode is that the
engine can detect when an event can no longer match any rule due to its
temporal constraints. When that happens, the engine can safely delete the
event from the session without side effects and release any resources used
by that event.

There are basically 2 ways for the engine to calculate the matching
window for a given event:

explicitly, using the expiration policy

implicitly, analyzing the temporal constraints on events

8.8.1. Explicit expiration offset

The first way of allowing the engine to calculate the window of
interest for a given event type is by explicitly setting it. To do that,
just use the declare statement and define an expiration for the fact
type:

The above example declares an expiration offset of 30 minutes
for StockTick events. After that time, assuming no rule still needs the
event, the engine will expire and remove the event from the session
automatically.

8.8.2. Inferred expiration offset

Another way for the engine to calculate the expiration offset for a
given event is implicitly, by analyzing the temporal constraints in the
rules. For instance, given the following rule:

Analyzing the above rule, the engine automatically calculates
that whenever a BuyOrderEvent matches, it needs to store it for up to 10
seconds to wait for matching AckEvent's. So, the implicit expiration offset
for BuyOrderEvent will be 10 seconds. AckEvent, on the other hand, can only
match existing BuyOrderEvent's, and so its expiration offset will be zero
seconds.

The engine will make this analysis for the whole rulebase and find the
offset for every event type. Whenever an implicit expiration offset clashes
with the explicit expiration offset, then engine will use the greater of the
two.

8.9. Temporal Reasoning

Temporal reasoning is another requirement of any CEP system. As
discussed previously, one of the distinguishing characteristics of events is
their strong temporal relationships.

Temporal reasoning is an extensive field of research, from its roots
on Temporal Modal Logic to its more practical applications in business
systems. There are hundreds of papers and thesis written and approaches are
described for several applications. Drools once more takes a pragmatic and
simple approach based on several sources, but specially worth noting the
following papers:

[BENNE00] by Bennet, Brandon and Galton, Antony P.. A Unifying Semantics for Time and Events. 2005.

[YONEK05] by Yoneki, Eiko and Bacon, Jean. Unified Semantics for Event Correlation Over Time and Space in
Hybrid Network Environments. 2005.

Drools implements the Interval-based Time Event Semantics described by
Allen, and represents Point-in-Time Events as Interval-based evens with
duration 0 (zero).

Note

For all temporal operator intervals, the "*" (star) symbol is used
to indicate positive infinity and the "-*" (minus
star) is used to indicate negative infinity.

8.9.1. Temporal Operators

Drools implements all 13 operators defined by Allen and also their
logical complement (negation). This section details each of the operators
and their parameters.

8.9.1.1. After

The after evaluator correlates two events and matches when the
temporal distance from the current event to the event being correlated
belongs to the distance range declared for the operator.

Lets look at an example:

$eventA : EventA( this after[ 3m30s, 4m ] $eventB )

The previous pattern will match if and only if the temporal distance
between the time when $eventB finished and the time when $eventA started
is between ( 3 minutes and 30 seconds ) and ( 4 minutes ). In other
words:

3m30s <= $eventA.startTimestamp - $eventB.endTimeStamp <= 4m

The temporal distance interval for the after operator is
optional:

If two values are defined (like in the example below), the
interval starts on the first value and finishes on the second.

If only one value is defined, the interval starts on the value
and finishes on the positive infinity.

If no value is defined, it is assumed that the initial value is
1ms and the final value is the positive infinity.

Note

It is possible to define negative distances for this operator.
Example:

$eventA : EventA( this after[ -3m30s, -2m ] $eventB )

Note

If the first value is greater than the second value, the engine
automatically reverses them, as there is no reason to have the first
value greater than the second value. Example: the following two patterns
are considered to have the same semantics:

Note

The after, before and
coincides operators can be used to define
constraints between events, java.util.Date attributes, and long
attributes (interpreted as timestamps since epoch) in any combination.
Example:

EventA( this after $someDate )

8.9.1.2. Before

The before evaluator correlates two events and matches when the
temporal distance from the event being correlated to the current
correlated belongs to the distance range declared for the operator.

Lets look at an example:

$eventA : EventA( this before[ 3m30s, 4m ] $eventB )

The previous pattern will match if and only if the temporal distance
between the time when $eventA finished and the time when $eventB started
is between ( 3 minutes and 30 seconds ) and ( 4 minutes ). In other
words:

3m30s <= $eventB.startTimestamp - $eventA.endTimeStamp <= 4m

The temporal distance interval for the before operator is
optional:

If two values are defined (like in the example below), the
interval starts on the first value and finishes on the second.

If only one value is defined, then the interval starts on the
value and finishes on the positive infinity.

If no value is defined, it is assumed that the initial value is
1ms and the final value is the positive infinity.

Note

It is possible to define negative distances for this operator.
Example:

$eventA : EventA( this before[ -3m30s, -2m ] $eventB )

Note

If the first value is greater than the second value, the engine
automatically reverses them, as there is no reason to have the first
value greater than the second value. Example: the following two patterns
are considered to have the same semantics:

Note

The after, before and
coincides operators can be used to define
constraints between events, java.util.Date attributes, and long
attributes (interpreted as timestamps since epoch) in any combination.
Example:

EventA( this after $someDate )

8.9.1.3. Coincides

The coincides evaluator correlates two events and matches when both
happen at the same time. Optionally, the evaluator accept thresholds for
the distance between events' start and finish timestamps.

Lets look at an example:

$eventA : EventA( this coincides $eventB )

The previous pattern will match if and only if the start timestamps
of both $eventA and $eventB are the same AND the end timestamp of both
$eventA and $eventB also are the same.

Optionally, this operator accepts one or two parameters. These
parameters are the thresholds for the distance between matching
timestamps.

If only one parameter is given, it is used for both start and
end timestamps.

If two parameters are given, then the first is used as a
threshold for the start timestamp and the second one is used as a
threshold for the end timestamp.

Warning

It makes no sense to use negative interval values for the
parameters and the engine will raise an error if that happens.

Note

The after, before and
coincides operators can be used to define
constraints between events, java.util.Date attributes, and long
attributes (interpreted as timestamps since epoch) in any combination.
Example:

EventA( this after $someDate )

8.9.1.4. During

The during evaluator correlates two events and matches when the
current event happens during the occurrence of the event being
correlated.

Lets look at an example:

$eventA : EventA( this during $eventB )

The previous pattern will match if and only if the $eventA starts
after $eventB starts and finishes before $eventB finishes.

If one value is defined, this will be the maximum distance
between the start timestamp of both event and the maximum distance
between the end timestamp of both events in order to operator match.
Example:

If two values are defined, the first value will be the minimum
distance between the timestamps of both events, while the second value
will be the maximum distance between the timestamps of both events.
Example:

If four values are defined, the first two values will be the
minimum and maximum distances between the start timestamp of both
events, while the last two values will be the minimum and maximum
distances between the end timestamp of both events. Example:

Warning

It makes no sense to use a negative interval value for the
parameter and the engine will raise an exception if that happens.

8.9.1.6. Finished By

The finishedby evaluator correlates two events and matches when the
current event start timestamp happens before the correlated event start
timestamp, but both end timestamps occur at the same time. This is the
symmetrical opposite of finishes evaluator.

Lets look at an example:

$eventA : EventA( this finishedby $eventB )

The previous pattern will match if and only if the $eventA starts
before $eventB starts and finishes at the same time $eventB
finishes.

The includes operator accepts 1, 2 or 4 optional parameters as
follow:

If one value is defined, this will be the maximum distance
between the start timestamp of both event and the maximum distance
between the end timestamp of both events in order to operator match.
Example:

If two values are defined, the first value will be the minimum
distance between the timestamps of both events, while the second value
will be the maximum distance between the timestamps of both events.
Example:

If four values are defined, the first two values will be the
minimum and maximum distances between the start timestamp of both
events, while the last two values will be the minimum and maximum
distances between the end timestamp of both events. Example:

8.9.1.8. Meets

The meets evaluator correlates two events and matches when the
current event's end timestamp happens at the same time as the correlated
event's start timestamp.

Lets look at an example:

$eventA : EventA( this meets $eventB )

The previous pattern will match if and only if the $eventA finishes
at the same time $eventB starts.

In other words:

abs( $eventB.startTimestamp - $eventA.endTimestamp ) == 0

The meets evaluator accepts one optional parameter. If it is
defined, it determines the maximum distance between the end timestamp of
current event and the start timestamp of the correlated event in order for
the operator to match. Example:

$eventA : EventA( this meets[ 5s ] $eventB )

Will match if and only if:

abs( $eventB.startTimestamp - $eventA.endTimestamp) <= 5s

Warning

It makes no sense to use a negative interval value for the
parameter and the engine will raise an exception if that happens.

8.9.1.9. Met By

The metby evaluator correlates two events and matches when the
current event's start timestamp happens at the same time as the correlated
event's end timestamp.

Lets look at an example:

$eventA : EventA( this metby $eventB )

The previous pattern will match if and only if the $eventA starts at
the same time $eventB finishes.

In other words:

abs( $eventA.startTimestamp - $eventB.endTimestamp ) == 0

The metby evaluator accepts one optional parameter. If it is
defined, it determines the maximum distance between the end timestamp of
the correlated event and the start timestamp of the current event in order
for the operator to match. Example:

$eventA : EventA( this metby[ 5s ] $eventB )

Will match if and only if:

abs( $eventA.startTimestamp - $eventB.endTimestamp) <= 5s

Warning

It makes no sense to use a negative interval value for the
parameter and the engine will raise an exception if that happens.

8.9.1.10. Overlaps

The overlaps evaluator correlates two events and matches when the
current event starts before the correlated event starts and finishes after
the correlated event starts, but before the correlated event finishes. In
other words, both events have an overlapping period.

If two values are defined, the first value will be the minimum
distance and the second value will be the maximum distance between the
start timestamp of the correlated event and the end timestamp of the
current event. Example:

8.9.1.11. Overlapped By

The overlappedby evaluator correlates two events and matches when
the correlated event starts before the current event starts and finishes
after the current event starts, but before the current event finishes. In
other words, both events have an overlapping period.

If two values are defined, the first value will be the minimum
distance and the second value will be the maximum distance between the
start timestamp of the current event and the end timestamp of the
correlated event. Example:

Warning

It makes no sense to use a negative interval value for the
parameter and the engine will raise an exception if that happens.

8.9.1.13. Started By

The startedby evaluator correlates two events and matches when the
correlating event's end timestamp happens before the current event's end
timestamp, but both start timestamps occur at the same time. Lets look at
an example:

$eventA : EventA( this startedby $eventB )

The previous pattern will match if and only if the $eventB finishes
before $eventA finishes and starts at the same time $eventB starts.

9.1.2. JSON

9.1.3. JAXB

There are two options for using JAXB, you can define your model in
an XSD file or you can have a POJO model. In both cases you have to
declare your model inside JAXBContext, and in order to do that you need to
use Drools Helper classes. Once you have the JAXBContext you need to
create the Unmarshaller/Marshaller as needed.

9.1.3.1. Using an XSD file to define the model

With your model defined in a XSD file you need to have a
KnowledgeBase that has your XSD model added as a resource.

To do this, the XSD file must be added as a XSD ResourceType into
the KnowledgeBuilder. Finally you can create the JAXBContext using the
KnowledgeBase created with the KnowledgeBuilder