1.1. What is a Rule Engine?

1.1.1. Introduction and Background

Artificial Intelligence (A.I.) is a very broad research area that
focuses on "Making computers think like people" and includes disciplines
such as Neural Networks, Genetic Algorithms, Decision Trees, Frame Systems
and Expert Systems. Knowledge representation is the area of A.I. concerned
with how knowledge is represented and manipulated. Expert Systems use
Knowledge representation to facilitate the codification of knowledge into
a knowledge base which can be used for reasoning, i.e., we can process
data with this knowledge base to infer conclusions. Expert Systems are
also known as Knowledge-based Systems and Knowledge-based Expert Systems
and are considered to be "applied artificial intelligence". The process of
developing with an Expert System is Knowledge Engineering. EMYCIN was one
of the first "shells" for an Expert System, which was created from the
MYCIN medical diagnosis Expert System. Whereas early Expert Systems had
their logic hard-coded, "shells" separated the logic from the system,
providing an easy to use environment for user input. Drools is a Rule
Engine that uses the rule-based approach to implement an Expert System and
is more correctly classified as a Production Rule System.

The term "Production Rule" originates from formal grammars where it
is described as "an abstract structure that describes a formal language
precisely, i.e., a set of rules that mathematically delineates a (usually
infinite) set of finite-length strings over a (usually finite) alphabet"
(Wikipedia).

Business Rule Management Systems build additional value on top of a
general purpose Rule Engine by providing business user focused systems for
rule creation, management, deployment, collaboration, analysis and end
user tools. Further adding to this value is the fast evolving and popular
methodology "Business Rules Approach", which is a helping to formalize the
role of Rule Engines in the enterprise.

The term Rule 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 VB code from those validation rules to
validate data entry. This, while a very valid and useful topic for some,
caused quite a surprise to this author, unaware at the time in the
subtleties of Rules Engines' differences, who was hoping to find some
hidden secrets to help improve the Drools engine. JBoss jBPM uses
expressions and delegates in its Decision nodes which control the
transitions in a Workflow. At each node it evaluates ther is a rule set
that dictates the transition to undertake, and so this is also a Rule
Engine. While a Production Rule System is a kind of Rule Engine and also
an Expert System, the validation and expression evaluation Rule Engines
mentioned previously are not Expert Systems.

A Production Rule System is Turing complete, with a focus on
knowledge representation to express propositional and first order logic in
a concise, non-ambiguous and declarative manner. The brain of a Production
Rules System is an Inference Engine that is able to scale to a large
number of rules and facts. The Inference Engine matches facts and data
against Production Rules - also called Productions or just Rules - to
infer conclusions which result in actions. A Production Rule is a two-part
structure using First Order Logic for reasoning over knowledge
representation.

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. There are a number of algorithms used for
Pattern Matching by Inference Engines including:

Linear

Rete

Treat

Leaps

Drools implements and extends the Rete algorithm; Leaps used to be provided but was retired as it became
unmaintained. The Drools Rete implementation is called 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 (Rete/UL)" (1995) by Robert B. Doorenbos.

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 1.1. High-level View of a Rule Engine

There are two methods of execution for a rule system: Forward
Chaining and Backward Chaining; systems that implement both are called
Hybrid Chaining Systems. As of Drools 5.2 Drools provides seamless hybrid
chaining, both forward and backwards. Understanding these two modes of
operation is the key to understanding why a Production Rule System is
different and how to get the best from it. 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 and we end in a conclusion.

Figure 1.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 it then 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 1.3. Backward Chaining

1.2. Why use a Rule Engine?

Some frequently asked questions:

When should you use a rule engine?

What advantage does a rule engine have over hand coded
"if...then" approaches?

Why should you use a rule engine instead of a scripting framework,
like BeanShell?

We will attempt to address these questions below.

1.2.1. Advantages of a Rule Engine

Declarative Programming

Rule engines allow you to say "What to do", not "How to do
it".

The key advantage of this point is that using rules can make it
easy to express solutions to difficult problems and consequently have
those solutions verified. Rules are much easier to read than
code.

Rule systems are capable of solving very, very hard problems,
providing an explanation of how the solution was arrived at and why
each "decision" along the way was made (not so easy with other of AI
systems like neural networks or the human brain - I have no idea why I
scratched the side of the car).

Logic and Data Separation

Your data is in your domain objects, the logic is in the rules.
This is fundamentally breaking the OO coupling of data and logic,
which can be an advantage or a disadvantage depending on your point of
view. The upshot is that the logic can be much easier to maintain as
there are changes in the future, as the logic is all laid out in
rules. This can be especially true if the logic is cross-domain or
multi-domain logic. Instead of the logic being spread across many
domain objects or controllers, it can all be organized in one or more
very distinct rules files.

Speed and Scalability

The Rete algorithm,the Leaps algorithm, and their descendants such as
Drools' ReteOO, provide very efficient ways of matching
rule patterns to your domain object data. These are especially
efficient when you have datasets that change in small portions as the
rule engine can remember past matches. These algorithms are battle
proven.

Centralization of Knowledge

By using rules, you create a repository of knowledge (a
knowledge base) which is executable. This means it's a single point of
truth, for business policy, for instance. Ideally rules are so
readable that they can also serve as documentation.

Tool Integration

Tools such as Eclipse (and in future, Web based user interfaces)
provide
ways to edit and manage rules and get immediate feedback, validation
and content assistance. Auditing and debugging tools are also
available.

Explanation Facility

Rule systems effectively provide an "explanation facility" by
being able to log the decisions made by the rule engine along with why
the decisions were made.

Understandable Rules

By creating object models and, optionally, Domain Specific
Languages that model your problem domain you can set yourself up to
write rules that are very close to natural language. They lend
themselves to logic that is understandable to, possibly nontechnical,
domain experts as they are expressed in their language, with all the
program plumbing, the technical know-how being hidden
away in the usual code.

1.2.2. When should you use a Rule Engine?

The shortest answer to this is "when there is no satisfactory
traditional programming approach to solve the problem.". Given that short
answer, some more explanation is required. The reason why there is no
"traditional" approach is possibly one of the following:

The problem is just too fiddle for traditional code.

The problem may not be complex, but you can't see a
non-fragile way of building a solution for it.

The problem is beyond any obvious algorithmic
solution.

It is a complex problem to solve, there are no obvious
traditional solutions, or basically the problem isn't fully
understood.

The logic changes often

The logic itself may even be simple but
the rules change quite often. In many organizations software
releases are few and far between and pluggable rules can help provide the
"agility" that is needed and expected in a reasonably safe
way.

Domain experts (or business analysts) are readily available,
but are nontechnical.

Domain experts often possess a wealth of knowledge about business
rules and processes. They typically are nontechnical, but can be
very logical. Rules can allow them to express the logic in their own
terms. Of course, they still have to think critically and be capable
of logical thinking. Many people in nontechnical positions do
not have training in formal logic, so be careful and work with them,
as by codifying business knowledge in rules, you will often expose
holes in the way the business rules and processes are currently
understood.

If rules are a new technology for your project teams, the overhead
in getting going must be factored in. It is not a trivial technology, but
this document tries to make it easier to understand.

Typically in a modern OO application you would use a rule engine to
contain key parts of your business logic,
especially the really messy parts. This is
an inversion of the OO concept of encapsulating all the logic inside your
objects. This is not to say that you throw out OO practices, on the
contrary in any real world application, business logic is just one part of
the application. If you ever notice lots of conditional statements
such as "if" and "switch", an
overabundance of strategy patterns and other messy logic in your code
that just doesn't feel right: that would be a place for rules.
If there is some such logic and you keep coming back to fix it, either
because you got it wrong, or the logic or your understanding changes: think
about using rules. If you are faced with tough problems for which there are
no algorithms or patterns: consider using rules.

Rules could be used embedded in your application or perhaps as a
service. Often a rule engine works best as "stateful" component, being
an integral part of an application. However, there have been
successful cases of creating reusable rule services which are
stateless.

For your organization it is important to decide about the process you
will use for updating rules in systems that are in production. The options
are many, but different organizations have different requirements.
Frequently, rules maintenance is out of the control of the application
vendors or project developers.

1.2.3. When not to use a Rule Engine

To quote a Drools mailing list regular:

It seems to me
that in the excitement of working with rules engines, that people forget
that a rules engine is only one piece of a complex application or
solution. Rules engines are not really intended to handle workflow or
process executions nor are workflow engines or process management tools
designed to do rules. Use the right tool for the job. Sure, a pair of
pliers can be used as a hammering tool in a pinch, but that's not what
it's designed for.

--Dave Hamu

As rule engines are dynamic (dynamic in the sense that the rules can
be stored and managed and updated as data), they are often looked at as a
solution to the problem of deploying software. (Most IT departments seem to
exist for the purpose of preventing software being rolled out.) If this is
the reason you wish to use a rule engine, be aware that rule engines work
best when you are able to write declarative rules. As an alternative, you
can consider data-driven designs (lookup tables), or script processing
engines where the scripts are managed in a database and are able to be
updated on the fly.

1.2.4. Scripting or Process Engines

Hopefully the preceding sections have explained when you may want to
use a rule engine.

Alternatives are script-based engines that provide the drive
for "changes on the fly", and there are many such solutions.

Alternatively Process Engines (also capable of workflow) such as
jBPM allow you to graphically (or programmatically) describe steps in a
process. Those steps can also involve decision points which are in
themselves a simple rule. Process engines and rules often can work nicely
together, so they are not mutually exclusive.

One key point to note with rule engines is that some rule engines
are really scripting engines. The downside of scripting engines is that
you are tightly coupling your application to the scripts. If they are
rules, you are effectively calling rules directly and this may cause more
difficulty in future maintenance, as they tend to grow in complexity over
time. The upside of scripting engines is that they can be easier to
implement initially, producing results quickly, and are conceptually
simpler for imperative programmers.

Many people have also implemented data-driven systems successfully
in the past (where there are control tables that store meta-data that
changes your applications behavior) - these can work well when the
control can remain very limited. However, they can quickly grow out of
control if extended too much (such that only the original creators can
change the applications behavior) or they cause the application to
stagnate as they are too inflexible.

1.2.5. Strong and Loose Coupling

No doubt you have heard terms like "tight coupling" and "loose
coupling" in systems design. Generally people assert that "loose" or
"weak" coupling is preferable in design terms, due to the added
flexibility it affords. Similarly, you can have "strongly coupled" and
"weakly coupled" rules. Strongly coupled in this sense means that one rule
"firing" will clearly result in another rule firing, and so on; in other
words,
there is a clear (probably obvious) chain of logic. If your rules are all
strongly coupled, the chances are that the will turn out to be inflexible,
and, more significantly, that a rule engine is an overkill. A clear chain
can be hard coded, or implemented using a Decision Tree. This is not to
say that strong
coupling is inherently bad, but it is a point to keep in mind when
considering a rule engine and the way you capture the rules. "Loosely"
coupled rules should result in a system that allows rules to be changed,
removed and added without requiring changes to other, unrelated
rules.

2.1. The Basics

2.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 into 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 refute 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.

Let's assume that the rules are in the same folder as the classes,
so we can use the classpath resource loader to build our first
KnowledgeBase. A Knowledge Base is what we call our
collection of compiled definitions, such as rules and processes, which are
compiled using the KnowledgeBuilder. Both the
KnowledgeBuilder and KnowledgeBase can be created from the factories
KnowledeBuilderFactory and KnowledgeBaseFactory.

The above code snippet looks on the classpath for the
licenseApplication.drl file, using the method
newClassPathResource(). The resource type is DRL, short for
"Drools Rule Language". Once the DRL file has been added we can check the
Knowledge Builder object for any errors. If there are no errors, we can
add the resulting packages to our Knowledge Base. Now we are ready to
build our session 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 array 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.

2.1.2. Stateful Knowledge Session

Stateful Sessions are longer 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 Knowledge Base contains references to Stateful Knowledge Sessions when
they are created. StatefulKnowledgeSession also supports the
BatchExecutor interface, like
StatelessKnowledgeSession, 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 was 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 intances. 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
retract( $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

The above rules should be placed in a single DRL file and saved to
some directory on the classpath and using the file name
fireAlarm.drl, as in the Stateless Session example.
We can then build a Knowledge Base, as before, just using the new name
fireAlarm.drl. The difference is that this time we
create a Stateful Session from the Knowledge Base, whereas before we
created a Stateless Session.

With the session created it is now possible to iteratvely 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.

> Turn on the sprinkler for room office
> Turn on the sprinkler for room kitchen
> Cancel the alarm
> 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.

2.2. A Little Theory

2.2.1. Methods versus Rules

People often confuse methods and rules, and new rule users regular
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.

2.2.2. 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 ar 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.

2.2.3. Activations, Agenda and Conflict Sets.

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.

By now you already know how to create Knowledge Bases and how to
instantiate facts to populate the StatefulKnowledgeSession,
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 2.1. 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.

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 2.2. 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 Activation. The
Agenda is a table of Activations that are able to fire and have their
consequences executed, as soon as fireAllRules() is called. Activations on
the Agenda are executed in turn. Notice that the order of execution so far
is considered arbitrary.

Figure 2.3. CashFlows and Account

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

Figure 2.4. 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
Activation on the Agenda.

Figure 2.5. CashFlows and Account

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

Figure 2.6. CashFlows and Account

What if you don't want the order of Activation execution to be
arbitrary? When there is one or more Activations on the Agenda they are
said to be in conflict, and a conflict resolver strategy is used to
determine the order of execution. At the simplest level the default
strategy uses salience to determine rule priority. Each rule has a default
value of 0, the higher the value the higher the priority. To illustrate
this 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.

The table below depicts the resulting Agenda. The three debit and
credit rules are shown to be in arbitrary order, while the print rule is
ranked last, to execute afterwards.

Figure 2.7. CashFlows and Account

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:

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.

2.2.4. Inference

Inference has a bad names 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 businesses with easier to maintain software.

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.

So in the above 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, hence forth 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
where to change that age to 21 there is a change management process.
Someone has 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 become costly and error
prone. Also the card department is managing more information than it needs
to be aware of with its "monolothic" approach to rules management which is
"leaking" information better placed else where. 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.

Instead what if we were to split (de-couple) the authoring
responsibility, so the central government maintains its rules and the ID
department maintains its.

So its the central governments job to determine who is an adult and
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 it's 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 create a single decision table that had all
possible information in it 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 or thumb when doing your knowledge engineering
is:

Bad

Monolithic

Leaky

Good

De-couple knowledge responsibilities

Encapsulate knowledge

Provide semantic abstractions for those
encapsulations

2.2.5. Inference and TruthMaintenance

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 "logicalInsert" is part of the Drools Truth Maintenance System
(TMS). Here the 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.

We can now bring back in the code to issue the passes, these two can
also be logically inserted, as the TMS supports chaining of logical
insertions for a cascading set of retracts.

Now when the 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:

2.3. More on building and deploying

2.3.1. Knowledge Base by Configuration Using Changesets

So far, the programmatic API has been used to build a Knowledge
Base. Quite often it's more desirable to do this via configuration. To
facilitate this, Drools supports the "Changeset" feature. The file
changeset.xml contains a list of resources, and it
may also point recursively to another changeset XML file. Currently there is
no XML schema for the changeset XML, but we hope to add one soon.
A few examples will be shown to give you the gist of things. A resource
approach is employed that uses a prefix to indicate the protocol. All the
protocols provided by java.net.URL, such as "file" and "http",
are supported, as well as an additional "classpath".
Currently the type attribute must always be specified for a resource, as
it is not inferred from the file name extension. Here is a simple example
that points to a http location for some rules.

Changesets can include any number of resources, and they even
support additional configuration information, which currently is only
needed for decision tables. The example below is expanded to load the
rules from a http URL location, and an Excel decision table from the
classpath.

It is also possible to specify a directory, to add the contents of
that directory. It is expected that all the files are of the specified
type, since type is not yet inferred from the file name extensions.

2.3.2. Knowledge Agent

The Knowlege Agent provides automatic loading, caching and
re-loading of resources and is configured from a properties files. The
Knowledge Agent can update or rebuild this Knowlege Base as the resources
it uses are changed. The strategy for this is determined by the
configuration given to the factory, but it is typically pull-based using
regular polling. We hope to add push-based updates and rebuilds in future
versions.

A KnowledgeAgent object will continuously scan all the
added resources, using a default polling interval of 60 seconds and, when
some last modification date is updated, it will applied the changes into the
cached Knowledge Base using the new resources. Note that the previous
KnowledgeBase reference will still exist and you'll have to
call getKnowledgeBase() to access the newly built
KnowledgeBase. If a directory is specified as part of the
change set, the entire contents of that directory will be scanned for
changes. The way modifications are applied depends on
drools.agent.newInstance property present in the
KnowledgeAgentConfiguration object passed to the agent.

For polling to occur, the polling and notifier services must be started:

2.3.2.1. Knowledge Agent and Custom ClassLoaders

Because Knowledge Agent could scan and process remote resources, it
could ends up failing when compiling or executing rules, queries, functions,
etc. that use classes outside the agent's classloader.
If this is your case, you could take 2 approach: use a custom classloader
for agent's kbuilder or force the agent to use the same classloader that
its kbase has.

2.3.2.1.1. Custom ClassLoaders for KnowledgeBuilder

Knowledge Agent uses KnowledgeBuilder internally in order to
compile managed resources. If you need to pass custom configuration to
these compilers you could pass a KnowledgeBuilderConfiguration object
to KnowledgeAgentFactory.newKnowledgeAgent(). This object will be used
in every builder the agent creates. Using a KnowledgeBuilderConfiguration
you can specify a custom classloader.

2.3.2.1.2. Reuse KnowledgeBase ClassLoader

Most of the times, the classloader you wan't to use in the
compilation process of remote resources is the same needed in the
agent's kbase, so the rules could be executed. If you want to use this
approach, you will need to setup the desired ClassLoader to the
agen't kbase and use the "drools.agent.useKBaseClassLoaderForCompiling"
property of KnowledgeAgentConfiguration object.

This approach lets you modify agent's kbuilder classloader in
runtime by modifying the classloader the agent's kbase uses. This will
serve also when not using incremental change set processing (see the
section below). When the kbase is recreated its configuration is
reused, so the classloader is maintained.

2.3.2.2. Incremental Change Set Processing

Knowledge Agent can process change sets in two different ways:
recreating the knowledge base every time a new change set is
processed or applying the change set in the cached knowledge base
without destroying it.
This behavior is controlled by the "newInstance" property of the
KnowledgeAgentConfiguration object passed to the Agent's constructor.

When "newInstace" is set to true (the default value), the agent
will destroy the cached Knowledge Base it contains and populate a
new one containing the change set modifications. When "newInstance"
is set to "false" change sets are applied directly to the cached
Knowledge Base. The rule that were not modified in the change sets'
resources are not replaced in the Knowledge Base, the modified or
deleted rules are modified or deleted from the cached Knowledge Base.
Functions, Queries and Definition Types are always replaced in the
cached Knowledge Base whether they are modified or not.

The following code snippet creates a new Knowledge Agent with its
"newInstace" property set to false

2.3.2.3. Remote HTTP resource caching

A note on remote HTTP Url Resources: if your knowledge agent is
"pulling" resources from a http(s) URL, then you might rightly be
concerned if that resource (remote web server) suddenly disappears. To
survive a restart when a resource is no longer available remotely (eg the
remote server is being restarted) then you can set a System Property:
drools.resource.urlcache to a directory that has write permissions for the
application: the Knowledge Agent will cache copies of the remote resources
in that local directory.

For example, using the java command line:
-Ddrools.resource.urlcache=/users/someone/KnowledgeCache - will keep local
copies of the resources (rules, packages etc) in that directory, for the
agent to use should it be restarted (when a remote resource becomes
available, and is updated, it will automatically update the local cache
copy).

Chapter 3. Advanced Concepts and Theory

3.1. Truth Maintenance with Logical Objects

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 3.1. Stated Insertion

Figure 3.2. Logical Insertion

3.1.1. Example Scenario

An example may make things clearer. Imagine a credit card
processing application, processing transactions for a given account and
we have a working memory accumulating knowledge about a single account
transaction. The rule engine is doing its best to decide whether
transactions are possibly fraudulent or not. Imagine that this rule base
basically has rules that kick in when there is "reason to be suspicious"
and when "everything is normal".

Of course there are many rules that operate no matter what,
performing standard calculations, etc. Now there are possibly many
reasons as to what could trigger a "reason to be suspicious": someone
notifying the bank, a sequence of large transactions, transactions for
geographically disparate locations, or even reports of credit card
theft. Rather then smattering all the little conditions in lots of
rules, imagine there is a fact class called "SuspiciousAccount".

Then there can be a series of rules whose job is to look for
things that may raise suspicion, and if they fire, they
logically insert a new SuspiciousAccount()
instance. All the other rules just have conditions like "not
SuspiciousAccount()" or "SuspiciousAccount()" depending on their needs.
Note that this has the advantage of allowing there to be many rules
around raising suspicion, without touching the other rules. After all
the facts causing the SuspiciousAccount() insertion are removed, the
account handling reverts to a normal mode of operation where, for
instance, a rule with "not SuspiciousAccount()" may kick in, which
flushes through any blocked transactions.

If you have followed this far, you will note that truth
maintenance, like logical assertions, allows rules to behave a little
like a human would, and can certainly make the rules more
manageable.

3.1.2. Lazy Truth Maintenance

You no longer need to enable or disable truth maintenance, via the
kbase configuration. It is now handled automatically and turned on only
when needed. This was done along with the code changes so that all entry
points use the same code, previous to this the default entry point and
named entry points used different code, to avoid TMS overhead for event
processing.

3.1.3. 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).

3.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 3.3. 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 3.4. 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 3.5. 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 3.6. 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.

4.1. Building

Figure 4.1. org.drools.builder

4.1.1. Building using Code

The KnowledgeBuilder is responsible for taking source files, such as
a DRL file or an Excel file, and turning them into a Knowledge Package of
rule and process definitions which a Knowledge Base can consume. An object
of the class ResourceType indicates the type of resource it is being
asked to build.

The ResourceFactory provides capabilities to load resources from a
number of sources, such as Reader, ClassPath, URL, File, or ByteArray.
Binaries, such as decision tables (Excel .xls files), should not use a Reader based
resource handler, which is only suitable for text based resources.

A configuration can be created using the KnowledgeBuilderFactory.
This allows the behavior of the Knowledge Builder to be modified. The most
common usage is to provide a custom class loader so that the KnowledgeBuilder
object can resolve classes that are not in the default classpath. The first parameter
is for properties and is optional, i.e., it may be left null, in which case the
default options will be used. The options parameter can be used for things
like changing the dialect or registering new accumulator functions.

Example 4.2. Creating a new KnowledgeBuilder with a custom ClassLoader

Resources of any type can be added iteratively. Below, a DRL file is
added. Unlike Drools 4.0 Package Builder, the Knowledge Builder can now
handle multiple namespaces, so you can just keep adding resources
regardless of namespace.

It is best practice to always check the hasErrors() method after an
addition. You should not add more resources or retrieve the Knowledge Packages
if there are errors. getKnowledgePackages() returns an empty list if
there are errors.

When all the resources have been added and there are no errors the
collection of Knowledge Packages can be retrieved. It is a Collection because
there is one Knowledge Package per package namespace. These
Knowledge Packages are serializable and often used as a unit of
deployment.

4.1.2. Building using Configuration and the ChangeSet XML

Instead of adding the resources to create definitions
programmatically it is also possible to do it by configuration, via the
ChangeSet XML. The simple XML file supports
three elements: add, remove, and modify, each of which has a sequence
of <resource> subelements defining a configuration entity. The
following XML schema is not normative and
intended for illustration only.

Notice the file: prefix, which signifies the protocol for the
resource. The Change Set supports all the protocols provided by
java.net.URL, such as "file" and "http", as well as an additional
"classpath". Currently the type attribute must always be specified for a
resource, as it is not inferred from the file name extension. Using the
ClassPath resource loader in Java allows you to specify the Class Loader to
be used to locate the resource but this is not possible from XML. Instead,
the Class Loader will default to the one used by the Knowledge Builder
unless the ChangeSet XML is itself loaded by the ClassPath resource, in
which case it will use the Class Loader specified for that resource.

Currently you still need to use the API to load that ChangeSet, but
we will add support for containers such as Spring in the future, so that the
process of creating a Knowledge Base can be done completely by XML configuration.
Loading resources using an XML file couldn't be simpler, as it's just another
resource type.

ChangeSets can include any number of resources, and they even support
additional configuration information, which currently is only needed for
decision tables. Below, the example is expanded to load rules from a
http URL location, and an Excel decision table from the classpath.

The ChangeSet is especially useful when working with a Knowledge Agent,
as it allows for change notification and automatic rebuilding of the
Knowledge Base, which is covered in more detail in the section on the
Knowledge Agent, under Deploying.

Directories can also be specified, to add all resources
in that folder. Currently it is expected that all resources in
that folder are of the same type. If you use the Knowledge Agent it will
provide a continous scanning for added, modified or removed resources and
rebuild the cached Knowledge Base. The KnowledgeAgent provides more
information on this.

4.2. Deploying

4.2.1. KnowledgePackage and Knowledge Definitions

A Knowledge Package is a collection of Knowledge Definitions, such
as rules and processes. It is created by the Knowledge Builder, as
described in the chapter "Building". Knowledge Packages are self-contained and
serializable, and they currently form the basic deployment unit.

Figure 4.4. KnowledgePackage

Knowledge Packages are added to the Knowledge Base. However, a
Knowledge Package instance cannot be reused once it's added to the
Knowledge Base. If you need to add it to another Knowledge Base, try
serializing it first and using the "cloned" result. We hope to fix this
limitation in future versions of Drools.

4.2.2. KnowledgeBase

The Knowlege Base is a repository of all the application's knowledge
definitions. It may contain rules, processes, functions, and type models.
The Knowledge Base itself does not contain instance data, known as facts;
instead, sessions are created from the Knowledge Base into which data can be
inserted and where process instances may be started. Creating the
Knowlege Base can be
heavy, whereas session creation is very light, so it is recommended that
Knowledge Bases be cached where possible to allow for repeated session
creation.

Figure 4.5. KnowledgeBase

A KnowledgeBase object is also serializable, and some people
may prefer to build and then store a KnowledgeBase, treating it also
as a unit of deployment, instead of the Knowledge Packages.

The KnowlegeBase is created using the KnowledgeBaseFactory.

Figure 4.6. KnowledgeBaseFactory

A KnowledgeBase can be created using the default
configuration.

Example 4.12. Creating a new KnowledgeBase

KnowledgeBase kbase =KnowledgeBaseFactory.newKnowledgeBase();

If a custom class loader was used with the KnowledgeBuilder to
resolve types not in the default class loader, then that must also be set
on the KnowledgeBase. The technique for this is the same as with the
KnowledgeBuilder.

4.2.3. In-Process Building and Deployment

This is the simplest form of deployment. It compiles the
knowledge definitions and adds them to the Knowledge Base in the same JVM.
This approach requires drools-core.jar and drools-compiler.jar to be on
the classpath.

Note that the addKnowledgePackages(kpkgs) method can be called
iteratively to add additional knowledge.

4.2.4. Building and Deployment in Separate Processes

Both the KnowledgeBase and the KnowledgePackage
are units of
deployment and serializable. This means you can have one machine do any
necessary building, requiring drools-compiler.jar, and
have another machine deploy and execute everything, needing only
drools-core.jar.

Although serialization is standard Java, we present an example of
how one machine might write out the deployment unit and how another
machine might read in and use that deployment unit.

The KnowledgeBase is also serializable and some people may prefer
to build and then store the KnowledgeBase itself, instead of the
Knowledge Packages.

Drools Guvnor, our server side management system, uses this
deployment approach. After Guvnor has compiled and published serialized
Knowledge Packages on a URL, Drools can use the URL resource type
to load them.

4.2.5. StatefulknowledgeSessions and KnowledgeBase Modifications

Stateful Knowledge Sessions will be discussed in more detail in
section "Running". The KnowledgeBase creates and returns
StatefulKnowledgeSession objects, and it may optionally
keep references to those.
When KnowledgeBase 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.6. KnowledgeAgent

The KnowlegeAgent provides automatic loading, caching and
re-loading of resources and is configured from a properties files. The
Knowledge Agent can update or rebuild this Knowlege Base as the
resources it uses are changed. The strategy for this is determined by the configuration
given to the factory, but it is typically pull-based using regular
polling. We hope to add push-based updates and rebuilds in future
versions. The Knowledge Agent will continuously scan all the added
resources, using a default polling interval of 60 seconds. If their
date of the last modification is updated it will rebuild the cached
Knowledge Base using the new resources.

Figure 4.7. KnowledgeAgent

The KnowlegeBuilder is created using a
KnowledgeBuilderFactory object.
The agent must specify a name, which is used in the log files to associate
a log entry with the corresponding agent.

The following example constructs an agent that will build a new
KnowledgeBase from the specified ChangeSet. (See section "Building" for
more details on the ChangeSet format.) Note that the method can be called
iteratively to add new resources over time.
The Knowledge Agent polls the resources added from the ChangeSet
every 60 seconds, the default interval, to see if they are updated.
Whenever changes are found it will construct a new Knowledge Base or apply
the modifications to the existing Knowledge Base according to its
configuration.
If the change set specifies a resource that
is a directory its contents will be scanned for changes, too.

The default resource scanning period may be changed via the
ResourceChangeScannerService. A suitably updated
ResourceChangeScannerConfiguration object is passed to the service's
configure() method, which allows for the service to be reconfigured on
demand.

Knowledge Agents can take an empty Knowledge Base or a populated one.
If a populated Knowledge Base is provided, the Knowledge Agent will
run an iterator from Knowledge Base and subscribe to the resources that
it finds. While it is
possible for the Knowledge Builder to build all resources found in a
directory, that information is lost by the Knowledge Builder so that those
directories will not be continuously scanned. Only directories specified
as part of the applyChangeSet(Resource) method are monitored.

One of the advantages of providing KnowledgeBase as the starting
point is that you can provide it with a KnowledgeBaseConfiguration. When
resource changes are detected and a new KnowledgeBase object is
instantiated, it will use the KnowledgeBaseConfiguration of the previous
KnowledgeBase object.

In the above example getKnowledgeBase() will return the same
provided kbase instance until resource changes are detected and a new
Knowledge Base is built. When the new Knowledge Base is built, it will be
done with the KnowledgeBaseConfiguration that was provided to
the previous KnowledgeBase.

As mentioned previously, a ChangeSet XML can specify a directory and
all of its contents will be added. If this ChangeSet XML is used with the
applyChangeSet() method it will also add any directories to the scanning
process. When the directory scan detects an additional file, it will be
added to the Knowledge Base; any removed file is removed from the
Knowledge Base, and modified files will be removed from the Knowledge Base.

Note that for the resource type PKG the drools-compiler dependency is
not needed as the Knowledge Agent is able to handle those with just
drools-core.

The KnowledgeAgentConfiguration can be used to modify a
Knowledge Agent's default behavior. You could use this to load
the resources from a directory, while inhibiting the continuous scan
for changes of that directory.

Previously we mentioned Drools Guvnor and how it can build and
publish serialized Knowledge Packages on a URL, and that the
ChangeSet XML can handle URLs and Packages. Taken together, this forms
an importanty deployment scenario for the Knowledge Agent.

4.3. Running

4.3.1. KnowledgeBase

The KnowlegeBase is a repository of all the
application's knowledge definitions. It will contain rules, processes,
functions, and type models. The Knowledge Base itself does not contain
data; instead, sessions are created from the KnowledgeBase
into which data can be inserted and from which process instances may be
started. Creating the KnowlegeBase can be heavy, whereas
session creation is very light, so it is recommended that Knowle Bases be
cached where possible to allow for repeated session creation.

Example 4.24. Creating a new KnowledgeBase

KnowledgeBase kbase =KnowledgeBaseFactory.newKnowledgeBase();

4.3.2. StatefulKnowledgeSession

The StatefulKnowledgeSession stores and executes on the
runtime data. It is created from the KnowledgeBase.

4.3.3. KnowledgeRuntime

4.3.3.1. WorkingMemoryEntryPoint

The WorkingMemoryEntryPoint provides the methods
around inserting, updating and retrieving facts. The term "entry point"
is related to the fact that we have multiple partitions in a Working
Memory and you can choose which one you are inserting into, although
this use case is aimed at event processing and covered in more detail in
the Fusion manual. Most rule based applications will work with the
default entry point alone.

The KnowledgeRuntime interface provides the main
interaction with the engine. It is available in rule consequences and
process actions. In this manual the focus is on the methods and
interfaces related to rules, and the methods pertaining to processes
will be ignored for now. But you'll notice that the
KnowledgeRuntime inherits methods from both the
WorkingMemory and the ProcessRuntime, thereby
providing a unified API to work with processes and rules. When working
with rules, three interfaces form the KnowledgeRuntime:
WorkingMemoryEntryPoint, WorkingMemory and the
KnowledgeRuntime itself.

Figure 4.10. WorkingMemoryEntryPoint

4.3.3.1.1. Insertion

Insertion is the act of telling the WorkingMemory
about a fact, which you do by
ksession.insert(yourObject), for example. When you insert
a fact, it is examined for matches against the rules. This means
all of the work for deciding about firing or not
firing a rule is done during insertion; no rule, however, is executed
until you call fireAllRules(), which you call after you
have finished inserting your facts. It is a common misunderstanding
for people to think the condition evaluation happens when you call
fireAllRules(). Expert systems typically use the term
assert or assertion to refer
to facts made available to the system. However, due to "assert" being
a keyword in most languages, we have decided to use the
insert keyword; so expect to hear the two used
interchangeably.

When an Object is inserted it returns a FactHandle.
This FactHandle is the token used to represent your
inserted object within the WorkingMemory. It is also used
for interactions with the WorkingMemory when you wish to
retract or modify an object.

As mentioned in the Knowledge Base section, a Working Memory may
operate in two assertion modes, i.e., equality or identity, with
identity being the default.

Identity means that the Working Memory uses
an IdentityHashMap to store all asserted objects. New
instance assertions always result in the return of a new
FactHandle, but if an instance is asserted again then it
returns the original fact handle, i.e., it ignores repeated insertions
for the same fact.

Equality means that the Working Memory uses
a HashMap to store all asserted Objects. New instance
assertions will only return a new FactHandle if no equal
objects have been asserted.

4.3.3.1.2. Retraction

Retraction is the removal of a fact from Working Memory, which
means that it will no longer track and match that fact, and any rules
that are activated and dependent on that fact will be cancelled. Note
that it is possible to have rules that depend on the nonexistence of a
fact, in which case retracting a fact may cause a rule to activate.
(See the not and exist keywords.) Retraction
is done using the FactHandle that was returned by the
insert call.

4.3.3.1.3. Update

The Rule Engine must be notified of modified facts, so that they
can be reprocessed. Internally, modification is actually a retract
followed by an insert; the Rule Engine removes the fact from the
WorkingMemory and inserts it again. You must use the
update() method to notify the WorkingMemory
of changed objects for those objects that are not able to notify the
WorkingMemory themselves. Notice that
update() always takes the modified object as a second
parameter, which allows you to specify new instances for immutable
objects. The update() method can only be used with
objects that have shadow proxies turned on. The update method is only
available within Java code. On the right hand side of a rule, also the
modify statement is supported, providing simplified
calls to the object's setters.

4.3.3.2. WorkingMemory

The WorkingMemory provides access to the Agenda, permits query
executions, and lets you access named Enty Points.

Figure 4.11. WorkingMemory

4.3.3.2.1. Query

Queries are used to retrieve fact sets based on patterns, as
they are used in rules. Patterns may make use of optional parameters.
Queries can be defined in the Knowlege Base, from where they are
called up to return the matching results. While iterating over the
result collection, any bound identifier in the query can be accessed
using the get(String identifier) method and any FactHandle for that
identifier can be retrieved using getFactHandle(String
identifier).

4.3.3.2.2. Live Querries

Drools has always had query support, but the result was returned
as an iterable set; this makes it hard to monitor changes over
time.

We have now complimented this with Live Querries, which has a
listener attached instead of returning an iterable result set. These
live querries stay open creating a view and publish change events for
the contents of this view. So now you can execute your query, with
parameters and listen to changes in the resulting view.

4.3.3.3. KnowledgeRuntime

The KnowledgeRuntime provides further methods that
are applicable to both rules and processes, such as setting globals and
registering Channels (previously exit points, some
references may remain in docs for a while).

Figure 4.14. KnowledgeRuntime

4.3.3.3.1. Globals

Globals are named objects that can be passed to the rule engine,
without needing to insert them. Most often these are used for static
information, or for services that are used in the RHS of a rule, or
perhaps as a means to return objects from the rule engine. If you use
a global on the LHS of a rule, make sure it is immutable. A global
must first be declared in a rules file before it can be set on the
session.

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()
for any session. Failure to declare the global type and identifier
first will result in an exception being thrown. To set the global on
the session use ksession.setGlobal(identifier,
value):

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

If a rule evaluates on a global before you set it you will get a
NullPointerException.

4.3.3.4. StatefulRuleSession

The StatefulRuleSession is inherited by the
StatefulKnowledgeSession and provides the rule related
methods that are relevant from outside of the engine.

Figure 4.15. StatefulRuleSession

4.3.3.4.1. Agenda Filters

Figure 4.16. AgendaFilters

AgendaFilter objects are optional implementations
of the filter interface which are used to allow or deny the firing of
an activation. What you filter on is entirely up to the
implementation. Drools 4.0 used to supply some out of the box filters,
which have not be exposed in drools 5.0 knowledge-api, but they are
simple to implement and the Drools 4.0 code base can be referred
to.

To use a filter specify it while calling
fireAllRules(). The following example permits only rules
ending in the string "Test". All others will be filtered
out.

ksession.fireAllRules(newRuleNameEndsWithAgendaFilter("Test"));

4.3.4. Agenda

The Agenda is a Rete feature. During actions on
the WorkingMemory, rules may become fully matched and
eligible for execution; a single Working Memory Action can result in
multiple eligible rules. When a rule is fully matched an Activation is
created, referencing the rule and the matched facts, and placed onto the
Agenda. The Agenda controls the execution order of these Activations using
a Conflict Resolution strategy.

The engine cycles repeatedly through two phases:

Working Memory 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 Working Memory Actions.

Figure 4.17. Two Phase Execution

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

Figure 4.18. Agenda

4.3.4.1. Conflict Resolution

Conflict resolution is required when there are multiple rules on
the agenda. (The basics to this are covered in chapter "Quick Start".)
As firing a rule may have side effects on the working memory, the rule
engine needs to know in what order the rules should fire (for instance,
firing ruleA may cause ruleB to be removed from the agenda).

The most visible one is salience (or
priority), in which case a user can specify that a certain rule has a
higher priority (by giving it a higher number) than other rules. In that
case, the rule with higher salience will be preferred. LIFO priorities
are based on the assigned Working Memory Action counter value, with all
rules created during the same action receiving the same value. The
execution order of a set of firings with the same priority value is
arbitrary.

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,
including but not limited to: agenda groups, rule flow groups,
activation groups, control/semaphore facts. These are discussed in later
sections.

Drools 4.0 supported custom conflict resolution strategies; while
this capability still exists in Drools it has not yet been exposed to
the end user via knowledge-api in Drools 5.0.

4.3.4.2. AgendaGroup

Figure 4.19. AgendaGroup

Agenda groups are a way to partition rules (activations, actually)
on the agenda. At any one time, only one group has "focus" which means
that activations for rules in that group only will take effect. You can
also have rules with "auto focus" which means that the focus is taken
for its agenda group when that rule's conditions are true.

Agenda groups are known as "modules" in CLIPS terminology. While
it best to design rules that do not need control flow, this is not
always possible. Agenda groups provide a handy way to create a "flow"
between grouped rules. You can switch the group which has focus either
from within the rule engine, or via the API. If your rules have a clear
need for multiple "phases" or "sequences" of processing, consider using
agenda-groups for this purpose.

Each time setFocus() is called it pushes that Agenda
Group onto a stack. When the focus group is empty it is popped from the
stack and the focus group that is now on top evaluates. An Agenda Group
can appear in multiple locations on the stack. The default Agenda Group
is "MAIN", with all rules which do not specify an Agenda Group being in
this group. It is also always the first group on the stack, given focus
initially, by default.

ksession.getAgenda().getAgendaGroup("Group A").setFocus();

4.3.4.3. ActivationGroup

Figure 4.20. ActivationGroup

An activation group is a set of rules bound together by the same
"activation-group" rule attribute. In this group only one rule can fire,
and after that rule has fired all the other rules are cancelled from the
agenda. The clear() method can be called at any time, which
cancels all of the activations before one has had a chance to
fire.

ksession.getAgenda().getActivationGroup("Group B").clear();

4.3.4.4. RuleFlowGroup

Figure 4.21. RuleFlowGroup

A rule flow group is a group of rules associated by the
"ruleflow-group" rule attribute. These rules can only fire when the
group is activate. The group itself can only become active when the
elaboration of the ruleflow diagram reaches the node representing the
group. Here too, the clear() method can be called at any
time to cancels all activations still remaining on the Agenda.

ksession.getAgenda().getRuleFlowGroup("Group C").clear();

4.3.5. Event Model

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

The KnowlegeRuntimeEventManager interface is
implemented by the KnowledgeRuntime which provides two
interfaces, WorkingMemoryEventManager and
ProcessEventManager. We will only cover the
WorkingMemoryEventManager here.

Figure 4.22. KnowledgeRuntimeEventManager

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

Figure 4.23. WorkingMemoryEventManager

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

Drools also provides DebugWorkingMemoryEventListener
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.29. Creating a new KnowledgeBuilder

ksession.addEventListener(newDebugWorkingMemoryEventListener());

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

Figure 4.24. KnowlegeRuntimeEvent

The events currently supported are:

ActivationCreatedEvent

ActivationCancelledEvent

BeforeActivationFiredEvent

AfterActivationFiredEvent

AgendaGroupPushedEvent

AgendaGroupPoppedEvent

ObjectInsertEvent

ObjectRetractedEvent

ObjectUpdatedEvent

ProcessCompletedEvent

ProcessNodeLeftEvent

ProcessNodeTriggeredEvent

ProcessStartEvent

4.3.6. KnowledgeRuntimeLogger

The KnowledgeRuntimeLogger 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.3.7. StatelessKnowledgeSession

The StatelessKnowledgeSession wraps the
StatefulKnowledgeSession, instead of extending it. Its main
focus is on 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 StatefulKnowledgeSession, 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.26. StatelessKnowledgeSession

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.

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

The Stateless Knowledge Session 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.33. Session scoped global

StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();//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.34. 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.3.7.1. Sequential Mode

With Rete you have a stateful session where objects can be
asserted and modified over time, and where rules can also be added and
removed. Now what happens if we assume a stateless session, where after
the initial data set no more data can be asserted or modified and rules
cannot be added or removed? Certainly it won't be necessary to
re-evaluate rules, and the engine will be able to operate in a
simplified way.

Order the Rules by salience and position in the ruleset (by
setting a sequence attribute on the rule terminal node).

Create an array, one element for each possible rule
activation; element position indicates firing order.

Turn off all node memories, except the right-input Object
memory.

Disconnect the Left Input Adapter Node propagation, and let
the Object plus the Node be referenced in a Command object, which is
added to a list on the Working Memory for later execution.

Assert all objects, and, when all assertions are finished and
thus right-input node memories are populated, check the Command list
and execute each in turn.

All resulting Activations should be placed in the array, based
upon the determined sequence number of the Rule. Record the first
and last populated elements, to reduce the iteration range.

Iterate the array of Activations, executing populated element
in turn.

If we have a maximum number of allowed rule executions, we can
exit our network evaluations early to fire all the rules in the
array.

The LeftInputAdapterNode no longer creates a Tuple,
adding the Object, and then propagate the Tuple – instead a Command
object is created and added to a list in the Working Memory. This
Command object holds a reference to the
LeftInputAdapterNode and the propagated object. This stops
any left-input propagations at insertion time, so that we know that a
right-input propagation will never need to attempt a join with the
left-inputs (removing the need for left-input memory). All nodes have
their memory turned off, including the left-input Tuple memory but
excluding the right-input object memory, which means that the only node
remembering an insertion propagation is the right-input object memory.
Once all the assertions are finished and all right-input memories
populated, we can then iterate the list of
LeftInputAdatperNode Command objects calling each in turn.
They will propagate down the network attempting to join with the
right-input objects, but they won't be remembered in the left input as
we know there will be no further object assertions and thus propagations
into the right-input memory.

There is no longer an Agenda, with a priority queue to schedule
the Tuples; instead, there is simply an array for the number of rules.
The sequence number of the RuleTerminalNode indicates the
element within the array where to place the Activation. Once all Command
objects have finished we can iterate our array, checking each element in
turn, and firing the Activations if they exist. To improve performance,
we remember the first and the last populated cell in the array. The
network is constructed, with each RuleTerminalNode being
given a sequence number based on a salience number and its order of
being added to the network.

Typically the right-input node memories are Hash Maps, for fast
object retraction; here, as we know there will be no object retractions,
we can use a list when the values of the object are not indexed. For
larger numbers of objects indexed Hash Maps provide a performance
increase; if we know an object type has only a few instances, indexing
is probably not advantageous, and a list can be used.

Sequential mode can only be used with a Stateless Session and is
off by default. To turn it on, either call
RuleBaseConfiguration.setSequential(true), or set the
rulebase configuration property drools.sequential to true.
Sequential mode can fall back to a dynamic agenda by calling
setSequentialAgenda with
SequentialAgenda.DYNAMIC. You may also set the
"drools.sequential.agenda" property to "sequential" or "dynamic".

4.3.8. Commands and the CommandExecutor

Drools has the concept of stateful or stateless sessions. We've
already covered stateful sessions, which use the standard working memory
that can be worked with iteratively over time. Stateless is a one-off
execution of a working memory 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 a rule
engine like a function call with optional return results.

In Drools 4 we supported these two paradigms but the way the user
interacted with them was different. StatelessSession used an execute(...)
method which would insert a collection of objects as facts.
StatefulSession didn't have this method, and insert used the more
traditional insert(...) method. The other issue was that the
StatelessSession did not return any results, so that users themselves had
to map globals to get results, and it wasn't possible to do anything
besides inserting objects; users could not start processes or execute
queries.

Drools 5.0 addresses all of these issues and more. The foundation
for this is the CommandExecutor interface, which both the
stateful and stateless interfaces extend, creating consistency and
ExecutionResults:

Figure 4.27. CommandExecutor

Figure 4.28. ExecutionResults

The CommandFactory allows for commands to be executed
on those sessions, the only difference being that the Stateless Knowledge
Session executes fireAllRules() at the end before disposing
the session. The currently supported commands are:

FireAllRules

GetGlobal

SetGlobal

InsertObject

InsertElements

Query

StartProcess

BatchExecution

InsertObject will insert a single object, with an
optional "out" identifier. InsertElements will iterate an
Iterable, inserting each of the elements. What this means is that a
Stateless Knowledge Session is no longer limited to just inserting
objects, it can now start processes or execute queries, and do this in any
order.

The execute method only allows for a single command. That's where
BatchExecution comes in, which represents a composite
command, created from a list of commands. Now, execute 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.

As mentioned previosly, the Stateless Knowledge Session 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
StatelessKnowledgeSession. 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.

Commands support out identifiers. Any command that has an out
identifier set on it will add its results to the returned ExecutionResults
instance. Let's look at a simple example to see how this works.

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.

A custom XStream marshaller can be used with the Drools Pipeline to
achieve XML scripting, which is perfect for services. Here are two simple
XML samples, one for the BatchExecution and one for the
ExecutionResults.

The BatchExecutionHelper provides a configured XStream
instance to support the marshalling of Batch Executions, where the
resulting XML can be used as a message format, as shown above. Configured
converters only exist for the commands supported via the Command Factory.
The user may add other converters for their user objects. This is very
useful for scripting stateless or stateful knowledge sessions, especially
when services are involved.

There is currently no XML schema to support schema validation. The
basic format is outlined here, and the drools-pipeline module has an
illustrative unit test in the XStreamBatchExecutionTest unit
test. The root element is <batch-execution> and it can contain zero
or more commands elements.

Example 4.42. Root XML element

<batch-execution>...</batch-execution>

This contains a list of elements that represent commands, the
supported commands is limited to those Commands provided by the Command
Factory. The most basic of these is the <insert> element, which
inserts objects. The contents of the insert element is the user object, as
dictated by XStream.

It's also possible to insert a collection of objects using the
<insert-elements> element. This command does not support an
out-identifier. The org.domain.UserClass is just an
illustrative user object that XStream would serialize.

<set-global> also supports two other optional
attributes, out and out-identifier.
A true value for the boolean out will add the global to
the <batch-execution-results> payload, using the name
from the identifier attribute.
out-identifier works like out but
additionally allows you to override the identifier used in the
<batch-execution-results> payload.

There is also a <get-global> element, without
contents, with just an out-identifier attribute. (There
is no need for an out attribute because retrieving the
value is the sole purpose of a <get-global>
element.

While the out attribute is useful in returning
specific instances as a result payload, we often wish to run actual
queries. Both parameter and parameterless queries are supported. The
name attribute is the name of the query to be called,
and the out-identifier is the identifier to be used for
the query results in the <execution-results>
payload.

However, with marshalling you need more flexibility when dealing
with referenced user data. To achieve this we have 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 used in the
example above, and it just calls the Serializable or
Externalizable methods on a user instance.
IdentityMarshallingStrategy instead 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
he code to use an Identity Marshalling Strategy.

For added flexability we can't assume that a single strategy is
suitable. Therefore we have added the
ObjectMarshallingStrategyAcceptor interface that each Object
Marshalling Strategy contains. The Marshaller has a chain of strategies,
and when it attempts to read or write a user object it iterates the
strategies asking if they accept responsability 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 array.

4.3.10. Persistence and Transactions

Longterm out of the box persistence with Java Persistence API (JPA)
is possible with Drools. You will need to have some implementation of the
Java Transaction API (JTA) installed. For development purposes we
recommend the Bitronix Transaction Manager, 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, so you can
continue to use it after a rollback. To load a previously persisted
Stateful Knowledge Session 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
contsulted for details. For a quick start, here is the programmatic
approach:

4.3.11. Drools Clips

Drools Clips is an alpha level research project to provide a Clips
like front end ot Drools. As of Drools 5.2 this module as stopped working,
we will try and fix for 5.3.

Deftemplates are working, the knowledge base handles multiple name
spaces and you can attach the knoweldge base to the session for interative
building, to provide a more "shell" like environment suitable for
Clips.

deftemplate

defrule

deffunction

and/or/not/exists/test conditional elements

Literal, Variable, Return Value and Predicate field
constarints

This project is very early stages and in need of love. If you want
to help, open up eclipse import api, core, compiler and clips and you
should be good to go. The unit tests should be self explanatory.

5.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.

5.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 5.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.

5.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.

5.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:

5.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.

5.3.1. Single line comment

Figure 5.1. Single line comment

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

rule "Testing Comments"
when
# this is a single line comment
// this is also 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
# this is another comment in a semantic code block
end

5.3.2. Multi-line comment

Figure 5.2. 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

5.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.

5.4.1. Message format

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

Figure 5.3. 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.

5.4.2. Error Messages Description

5.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 5.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.

5.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:

5.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.

5.4.3. Other Messages

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

5.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 5.4. package

Notice that any rule atttribute (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.

5.5.1. import

Figure 5.5. 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.

5.5.2. global

Figure 5.6. 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.

5.6. Function

Figure 5.7. 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:

5.7. Type Declaration

Figure 5.8. meta_data

Figure 5.9. 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.

5.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.

Example 5.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:

5.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 5.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.:

@position can be used to declare the position of a field, overriding
the default declared order. This is used for positional constraints in
patterns.

5.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.

5.7.2.1.1. @role( <fact | event> )

See Drools Fusion documentation for details.

5.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.

5.7.2.1.3. @timestamp( <attribute name> )

See Drools Fusion documentation for details.

5.7.2.1.4. @duration( <attribute name> )

See Drools Fusion documentation for details.

5.7.2.1.5. @expires( <time interval> )

See Drools Fusion documentation for details.

5.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.

Example 5.17. @propertyChangeSupport

declare Person
@propertyChangeSupport
end

5.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.

5.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
constructutor taking firstName and lastName as parameters, allowing
one to create instances with a code like this:

Example 5.19. creating an instance using the key constructor

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

5.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 interpretted 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
overiden 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. Inheritence 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 posional arguments, but not
variables.

5.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.

5.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.

5.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.

5.8. Rule

Figure 5.10. 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 5.24. Rule Syntax Overview

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

5.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 5.11. 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. In other
words, the first rule in an activation-group to fire will cancel the
other rules' activations, 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 5.27. Some attribute examples

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

5.8.2. Timers and Calendars

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

5.8.3. Left Hand Side (when) syntax

5.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?

5.8.3.2. Pattern (conditional element)

5.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 5.13. 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.

5.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.

5.8.3.3. Constraint (part of a pattern)

5.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.

5.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.

5.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

5.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.

5.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
occurance, and constrain to the same value of the bound field for
sequence occurances.

5.8.3.3.7. Special literal support

5.8.3.3.7.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.

5.8.3.3.10.5. The operator not contains

The operator not contains is used to check
whether a field that is a Collection or array does not
contain the specified value.

Example 5.40. 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.

5.8.3.3.10.6. The operator memberOf

The operator memberOf is used to check
whether a field is a member of a collection or array; that
collection must be a variable.

Example 5.41. Literal Constraint with Collections

CheeseCounter( cheese memberOf $matureCheeses )

5.8.3.3.10.7. The operator not memberOf

The operator not memberOf is used to check
whether a field is not a member of a collection or array; that
collection must be a variable.

Example 5.42. Literal Constraint with Collections

CheeseCounter( cheese not memberOf $matureCheeses )

5.8.3.3.10.8. 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).

5.8.3.3.10.9. 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 )

5.8.3.3.10.10. 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
==.

5.8.3.3.11. Inline eval operator (deprecated)

Figure 5.18. 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.

5.8.3.3.12. Operator precedence

The operators are evaluated in this precedence:

Table 5.1. Operator precedence

Operator type

Operators

Notes

(nested) 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

5.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 interpretted 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 posional arguments, but not variables.
Positional arguments are always resolved using unification.

Positional arguments that are given a previously declared binding
will consrain 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.

5.8.3.5. Basic conditional elements

5.8.3.5.1. Conditional Element and

The Conditional Element "and" is used to
group other Conditional Elements into a logical conjunction. Drools
supports both prefix and and infix
and.

Note

The symbol || (as an alternative to
or) is deprecated. But it is still supported in
the syntax for backwards compatibility.

Figure 5.22. 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.

5.8.3.5.3. Conditional Element not

Figure 5.23. 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.

5.8.3.5.4. Conditional Element exists

Figure 5.24. 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.

5.8.3.6. Advanced conditional elements

5.8.3.6.1. Conditional Element forall

Figure 5.25. 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.

5.8.3.6.2. Conditional Element from

Figure 5.26. 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:

rule "Assign people in North Carolina (NC) to sales region 1"
ruleflow-group "test"
lock-on-active true
when
$p : Person($addresses : addresses)
exists (Address(state == "NC") from $addresses)
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($addresses : addresses)
exists (Address(city == "Raleigh") from $addresses)
then
modify ($p) {} #Apply discount to person in a modify block
end

However, the following slightly different approach does exhibit
the problem:

rule "Assign people in North Carolina (NC) to sales region 1"
ruleflow-group "test"
lock-on-active true
when
$assessment : Assessment()
$p : Person()
$addresses : List() from $p.addresses
exists (Address( state == "NC") from $addresses)
then
modify ($assessment) {} #Modify assessment in a modify block
end
rule "Apply a discount to people in the city of Raleigh"
ruleflow-group "test"
lock-on-active true
when
$assessment : Assessment()
$p : Person()
$addresses : List() from $p.addresses
exists (Address( city == "Raleigh") from $addresses)
then
modify ($assessment) {} #Modify assessment in a modify block
end

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.

5.8.3.6.3. Conditional Element collect

Figure 5.27. 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

5.8.3.6.4. Conditional Element accumulate

Figure 5.28. 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 doing. Basically, what it does is that it allows a rule to
iterate over a collection of objects, executing custom actions for
each of the elements, and at the end it returns a result
object.

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 extremely hard to maintain, and frequently
leads to code duplication. Accumulate functions are easier to test and
reuse.

5.8.3.6.4.1. Accumulate Functions

The accumulate CE is a very powerful CE, but it gets real
declarative and easy to use when using predefined functions that are
known as Accumulate Functions. They work exactly like accumulate,
but instead of explicitly writing custom code in every accumulate
CE, the user can use predefined code for common operations.

For instance, a rule to apply a 10% discount on orders over
$100 could be written in the following way, using Accumulate
Functions:

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 Functions all one needs to do is to
create a Java class that implements the
org.drools.runtime.rule.TypedAccumulateFunction
interface and add a line to the configuration file or set a system
property to let the engine know about the new function. As an
example of an Accumulate Function implementation, the following is
the implementation of the 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 plug the function into the engine, we added it to the
configuration file:

Here, "drools.accumulate.function." is a prefix that must
always be used, "average" is how the function will be used in the
rule file, and
"org.drools.base.accumulators.AverageAccumulateFunction" is the
fully qualified name of the class that implements the function
behavior.

5.8.3.6.4.2. Accumulate with inline custom code

Warning

The use of accumulate with inline custom code is not a good
practice for several reasons, including dificulties 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.

<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 retracted,
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 retract.

The accumulate CE can be used to execute
any action on source objects. The following example instantiates and
populates a custom object:

5.8.3.6.4.3. Multi-function Accumulates

The accumulate CE now supports multiple functions. For
instance, if one needs to find the minimum, maximum and average
value for the same set of data, instead of having to repeat the
accumulate statement 3 times, a single accumulate can be
used.

5.8.3.7. Conditional Element eval

Figure 5.29. 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.

5.8.3.8. Railroad diagrams

5.8.4. The Right Hand Side (then)

5.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, retractor modify working memory
data. To assist with that there are a few convenience methods you can
use to modify working memory; without having to first reference a
working memory instance.

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.)

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 retracted when there are no
more facts to support the truth of the currently firing rule.

retract(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 retract(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
KnowledgeContext. Its method
getKnowledgeRuntime() delivers an object of type
KnowledgeRuntime, 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.getKnowledgeRuntime().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.

MethodgetKnowledgeBase() returns the
KnowledgeBase 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.

5.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.

5.8.5. 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.

5.9. Query

Figure 5.30. 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 KnowledgeBase;
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 the declared type order in the type declaration matches the
argument position. But it possible to override these using the @position
annotation.

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. Inheritence of classes is supported,
but not interfaces of methods yet.

Queries can now call other queries, this combined with optional
query arguments provides deriviation query style backward chaining.
Positional and mixed positional/named type is supported. Literal
expressions can passed as query arguments, but at this stage you cannot
mix expressions with variables. Here s 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 received 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.runtime.rule.Variable.v - note you must use 'v' and not an
alternative instanceof 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 suported:

List and Map unification

Variables for the fields of facts

Expression unification - pred( X, X + 1, X * Y / 7 )

5.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.

5.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 accomodating 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.

5.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 5.58. 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 5.60. 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 5.61. 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.

5.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.

5.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.

5.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 attachements, 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 5.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 5.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 is customarily given the extension
.dsl. It is passed to the Knowledge Builder with
ResourceType.DSL. For a file using DSL definition, the extension
.dslr should be used. The Knowledge Builder expects
ResourceType.DSLR. The IDE, however, relies on file extensions
to correctly recognize and work with your rules file.

The DSL must be passed to the Knowledge Builder ahead of any rules
file using the DSL.

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.

5.11. XML Rule Language

As an option, Drools also supports a "native" rule language as an alternative to DRL. This allows you to
capture and manage your rules as XML data. Just like the non-XML DRL format,
the XML format is parsed into the internal "AST" representation - as fast as
possible (using a SAX parser). There is no external transformation step
required. All the features are available with XML that are available to
DRL.

5.11.1. When to use XML

There are several scenarios that XML is desirable. However, we
recommend that it is not a default choice, as XML is not readily human
readable (unless you like headaches) and can create visually bloated
rules.

If you do want to edit XML by hand, use a good schema aware editor
that provides nice hierarchical views of the XML, ideally visually
(commercial tools like XMLSpy, Oxygen etc are good, but cost money, but
then so do headache tablets).

Other scenarios where you may want to use the XML format are if you
have a tool that generates rules from some input (programmatically
generated rules), or perhaps interchange from another rule language, or
from another tool that emits XML (using XSLT you can easily transform
between XML formats). Note you can always generate normal DRL as
well.

Alternatively you may be embedding Drools in a product that already
uses XML for configuration, so you would like the rules to be in an XML
format. You may be creating your own rule language on XML - note that you
can always use the AST objects directly to create your own rule language
as well (the options are many, due to the open architecture).

5.11.2. The XML format

A full W3C standards (XMLSchema) compliant XSD is provided that
describes the XML language, which will not be repeated here verbatim. A
summary of the language follows.

In the preceding XML text you will see the typical XML
element, the package declaration, imports, globals, functions,
and the rule itself. Most of the elements are self explanatory
if you have some understanding of the Drools features.

The import elements import the types you wish to
use in the rule.

The global elements define global objects that can
be referred to in the rules.

The function contains a function declaration, for
a function to be used in the rules. You have to specify a return type,
a unique name and parameters, in the body goes a snippet of code.

In the above detail of the rule we see that the rule has LHS
and RHS (conditions and consequence) sections.
The RHS is simple, it is just a block of semantic code that will be
executed when the rule is activated. The LHS is slightly more
complicated as it contains nested elements for conditional elements,
constraints and restrictions.

A key element of the LHS is the Pattern element. This allows you to
specify a type (class) and perhaps bind a variable to an instance of that
class. Nested under the pattern object are constraints and restrictions
that have to be met. The Predicate and Return Value constraints
allow Java expressions to be embedded.

That leaves the conditional elements, not, exists, and, or etc. They
work like their DRL counterparts. Elements that are nested under and an
"and" element are logically "anded" together. Likewise with "or" (and you
can nest things further). "Exists" and "Not" work around patterns, to check
for the existence or nonexistence of a fact meeting the pattern's
constraints.

The Eval element allows the execution of a valid snippet of Java
code - as long as it evaluates to a boolean (do not end it with a
semi-colon, as it is just a fragment) - this can include calling a
function. The Eval is less efficient than the columns, as the rule engine
has to evaluate it each time, but it is a "catch all" feature for when you
can express what you need to do with Column constraints.

5.11.3. Legacy Drools 2.x XML rule format

5.11.4. Automatic transforming between formats (XML and DRL)

Drools comes with some utility classes to transform between formats.
This works by parsing the rules from the source format into the AST, and
then "dumping" out to the appropriate target format. This allows you, for
example, to write rules in DRL, and when needed, export to XML if
necessary at some point in the future.

Using combinations of the above, you can convert between any
format (including round trip). Note that DSLs will not be preserved (from
DRLs that are using a DSL) - but they will be able to be converted.

Feel free to make use of XSLT to provide all sorts of possibilities
for XML, XSLT and its ilk are what make XML powerful.

6.1. 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.1.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.1.2. Overview

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

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.

6.1.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.

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.

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 row numbers are appended to
guarantee unique rule names. 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 exsist 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".

6.1.4. Spreadsheet Syntax

6.1.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.1.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.1. 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.

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.

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.2. Rule attribute entries in the Rule Set area

Keyword

Initial

Value

PRIORITY

P

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

DURATION

D

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

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.1.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.3. 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 constaint 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.1.4.4. Examples

The various interpolations are illustrated in the following example.

Example 6.1. 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 alse 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 sinle 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.

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

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.1.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).

6.1.6. Managing Business Rules in Decision Tables

6.1.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.1.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.

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.1.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).

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.2. Templates

If you discover that you have a group of rules following
the same arrangement of patterns, constraints and actions on
the RHS, differing only in constants or names for objects or
fields, you might think of employing Drool's rule template feature
for generating the actual rules. You would write a
rule template file, containing the
textual skeleton of your rule and use the Drools template
compiler in combination with a collection of objects providing
the actual values for the "flesh" of the rules for their
instantiation.

The mechanism is very similar to what a macro processor
does. The major advantage proffered by template expansion is
that it's nicely integrated in the overall handling of
Knowledge Resources.

Caution

This is an experimental feature. In particular,
the API is subject to change.

6.2.1. The Rule Template File

A rule template file begins with a header defining the
placeholders, or formal template parameters
for the strings that are to be inserted during instantiation.
After the first line, which invariably contains template header,
you should write a number of lines, each of which contains a single
parameter name.

Example 6.2. Rule template file: template header

template headerparameter-name-1
...
parameter-name-n
...

The template header is followed by the text that is to
be replicated and interpolated with the actual parameters. It
may begin with a package statement, followed by some
additional lines. These
may be sectioned into one or more templates, each of them
between a pair of matching template and
end template statements. The template takes
an argument, which puts a name to the template. The name
can be a simple unquoted name or an arbitrary string enclosed
in double quotes. The template text between these lines may
contain one or more rules, constituting the "raw material"
for the expansion.

The resulting text will begin with the package line and the
header text following it, if present. Then, each template text
will be expanded individually, yielding one set of rules for each
of the actual parameter sets. Therefore, the structure of the
template sections affect the order of the generated rules, since
the generator iterates over the sections and then over the
set of actual parameters.

Any interpolation takes place between a pair of template
and end template statements, when this template is
expanded. The template text is scanned for occurrences of
parameter expansions written according to:

@{parameter-name}

The name between '@{' and '}' should be one of the parameter names
defined in the template header. The substitution is effected anywhere,
even within string literals.

An important parameter is available without having to be
included in the data source providing the actual values. The
parameter substitution
@{row.rowNumber}
expands to the integers 0, 1, 2, etc., providing a unique distinction
for the instantiation derived from a parameter set. You would use this
as part of each rule name, because, without this precaution, there
would be duplicate rule names. (You are, of course, free to use your
own identification included as an extra parameter.)

6.2.2. Expanding a Template

To expand a template, you must prepare a data source. This can
be a spreadsheet, as explained in the previous section. Here, we'll
concentrate on expansion driven by Java objects. There are two
straightforward ways of supplying values for a fixed set of names:
Java objects, in the JavaBeans style, and Maps. Both of them can
be arranged in a Collection, whose elements will be
processed during the expansion, resulting in an instantiation
for each element.

6.2.2.1. Instantiation from Java Objects

You may use a Java object that provides getter methods
corresponding to all of the parameter names of your template
file. If, for instance, you have defined a header

Although interpolation is pure text manipulation, the actual values
supplied may be of any type, just as long as this type provides a
reasonable toString() method. (For simple types, the
eponymous static method of the related class from java.lang
is used.)

Assuming that we have created a Collection<ParamSet>
for a template file template.drl, we can now proceed to
request its expansion.

The resulting string contains the expanded rules text. You could
write it to a file and proceed as usual, but it's also possible to
feed this to a KnowledgeBuilder and continue with the
resulting Knowledge Packages.

6.2.2.2. Instantiation from Maps

A Map that provides the values for substituting
template parameters should have a (string) key set matching all of
the parameter names. Again, values could be from any class, as long
as they provide a good toString() method. The expansion
would use the same approach, just differing in the way the
map collection is composed.

Note that the method getCodes() does returns the
EnumSet<ItemCode> field value as a String
value representing a multiple restriction, i.e., a test for one out
of a list of values.

The task of expanding a template, passing the resulting DRL text
to a Knowledge Builder and adding the resulting Knowledge Packages
to a Knowledge Base is generic. The utility class Expander
takes care of this, using a Knowledge Base, the InputStream
with the rule template and the collection of parameter sets.

We are now all set to prepare the Knowledge Base with some
generated rules. First, we define several parameter sets,
constructed as ParamSet objects, and add them to a
List, which is passed to the expand
method shown above. Then we launch a stateful session, insert a
few Item, and watch what happens.

Chapter 7. The Java Rule Engine API

7.1. Introduction

Drools provides an implementation of the Java Rule Engine API (known
as JSR94), which allows for support of multiple rule engines from a
single API. JSR94 does not deal in any way with the rule language
itself. W3C is working on the
Rule Interchange Format (RIF)
and the OMG has started to work on a standard based on
RuleML.
Recently Haley Systems has also proposed a rule language standard
called RML.

It should be remembered that the JSR94 standard represents the "least
common denominator" in features across rule engines. This means that
there is less functionality in the JSR94 API than in the standard
Knowledge (Drools and jBPM) API. So, by using JSR94, you forfeit the advantage of using the
full capabilities of the Drools Rule Engine. It is necessary to expose
further functionality, like globals and support for DRL, DSL and XML,
via property maps due to the very basic feature set of JSR94; this
introduces non-portable functionality. Furthermore, as JSR94 does not
provide a rule language, you are only solving a small fraction of the
complexity of switching rule engines with very little gain. So, while
we support JSR94, for those that insist on using it, we strongly
recommend you program against the Knowledge (Drools and jBPM) API.

7.2. How To Use

There are two parts to working with JSR94. The first part is the
administrative API that deals with building and registering RuleExecutionSet objects,
the second part is runtime session execution of these RuleExecutionSets.

7.2.1. Building and Registering RuleExecutionSets

The RuleServiceProviderManager manages the registration and
retrieval of RuleServiceProviders. The Drools RuleServiceProvider
implementation is automatically registered via a static block when the
class is loaded using Class.forNamem, in much the same way as JDBC
drivers.

Example 7.1. Automatic RuleServiceProvider Registration

//RuleServiceProviderImpl is registered to "http://drools.org/"// via a static initialization blockClass.forName("org.drools.jsr94.rules.RuleServiceProviderImpl");//Get the rule service provider from the provider manager.RuleServiceProvider ruleServiceProvider =RuleServiceProviderManager.getRuleServiceProvider("http://drools.org/");

The RuleServiceProvider provides access to the RuleRuntime and
RuleAdministrator APIs. The RuleAdministrator provides an administration
API for the management of RuleExecutionSet objects, making it possible to
register a RuleExecutionSet that can then be retrieved via the
RuleRuntime.

First, you need to create a RuleExecutionSet before it can be
registered; RuleAdministrator provides factory methods to return an empty
LocalRuleExecutionSetProvider or RuleExecutionSetProvider. The
LocalRuleExecutionSetProvider should be used to load a RuleExecutionSets
from local sources that are not serializable, like Streams. The
RuleExecutionSetProvider can be used to load RuleExecutionSets from
serializable sources, like DOM Elements or Packages. Both the
"ruleAdministrator.getLocalRuleExecutionSetProvider( null );" and the
"ruleAdministrator.getRuleExecutionSetProvider( null );" take null as a
parameter, as the properties map for these methods is not currently
used.

Example 7.2. Registering a LocalRuleExecutionSet with the RuleAdministrator
API

"ruleExecutionSetProvider.createRuleExecutionSet( reader, null )" in
the above example takes a null parameter for the properties map; however
it can actually be used to provide configuration for the incoming source.
When null is passed the default is used to load the input as a drl.
Allowed keys for a map are "source" and "dsl". The key "source" takes "drl" or
"xml" as its value; you set "source" to "drl" to load a DRL, or to "xml" to
load an XML source; "xml" will ignore any "dsl" key/value settings. The
"dsl" key can take a Reader or a String (the contents of the dsl) as a
value.

Example 7.3. Specifying a DSL when registering a LocalRuleExecutionSet

When registering a RuleExecutionSet you must specify the name to be
used for its retrieval. There is also a field to pass properties, which is
currently unused - so just pass null.

Example 7.4. Register the RuleExecutionSet

//Register the RuleExecutionSet with the RuleAdministratorString uri = ruleExecutionSet.getName();ruleAdministrator.registerRuleExecutionSet(uri, ruleExecutionSet,null);

7.2.2. Using Stateful and Stateless RuleSessions

The Runtime, obtained from the RuleServiceProvider, is used to
create stateful and stateless rule engine sessions.

Example 7.5. Getting the RuleRuntime

RuleRuntime ruleRuntime = ruleServiceProvider.getRuleRuntime();

To create a rule session you must use one of the two RuleRuntime
public constants. These are "RuleRuntime.STATEFUL_SESSION_TYPE" and
"RuleRuntime.STATELESS_SESSION_TYPE", accompanying the URI to the
RuleExecutionSet you wish to instantiate a RuleSession for. The properties
map can be null, or it can be used to specify globals, as shown in the
next section. The createRuleSession(...) method returns a RuleSession
instance which must then be cast to StatefulRuleSession or
StatelessRuleSession.

7.2.2.1. Globals

It is possible to support globals with JSR94, in a manner that is
not portable, by using the properties map passed to the RuleSession factory
method. Globals must be defined in the DRL or XML file first, otherwise
an exception will be thrown. The key represents the identifier declared
in the DRL or XML, and the value is the instance you wish to be used in
the execution. In the following example the results are collected in a
java.util.List which is used as global:

The Eclipse based IDE provides developers (and very technical users)
with an environment to edit and test rules in various formats, and integrate
it deeply with their applications. In cases where you prefer business rules
and web tooling, you will want to look at the BRMS (but using the BRMS and
the IDE together is not uncommon).

The Drools IDE is delivered as an Eclipse plug-in, which allows you to
author and manage rules from within Eclipse, as well as integrate rules with
your application. This is an optional tool, and not all components are
required to be used, you can use what components are relevant to you. The
Drools IDE is also a part of the Red Hat Developer Studio (formerly known as
JBoss IDE).

This guide will cover some of the features of JBoss Drools, in as far
as the IDE touches on them (it is assumed that the reader has some
familiarity with rule engines, and Drools in particular. It is important to
note that none of the underlying features of the rule engine are dependent
on Eclipse, and integrators are free to use their tools of choice, as always
! Plenty of people use IntelliJ with rules, for instance.

Note

You can get the plug-in either as a zip to download, or from an
update site. Refer to the chapter on installation.

Figure 8.1. Overview

8.1. Features Outline

The rules IDE has the following features

Textual/graphical rule editor

An editor that is aware of DRL syntax, and provides content
assistance (including an outline view)

An editor that is aware of DSL (domain specific langauge)
extensions, and provides content assistance.

RuleFlow graphical editor

You can edit visual graphs which represent a process (a rule
flow). The RuleFlow can then be applied to your rule package to have
imperative control.

Wizards for fast creation of

a "rules" project

a rule resource, either as a DRL file or a "guided rule
editor" file (.brl)

a Domain Specific language

a decision table

a ruleflow

A domain specific language editor

Create and manage mappings from your user's language to the
rule language

Rule validation

As rules are entered, the rule is "built" in the background
and errors reported via the problem view where possible

The above features make use of Eclipse infrastructure and features,
with all of the power of Eclipse being available.

8.2. Drools Runtimes

A Drools runtime is a collection of jar files 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.

8.2.1. Defining a Drools Runtime

To define one or more Drools runtimes using the Eclipse
preferences view you open up your Preferences, by selecting the
"Preferences" menu item in the menu "Window". A "Preferences" dialog
should show all your settings. 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 look like the figure
below.

To define a new Drools runtime, click on the add button. A dialog
such as the one shown below should pop up, asking for the name of 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 jar files 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 two runtimes have been
defined: a Drools 5.1.1 runtime and a Drools 5.2.0.M2 runtime. The
Drools 5.1.1 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.

8.2.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 action "Convert to Drools Project" 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 and selecting the Drools category, as
shown below. Mark 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.

8.3. Creating a Rule Project

The aim of the new project wizard is to set up an executable
scaffold project to start using rules immediately. This will set up a
basic structure, the classpath, sample rules and a test case to get you
started.

Figure 8.2. New rule project scaffolding

When you choose to create a new "rule project" you will get a choice
to add some default artifacts to it, like rules, decision tables,
ruleflows, etc. These can serve as a starting point, and will give you
something executable almost immediately, which you can then modify and
mould to your needs. The simplest case (a hello world rule) is shown
below. Feel free to experiment with the plug-in at this point.

Figure 8.3. New rule project result

The newly created project contains an example rule file (Sample.drl)
in the src/rules directory and an example Java file (DroolsTest.java) that
can be used to execute the rules in a Drools engine. You'll find this in
the folder src/java, in the com.sample package. All the other jars that
are necessary during execution are also added to the classpath in a custom
classpath container called Drools Library. Rules do not have to be kept in
"Java" projects at all, this is just a convenience for people who are
already using Eclipse as their Java IDE.

Important note: The Drools plug-in adds a "Drools Builder"
capability to your Eclipse instance. This means you can enable a builder
on any project that will build and validate your rules when resources
change. This happens automatically with the Rule Project Wizard, but you
can also enable it manually on any project. One downside of this is that
if you have rule files with a large number of rules (more than 500 rules
per file), it means that the background builder may be doing a lot of work
to build the rules on each change. An option here is to turn off the
builder, or put the large rules into .rule files, where you can still use
the rule editor, but it won't build them in the background. To fully
validate the rules you will need to run them in a unit test of
course.

8.4. Creating a New Rule and Wizards

You can create a rule simple as an empty text ".drl" file, or use
the wizard to do so. The wizard menu can be invoked with Control+N, or by
choosing it from the toolbar, where there is a menu with the JBoss Drools
icon.

Figure 8.4. The wizard menu

The wizard will ask for some basic options for generating a rule
resource. These are just hints - you can change your mind later. For
storing rule files you would typically create a directory src/rules and
create suitably named subdirectories. The package name is mandatory, and
is similar to a package name in Java; i.e., it establishes a namespace for
grouping related rules.

Figure 8.5. New rule wizard

The result of this wizard is a rule skeleton, for you to expand. As
with all wizards, they are an optional help - you don't have to use them
if you don't want to.

8.5. Textual Rule Editor

The rule editor is where rule managers and developers will be
spending most of their time. The rule editor follows the pattern of a
normal text editor in Eclipse, with all the customary features of a text
editor. On top of this, the rule editor provides pop-up content
assistance. You invoke pop-up content assistance the "normal" way by
pressing Control+Space.

Figure 8.6. The rule editor in action

The rule editor works on files that have a .drl (or .rule)
extension. Usually these contain related rules, but it would also be
possible to have rules in individual files, grouped by being in the same
package "namespace", if you so prefer. These DRL files are plain text
files.

You can see from the example above that the rule group is using a
domain specific language. Note the expander keyword, which tells the rule
compiler to look for a dsl file of that name, to resolve the rule
language. Even with the domain specific language (DSL) the rules are still
stored as plain text as you see it onscreen, which allows simpler
management of rules and versions, e.g., comparing versions of
rules.

The editor has an outline view that is kept in sync with the
structure of the rules; it is updated on save. This provides a quick way
of navigating around rules by name, even in a file which may have hundreds
of rules. The items are sorted alphabetically by default.

Figure 8.7. The rule outline view

8.6. Drools Views

When debugging an application using a Drools engine, these views can
be used to check the state of the Drools engine itself: the Working Memory
View, the Agenda View, and the Global Data View. To be able to use these
views, create breakpoints in your code invoking the working memory. For
example, the line where you call workingMemory.fireAllRules() is a good
candidate. If the debugger halts at that joinpoint, you should select the
working memory variable in the debug variables view. The available views
can then be used to show the details of the selected working
memory:

The Working Memory View shows all elements of the Drools working
memory.

The Agenda View shows all elements on the agenda. For each rule
on the agenda, the rule name and bound variables are shown.

The Global Data View shows all global data currently defined in
the Drools working memory.

The Audit view can be used to display audit logs containing events
that were logged during the execution of a rules engine, in tree
form.

8.6.1. The Working Memory View

The Working Memory View shows all elements in the working memory
of the Drools engine.

An action is added to the right of the view, to customize what is
shown:

The Show Logical Structure toggles showing the logical
structure of the elements in the working memory, or all their
details. Logical structures allow for visualizing sets of elements
in a more obvious way.

8.6.2. The Agenda View

The Agenda View shows all elements on the agenda. For each rule on
the agenda, the rule name and bound variables are shown.

An action is added to the right of the view, to customize what is
shown:

The Show Logical Structure toggles showing the logical
structure of the agenda item, or all their details. Logical
structures allow for example visualizing sets of elements in a more
obvious way. The logical structure of AgendaItems shows the rule
that is represented by the AgendaItem, and the values of all the
parameters used in the rule.

8.6.3. The Global Data View

The Global Data View shows all global data currently defined in
the Drools engine.

An action is added to the right of the view, to customize what is
shown:

The Show Logical Structure toggles showing the logical
structure of the elements in the working memory, or all their
details. Logical structures allow for example visualizing sets of
elements in a more obvious way.

8.6.4. The Audit View

The audit view visualizes an audit log, that is optionally created
when executing the rules engine. To create an audit log, use the
following code:

WorkingMemory workingMemory = ruleBase.newWorkingMemory();//Create a newWorkingMemoryLogger, that logs to file.WorkingMemoryFileLogger logger =newWorkingMemoryFileLogger(workingMemory);//An event.log file is created in the subdirectory log (which must exist)// of the working directory.logger.setFileName("log/event");workingMemory.assertObject(...);workingMemory.fireAllRules();// stop logginglogger.writeToDisk();

Open the log by clicking the Open Log action, the first icon in
the Audit View, and select the file. The Audit View now shows all events
that where logged during the executing of the rules. There are different
types of events, each with a different icon:

Object inserted, a green square:

Object updated, a yellow square:

Object removed, a red square:

Activation created, a right arrow:

Activation cancelled, a left arrow:

Activation executed, a blue diamond:

Ruleflow start or end, the "process" icon:

Ruleflow-group activation or deactivation, the "activity"
icon:

Rule package addition or removal, the Drools icon:

Rule addition or removal, the Drools icon:

All these events show extra information concerning the event, like
the id and toString representation of the object in case of working
memory events (insert, modify and retract), the name of the rule and all
the variables bound in the activation in case of an activation event
(created, cancelled or executed). If an event occurs when executing an
activation, it is shown as a child of the activation's execution event.
For some events, you can retrieve the "cause":

The cause of an object modified or retracted event is the last
object event for that object. This is either the object asserted
event, or the last object modified event for that object.

The cause of an activation cancelled or executed event is the
corresponding activation created event.

When selecting an event, the cause of that event is shown in green
in the audit view (if visible of course). You can also right click the
action and select the "Show Cause" menu item. This will scroll you to
the cause of the selected event.

8.7. Domain Specific Languages

Domain Specific Languages (DSL) enable you to create a language that
allows your rules to look like - rules! Most often the domain specific
language reads like natural language. Typically you would look at how a
business analyst would describe the rule, in their own words, and then map
this to your object model, via rule constructs. A side benefit of this is
that it can provide an insulation layer between your domain objects and
the rules themselves (as we know you like to refactor). A domain specific
language will grow as the rules grow, and works best when there are common
terms used over an over, with different parameters.

To aid with this, the rule workbench provides an editor for Domain
Specific Languages. They are stored in a plain text format, so you can use
any editor of your choice; this format is simply a slightly enhanced
version of the "Properties" file format. The editor will be invoked on any
files with a .dsl extension. There is also a wizard to create a sample
DSL.

8.7.1. Editing languages

Figure 8.8. The Domain Specific Language editor

The DSL editor provides a tabular view of the mapping of Language
to Rule Expressions. The Language Expression is what is used in the
rules. This also feeds the content assistance for the rule editor, so
that it can suggest Language Expressions from the DSL configuration.
(The rule editor loads the DSL configuration when the rule resource is
loaded for editing.) The Rule language mapping defines the "code" for
the rules into which the language expression will be compiled by the
rule engine compiler. The form of this Rule language expression depends
on it being intended for the condition or the action part of a rule.
(For the RHS it may be a snippet of Java, for instance). The "scope"
item indicates where the expression belongs, "when" indicating the LHS,
"then" the RHS, and "*" meaning anywhere. It's also possible to create
aliases for keywords.

By selecting a mapping item (a row in the table) you can see the
expression and mapping in the text fields below the table. Double
clicking or pressing the edit button will open the edit dialog. Other
buttons let you remove and add mappings. Don't remove mappings while
they are still in use.

Figure 8.9. Language Mapping editor dialog

Here is a short description of the DSL translation process. The
parser reads the rule text in a DSL, line by line, and tries to match
some "Language Expression", depending on the scope. After a match, the
values that correspond to a placeholder between curly braces (e.g.,
{age}) are extracted from the rule source. The placeholders in the
corresponding "Rule Expression" are replaced by their corresponding
value. In the example above, the natural language expression maps to two
constraints on a fact of type Person, based on the fields age and
location, and the {age} and {location} values are extracted from the
original rule text.

If you do not wish to use a language mapping for a particular rule
in a drl, prefix the expression with > and the compiler will not try
to translate it according to the language definition. Also note that
Domain Specific Languages are optional. When the rule is compiled, the
.dsl file will also need to be available.

8.8. The Rete View

The Rete Tree View shows you the current Rete Network for your DRL
file. You display it by clicking on the tab "Rete Tree" at the bottom of
the DRL Editor window. With the Rete Network visualization being open, you
can use drag-and-drop on individual nodes to arrange optimal network
overview. You may also select multiple nodes by dragging a rectangle over
them; then the entire group can be moved around. The Eclips toolbar icons
for zooming in and out can be used in the customary manner.

In the current release there is no export function to creates a gif
or jpeg file. Meanwhile, please use ctrl + alt + print to create a copy of
your current Eclipse window, and cut it off.

The Rete View is an advanced feature which takes full advantage of
the Eclipse Graphical Editing Framework (GEF).

The Rete view works only in Drools Rule Projects, where the Drools
Builder is set in the project´s properties.

If you are using Drools in another type of project where you are not
having a Drools Rule Project with the appropriate Drools Builder, you can
use a workaround: Set up a little Drools Rule Project next to it, putting
needed libraries into it, and the DRLs you want to inspect with the Rete
View. Just click on the right tab below in the DRL Editor, followed by a
click on "Generate Rete View".

8.9. Large DRL Files

Depending on the JDK you use, it may be necessary to increase the
permanent generation max size. Both the SUN and the IBM JDK have a
permanent generation, whereas BEA JRockit does not.

To increase the permanent generation, start Eclipse with
-XX:MaxPermSize=###m

Example: c:\Eclipse\Eclipse.exe -XX:MaxPermSize=128m

Rulesets of 4,000 rules or greater should set the permanent
generation to at least 128Mb.

Note

This may also apply to compiling large numbers of rules in
general, as there is generally one or more classes per rule.

As an alternative to the above, you may put rules in a file with the
".rule" extension, and the background builder will not try to compile them
with each change, which may provide performance improvements if your IDE
becomes sluggish with very large numbers of rules.

8.10. Debugging Rules

Figure 8.10. Debugging

You can debug rules during the execution of your Drools application.
You can add breakpoints in the consequences of your rules, and whenever
such a breakpoint is encountered during the execution of the rules,
execution is halted. You can then inspect the variables known at that
point and use any of the default debugging actions to decide what should
happen next: step over, continue, etc. You can also use the debug views to
inspect the content of the working memory and the Agenda.

8.10.1. Creating Breakpoints

You can add and remove rule breakpoints in DRL files in two ways,
similar to adding breakpoints to Java files:

Double-click the ruler of the DRL editor at the line where you
want to add a breakpoint. Note that rule breakpoints can only be
created in the consequence of a rule. Double-clicking on a line
where no breakpoint is allowed will do nothing. A breakpoint can be
removed by double-clicking the ruler once more.

If you right-click the ruler, a popup menu will show up,
containing the "Toggle breakpoint" action. Note that rule
breakpoints can only be created in the consequence of a rule. The
action is automatically disabled if no rule breakpoint is allowed at
that line. Clicking the action will add a breakpoint at the selected
line, or remove it if there was one already.

The Debug Perspective contains a Breakpoints view which can be
used to see all defined breakpoints, get their properties,
enable/disable or remove them, etc.

8.10.2. Debugging Rules

Drools breakpoints are only enabled if you debug your application
as a Drools Application. You can do this like this:

Figure 8.11. Debug as Drools Application

Select the main class of your application. Right click it and
select the "Debug As >" sub-menu and select Drools Application.
Alternatively, you can also select the "Debug ..." menu item to open
a new dialog for creating, managing and running debug configurations
(see the screenshot below).

Select the "Drools Application" item in the left tree and
click the "New launch configuration" button (leftmost icon in the
toolbar above the tree). This will create a new configuration with
some of the properties (like project and main class)already filled
in, based on the main class you selected in the beginning. All
properties shown here are the same as for any standard Java
program.

Change the name of your debug configuration to something
meaningful. You can just accept the defaults for all other
properties. For more information about these properties, please
check the Eclipse JDT documentation.

Click the "Debug" button on the bottom to start debugging your
application. You only have to define your debug configuration once.
The next time you run your Drools application, you don't have to
create a new one but select the previously defined one in the tree
on the left, as a sub-element of the "Drools Application" tree node,
and then click the Debug button. The Eclipse toolbar also contains
shortcut buttons to quickly re-execute one of your previous
configurations (at least when one of the Java, Java Debug, or Drools
perspectives has been selected).

Figure 8.12. Debug as Drools Application Configuration

After clicking the "Debug" button, the application starts
executing and will halt if any breakpoint is encountered. This can be a
Drools rule breakpoint, or any other standard Java breakpoint. Whenever
a Drools rule breakpoint is encountered, the corresponding DRL file is
opened and the active line is highlighted. The Variables view also
contains all rule parameters and their value. You can then use the
default Java debug actions to decide what to do next: resume, terminate,
step over, etc. The debug view can also be used to inspect the contents
of the Working Memory and the Agenda at that time as well. You don't
have to select a Working Memory now, as the current executing working
memory is automatically shown.

9.1. Getting the Examples

Make sure the Drools Eclipse plugin is installed, which
needs the Graphical Editing Framework (GEF) dependency installed
first. Then download and extract the
drools-examples zip file, which includes an already created Eclipse
project. Import that project into a new Eclipse workspace. The rules
all have example classes that execute the rules. If you want to try
the examples in another project (or another IDE) then you will need
to set up the dependencies by hand, of course. Many, but not all of the
examples are documented below, enjoy!

9.2. Hello World

The "Hello World" example shows a simple example of rules usage, and
both the MVEL and Java dialects.

This example demonstrates how to build Knowledge Bases and Sessions.
Also, audit logging and debug outputs are shown, which is ommitted
from other examples as it's all very similar. A KnowledgeBuilder
is used to turn a DRL source file into Package objects which
the Knowledge Base can consume. The add method takes a Resource
interface and a Resource Type as parameters. The Resource can be
used to retrieve a DRL source file from various locations; in this case the
DRL file is being retrieved from the classpath using a
ResourceFactory, but it could come from a disk file or a URL.
Here, we only add a single DRL source file, but multiple DRL files can be
added. Also, DRL files with different namespaces can be added, where
the Knowledge Builder creates a package for each namespace. Multiple
packages of different namespaces can be added to the same Knowledge Base.
When all the DRL files have been added, we should check the builder for
errors. While the Knowledge Base will validate the package, it will only
have access to the error information as a String, so if you wish to debug
the error information you should do it on the KnowledgeBuilder
instance. Once you know the builder is error free, get the
Package collection, instantiate a KnowledgeBase
from the KnowledgeBaseFactory and add the package
collection.

Example 9.1. HelloWorld: Creating the KnowledgeBase and Session

finalKnowledgeBuilder kbuilder =KnowledgeBuilderFactory.newKnowledgeBuilder();//this will parse and compile in one stepkbuilder.add(ResourceFactory.newClassPathResource("HelloWorld.drl",HelloWorldExample.class),ResourceType.DRL);//Check the builder for errorsif(kbuilder.hasErrors()){System.out.println(kbuilder.getErrors().toString());thrownewRuntimeException("Unable to compile \"HelloWorld.drl\".");}// get the compiled packages (which are serializable)finalCollection<KnowledgePackage> pkgs = kbuilder.getKnowledgePackages();// add the packages to a knowledgebase (deploy the knowledge packages).finalKnowledgeBase kbase =KnowledgeBaseFactory.newKnowledgeBase();kbase.addKnowledgePackages(pkgs);finalStatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();

Drools has an event model that exposes much of what's happening
internally. Two default debug listeners are supplied,
DebugAgendaEventListener and
DebugWorkingMemoryEventListener which print out
debug event information to the System.err stream displayed
in the Console window. Adding listeners to a
Session is trivial, as shown below. The KnowledgeRuntimeLogger
provides execution auditing, the result of which can be viewed in a
graphical viewer. The logger is actually a specialised implementation
built on the Agenda and Working Memory listeners. When the engine has
finished executing, logger.close() must be called.

Most of the examples use the Audit logging features of Drools to
record execution flow for later inspection.

A single Message object is created with the
message text "Hello World" and the status HELLO and then
inserted into the engine, at which point fireAllRules()
is executed. Remember that all the network evaluation is done
during the insert time, so that by the time the program execution reaches the
fireAllRules() method call the engine already knows which rules
are fully matches and able to fire.

Open the class org.drools.examples.helloworld.HelloWorldExample in your
Eclipse IDE

Right-click the class and select "Run as..." and then "Java
application"

If we put a breakpoint on the fireAllRules() method
and select the ksession variable, we can see that the
"Hello World" rule is already activated and on the Agenda, confirming
that all the pattern matching work was already done during the insert.

Figure 9.1. Hello World: fireAllRules Agenda View

The may application print outs go to to System.out while the debug
listener print outs go to System.err.

The LHS (after when) section of the rule states that it will be
activated for each Message object inserted into the Working
Memory whose status is Message.HELLO. Besides that, two
variable bindings are created: the variable message is bound
to the message attribute and the variable m
is bound to the matched Message object itself.

The RHS (after then) or consequence part of the rule is
written using the MVEL expression language, as declared by
the rule's attribute dialect. After printing the content of
the bound variable message to System.out,
the rule changes the values of the message and
status attributes of the Message object
bound to m. This is done MVEL's modify statement,
which allows you to apply a block of assignments in one statement, with the
engine being automatically notified of the changes at the end of the
block.

We can set a breakpoint into the DRL, on the modify
call, and inspect the Agenda view again during the execution of the
rule's consequence. This time we start the execution via "Debug As"
and "Drools application" and not by running a "Java application":

Open the class org.drools.examples.HelloWorld in your
Eclipse IDE.

Right-click the class and select "Debug as..." and then "Drools
application".

Now we can see that the other rule "Good Bye", which
uses the Java dialect, is activated and placed on the Agenda.

Figure 9.2. Hello World: rule "Hello World" Agenda View

The "Good Bye" rule, which specifies the "java" dialect, is similar
to the "Hello World" rule except that it matches Message
objects whose status is Message.GOODBYE.

Remember the Java code where we used the
KnowledgeRuntimeLoggerFactory method newFileLogger
to create a KnowledgeRuntimeLogger and called
logger.close() at the end. This created an audit log file that
can be shown in the Audit view. We use the Audit view in many of the
examples to demostrate the example execution flow. In the view screen shot
below we can see that the object is inserted, which creates an activation
for the "Hello World" rule; the activation is then executed which updates
the Message object causing the "Good Bye" rule to
activate; finally the "Good Bye" rule also executes. Selecting an event in
the Audit view highlights the origin event in green; therefore the
"Activation created" event is highlighted in green as the origin of the
"Activation executed" event.

Figure 9.3. Hello World: Audit View

9.3. State Example

This example is implemented in three different versions to
demonstrate different ways of implementing the same basic behavior:
forward chaining, i.e., the ability the engine has to evaluate,
activate and fire rules in sequence, based on changes on the facts
in the Working Memory.

Ignoring the PropertyChangeSupport, which will
be explained later, we see the creation of four State
objects named A, B, C and D. Initially their states are set to
NOTRUN, which is default for the used constructor.
Each instance is asserted in turn into the Session and then
fireAllRules() is called.

Open the class org.drools.examples.state.StateExampleUsingSalience in your Eclipse IDE.

Right-click the class and select "Run as..." and then
"Java application"

You will see the following output in the Eclipse console
window:

Example 9.11. Salience State: Console Output

A finished
B finished
C finished
D finished

There are four rules in total. First, the Bootstrap
rule fires, setting A to state FINISHED, which then
causes B to change its state to FINISHED. C and D are
both dependent on B, causing a conflict which is resolved by the
salience values. Let's look at the way this was executed.

The best way to understand what is happening is to use the
Audit Logging feature to graphically see the results of each
operation. To view the Audit log generated by a run of this
example:

If the Audit View is not visible, click on "Window" and
then select "Show View", then "Other..." and "Drools" and
finally "Audit View".

In the "Audit View" click the "Open Log" button and select
the file "<drools-examples-dir>/log/state.log".

After that, the "Audit view" will look like the following
screenshot:

Figure 9.4. Salience State Example Audit View

Reading the log in the "Audit View", top to bottom, we see every
action and the corresponding changes in the Working Memory. This way
we observe that the assertion of the State object A in the state
NOTRUN activates the Bootstrap rule, while
the assertions of the other State objects have no
immediate effect.

The execution of rule "A to B" changes the state of B to
FINISHED, which activates both, rules "B to C" and
"B to D", placing their Activations onto the Agenda. From this moment
on, both rules may fire and, therefore, they are said to be
"in conflict". The conflict resolution strategy allows the engine's
Agenda to decide which rule to fire. As rule "B to C" has the
higher salience value (10 versus
the default salience value of 0), it fires first, modifying object C
to state FINISHED. The Audit view shown above reflects
the modification of the State object in the rule "A to B",
which results in two activations being in conflict. The Agenda view
can also be used to investigate the state of the Agenda, with debug
points being placed in the rules themselves and the Agenda view opened.
The screen shot below shows the breakpoint in the rule "A to B" and
the state of the Agenda with the two conflicting rules.

Another notable concept in this example is the use of
dynamic facts, based on
PropertyChangeListener objects. As described in the
documentation, in order for the engine to see and react to changes of
fact properties, the application must tell the engine that changes
occurred. This can be done explicitly in the rules by using the
modify statement, or implicitly by letting the engine know
that the facts implement PropertyChangeSupport as defined
by the JavaBeans specification. This example
demonstrates how to use PropertyChangeSupport to avoid
the need for explicit modify statements in the rules. To
make use of this feature, ensure that your facts implement
PropertyChangeSupport, the same way the class
org.drools.example.State does, and use the following
code to insert the facts into the Working Memory:

Example 9.16. Inserting a Dynamic Fact

//By setting dynamic to TRUE,Drools will use JavaBean//PropertyChangeListeners so you don't have to call modify or update().finalboolean dynamic =true;session.insert( fact, dynamic );

When using PropertyChangeListener objects, each
setter must implement a little extra code for the notification. Here
is the setter for state in the class
org.drools.examples:

There are two other classes in this example:
StateExampleUsingAgendGroup and
StateExampleWithDynamicRules. Both execute from A to B
to C to D, as just shown. The StateExampleUsingAgendGroup
uses agenda-groups to control the rule conflict and which one fires
first. StateExampleWithDynamicRules shows how an
additional rule can be added to an already running Working Memory
with all the existing data applying to it at runtime.

Agenda groups are a way to partition the Agenda into groups
and to control which groups can execute. By default, all rules are
in the agenda group "MAIN". The "agenda-group" attribute lets
you specify a different agenda group for the rule. Initially,
a Working Memory has its focus on the Agenda group "MAIN". A group's
rules will only fire when the group receives the focus. This can be
achieved either ny using the method by setFocus() or the
rule attribute auto-focus. "auto-focus" means that the rule
automatically sets the focus to its agenda group when the rule is
matched and activated. It is this "auto-focus" that enables rule
"B to C" to fire before "B to D".

The single fact class Fibonacci is used in this
example. It has two fields, sequence and value. The sequence field
is used to indicate the position of the object in the Fibonacci
number sequence. The value field shows the value of that
Fibonacci object for that sequence position, using -1 to indicate
a value that still needs to be computed.

To kick this off from Java we only insert a single Fibonacci
object, with a sequence field of 50. A recursive rule is then used
to insert the other 49 Fibonacci objects. This example
doesn't use
PropertyChangeSupport. It uses the MVEL dialect, which
means we can use the modify keyword, which allows a block
setter action which also notifies the engine of changes.

Example 9.24. Fibonacci Example: Execution

ksession.insert(newFibonacci(50));ksession.fireAllRules();

The rule Recurse is very simple. It matches each asserted
Fibonacci object with a value of -1, creating and
asserting a new Fibonacci object with a sequence of
one less than the currently matched object. Each time a Fibonacci
object is added while the one with a sequence field equal to 1
does not exist, the rule re-matches and fires again. The
not conditional element is used to stop the rule's matching
once we have all 50 Fibonacci objects in memory. The rule also has a
salience value, because we need to have all 50 Fibonacci
objects asserted before we execute the Bootstrap rule.

The Audit view shows the original assertion of the
Fibonacci object with a sequence field of 50, done from
Java code. From there on, the Audit view shows the continual
recursion of the rule, where each asserted Fibonacci
object causes the Recurse rule to become activated and to fire again.

Figure 9.6. Fibonacci Example: "Recurse" Audit View 1

When a Fibonacci object with a sequence field of 2 is
asserted the "Bootstrap" rule is matched and activated along with the
"Recurse" rule. Note the multi-restriction on field
sequence, testing for equality with 1 or 2.

At this point the Agenda looks as shown below. However,
the "Bootstrap" rule does not fire because the "Recurse" rule has a higher
salience.

Figure 9.7. Fibonacci Example: "Recurse" Agenda View 1

When a Fibonacci object with a sequence of 1 is
asserted the Bootstrap rule is matched again, causing two activations
for this rule. Note that the "Recurse" rule does not match and activate
because the not conditional element stops the rule's matching
as soon as a Fibonacci object with a sequence of 1
exists.

Figure 9.8. Fibonacci Example: "Recurse" Agenda View 2

Once we have two Fibonacci objects with values
not equal to -1 the "Calculate" rule is able to match. It was
the "Bootstrap" rule that set the objects with sequence 1 and 2 to
values of 1. At this point we have 50 Fibonacci objects in the Working
Memory. Now we need to select a suitable triple to calculate each
of their values in turn. Using three Fibonacci patterns in a rule without
field constraints to confine the possible cross products would result
in 50x49x48 possible combinations, leading to about 125,000 possible rule
firings, most of them incorrect. The "Calculate" rule uses field
constraints to correctly constraint the thee Fibonacci patterns in the
correct order; this
technique is called cross product matching. The
first pattern finds any Fibonacci with a value != -1 and binds both
the pattern and the field. The second Fibonacci does this, too, but
it adds an additional field constraint to ensure that its sequence is
greater by one than the Fibonacci bound to f1. When this
rule fires for the first time, we know that only sequences 1 and 2
have values of 1, and the two constraints ensure that f1
references sequence 1 and f2 references sequence 2. The
final pattern finds the Fibonacci with a value equal to -1 and with a
sequence one greater than f2. At this point, we have
three Fibonacci objects correctly selected from the
available cross products, and we can calculate the value for the
third Fibonacci object that's bound to f3.

The modify statement updated the value of the
Fibonacci object bound to f3. This means
we now have another new Fibonacci object with a value not equal to -1,
which allows the "Calculate" rule to rematch and calculate the next
Fibonacci number. The Audit view below shows how the firing of the
last "Bootstrap" modifies the Fibonacci object,
enabling the "Calculate" rule to match, which then modifies
another Fibonacci object allowing the "Calculate" rule to match again.
This continues till the value is set for all Fibonacci
objects.

This tutorial demonstrates the process of developing a
complete personal banking application to handle credits and debits on
multiple accounts. It uses a set of design patterns that have
been created for the process.

The class RuleRunner is a simple harness to execute
one or more DRL files against a set of data. It compiles the Packages
and creates the Knowledge Base for each execution, allowing us to
easily execute each scenario and inspect the outputs. In reality this
is not a good solution for a production system, where the Knowledge Base
should be built just once and cached, but for the purposes of this
tutorial it shall suffice.

This doesn’t use any specific facts but instead asserts a set
of java.lang.Integer objects. This is not considered
"best practice" as a number is not a useful fact, but we use it here
to demonstrate basic techniques before more complexity is added.

Once again, this rule does nothing special. It identifies any
facts that are Number objects and prints out the values.
Notice the use of the abstract class Number: we inserted
Integer objects but we now look for any kind of number.
The pattern matching engine is able to match interfaces and
superclasses of asserted objects.

The output shows the DRL being loaded, the facts inserted and
then the matched and fired rules. We can see that each inserted number
is matched and fired and thus printed.

Example 9.34. Banking Tutorial: Output of Example2.java

Loading file: Example2.drl
Inserting fact: 3
Inserting fact: 1
Inserting fact: 4
Inserting fact: 1
Inserting fact: 5
Number found with value: 5
Number found with value: 1
Number found with value: 4
Number found with value: 1
Number found with value: 3

There are certainly many better ways to sort numbers than using
rules, but since we will need to apply some cashflows in date order
when we start looking at banking rules we'll develop simple rule
based sorting technique.

The first line of the rule identifies a Number and
extracts the value. The second line ensures that there does not exist
a smaller number than the one found by the first pattern. We might
expect to match only one number - the smallest in the set. However,
the retraction of the number after it has been printed means that the
smallest number has been removed, revealing the next smallest number,
and so on.

The resulting output shows that the numbers are now
sorted numerically.

Example 9.37. Banking Tutorial: Output of Example3.java

Loading file: Example3.drl
Inserting fact: 3
Inserting fact: 1
Inserting fact: 4
Inserting fact: 1
Inserting fact: 5
Number found with value: 1
Number found with value: 1
Number found with value: 3
Number found with value: 4
Number found with value: 5

We are ready to start moving towards our personal accounting
rules. The first step is to create a Cashflow object.

Class Cashflow has two simple attributes, a date
and an amount. (Note that using the type double for
monetary units is generally not a good idea
because floating point numbers cannot represent most numbers accurately.)
There is also an overloaded constructor to set the values, and a
method toString to print a cashflow. The Java code of
Example4.java inserts five Cashflow objects,
with varying dates and amounts.

Here, we identify a Cashflow and extract the date
and the amount. In the second line of the rule we ensure that there
is no Cashflow with an earlier date than the one found. In the
consequence, we print the Cashflow that satisfies the
rule and then retract it, making way for the next earliest
Cashflow. So, the output we generate is:

Next, we extend our Cashflow, resulting in a
TypedCashflow which can be a credit or a debit operation.
(Normally, we would just add this to the Cashflow type, but
we use extension to keep the previous version of the class intact.)