JBoss.orgCommunity Documentation

Chapter 7. Running

7.1. KieRuntime
7.1.1. EntryPoint
7.1.2. RuleRuntime
7.1.3. StatefulRuleSession
7.2. Agenda
7.2.1. Conflict Resolution
7.2.2. AgendaGroup
7.2.3. ActivationGroup
7.2.4. RuleFlowGroup
7.3. Event Model
7.4. StatelessKieSession
7.4.1. Sequential Mode
7.5. Rule Execution Modes
7.5.1. Passive Mode
7.5.2. Active Mode
7.6. Propagation modes
7.7. Commands and the CommandExecutor

Ths sections extends the KIE Running section, which should be read first, with specifics for the Drools runtime.

The EntryPoint provides the methods around inserting, updating and deleting 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. The use of multiple entry points is more common in event processing use cases, but they can be used by pure rule applications as well.

The KieRuntime 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 KieRuntime 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 KieRuntime: EntryPoint, WorkingMemory and the KieRuntime itself.

In order for a fact to be evaluated against the rules in a KieBase, it has to be inserted into the session. This is done by calling the method insert(yourObject). When a fact is inserted into the session, some of its properties might be immediately evaluated (eager evaluation) and some might be deferred for later evaluation (lazy evaluation). The exact behaviour depends on the rules engine algorithm being used.

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 delete or modify an object.

Cheese stilton = new Cheese("stilton");
FactHandle stiltonHandle = ksession.insert( stilton );      

As mentioned in the KieBase section, a Working Memory may operate in two assertion modes: either equality or identity. Identity is 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 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 object.

Equality means that the Working Memory uses a HashMap to store all asserted objects. An object instance assertion will only return a new FactHandle if the inserted object is not equal (according to its equal()/hashcode() methods) to an already existing fact.

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

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 a Match is created, referencing the rule and the matched facts, and placed onto the Agenda. The Agenda controls the execution order of these Matches using a Conflict Resolution strategy.

The engine cycles repeatedly through two phases:

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.

Agenda groups are a way to partition rules (matches, actually) on the agenda. At any one time, only one group has "focus" which means that matches 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();

The clear() method can be used to cancel all the activations generated by the rules belonging to a given Agenda Group before one has had a chance to fire.

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

Note that, due to the lazy nature of the phreak algorithm used by Drools, the activations are by default materialized only at firing time, but it is possible to anticipate the evaluation and then the activation of a given rule at the moment when a fact is inserted into the session by annotating it with @Propagation(IMMEDIATE) as explained in the Propagation modes section.

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 WorkingMemoryEventManager allows for listeners to be added and removed, so that events for the working memory and the agenda can be listened to.

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

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

The events currently supported are:

  • MatchCreatedEvent

  • MatchCancelledEvent

  • BeforeMatchFiredEvent

  • AfterMatchFiredEvent

  • AgendaGroupPushedEvent

  • AgendaGroupPoppedEvent

  • ObjectInsertEvent

  • ObjectDeletedEvent

  • ObjectUpdatedEvent

  • ProcessCompletedEvent

  • ProcessNodeLeftEvent

  • ProcessNodeTriggeredEvent

  • ProcessStartEvent

The StatelessKieSession wraps the KieSession, 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 KieSession, add all the user data and execute user commands, call fireAllRules(), and then call dispose(). While the main way to work with this class is via the BatchExecution (a subinterface of Command) as supported by the CommandExecutor interface, two convenience methods are provided for when simple object insertion is all that's required. The CommandExecutor and BatchExecution are talked about in detail in their own section.

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 this was done as a single Command it would be as follows:

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

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

StatelessKieSession supports globals, scoped in a number of ways. 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 CommandExecutor interface also offers the ability to export data via "out" parameters. Inserted facts, globals and query results can all be returned.

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.

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 elements for the number of rules. The sequence number of the RuleTerminalNode indicates the element within the elements where to place the Match. Once all Command objects have finished we can iterate our elements, checking each element in turn, and firing the Matches if they exist. To improve performance, we remember the first and the last populated cell in the elements. 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 deletion; here, as we know there will be no object deletions, 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".

Drools provides two modes for rule execution - passive and active.

As a general guideline, Passive Mode is most suitable for Rule Engine applications which need to explicitly control when the engine shall evaluate and fire the rules, or for CEP applications making use of the Pseudo Clock. Active Mode is most effective for Rule Engine applications which delegate control of when rules are evaluated and fired to the engine, or for typical CEP application making use of the Real Time Clock.

Drools offers a fireUntilHalt() method, that starts the engine in Active Mode, which is asynchronous in behavior, where rules will be continually evaluated and fired, until a halt() call is made.

This is specially useful for CEP scenarios that require what is commonly known as "active queries".

Please note calling fireUntilHalt() blocks the current thread, while the engine will start and continue running asynchronously until the halt() is called on the KieSession. It is suggested therefore to call fireUntilHalt() from a dedicated thread, so the current thread does not get blocked indefinitely; this also enable the current thread to call halt() at a later stage, ref. examples below.

An example outline of Drools code for a CEP application making use of Active Mode:

KieSessionConfiguration config = KieServices.Factory.get().newKieSessionConfiguration();
config.setOption( ClockTypeOption.get("realtime") );
KieSession session = kbase.newKieSession( conf, null );

new Thread( new Runnable() {
  public void run() {
} ).start();

session.insert( tick1 );

... Thread.sleep( 1000L ); ...

session.insert( tick2 );

... Thread.sleep( 1000L ); ...

session.insert( tick3 );


When in Active Mode, the Drools engine is in control of when the rule shall be evaluated and fired; therefore it is important that operations on the KieSession are performed in a thread-safe manner. Additionally, from a client-side perspective, there might be the need for more than one operations to be called on the KieSession in between rule evaluations, but for engine to consider these as an atomic operation: for example, inserting more than one Fact at a given time, but for the engine to await until all the inserts are done, before evaluating the rules again.

Drools offers a submit() method to group and perform operations on the KieSession as a thread-safe atomic action, while in Active Mode.

An example outline of Drools code to perform KieSession operations atomically when in Active Mode:

KieSession session = ...;

new Thread( new Runnable() {
  public void run() {
} ).start();

final FactHandle fh = session.insert( fact_a );

... Thread.sleep( 1000L ); ...

session.submit( new KieSession.AtomicAction() {
  public void execute( KieSession kieSession ) {
    kieSession.update( fh, fact_a );
    kieSession.insert( fact_1 );
    kieSession.insert( fact_2 );
    kieSession.insert( fact_3 );
} );

... Thread.sleep( 1000L ); ...

session.insert( fact_z );


As a reminder example, the fact handle could also be retrieved from the KieSession:

session.insert( fact_a );

... Thread.sleep( 1000L ); ...

session.submit( new KieSession.AtomicAction() {
  public void execute( KieSession kieSession ) {
    final FactHandle fh = kieSession.getFactHandle( fact_a );
    kieSession.update( fh, fact_a );
    kieSession.insert( fact_1 );
    kieSession.insert( fact_2 );
    kieSession.insert( fact_3 );
} );


The introduction of PHREAK as default algorithm for the Drools engine made the rules' evaluation lazy. This new Drools lazy behavior allowed a relevant performance boost but, in some very specific cases, breaks the semantic of a few Drools features.

More precisely in some circumstances it is necessary to propagate the insertion of new fact into th session immediately. For instance Drools allows a query to be executed in pull only (or passive) mode by prepending a '?' symbol to its invocation as in the following example:

In this case, since the query is passive, it shouldn't react to the insertion of a String matching the join condition in the query itself. In other words this sequence of commands

KieSession ksession = ...

shouldn't cause the rule R to fire because the String satisfying the query condition has been inserted after the Integer and the passive query shouldn't react to this insertion. Conversely the rule should fire if the insertion sequence is inverted because the insertion of the Integer, when the passive query can be satisfied by the presence of an already existing String, will trigger it.

Unfortunately the lazy nature of PHREAK doesn't allow the engine to make any distinction regarding the insertion sequence of the two facts, so the rule will fire in both cases. In circumstances like this it is necessary to evaluate the rule eagerly as done by the old RETEOO-based engine.

In other cases it is required that the propagation is eager, meaning that it is not immedate, but anyway has to happen before the engine/agenda starts scheduled evaluations. For instance this is necessary when a rule has the no-loop or the lock-on-active attribute and in fact when this happens this propagation mode is automatically enforced by the engine.

To cover these use cases, and in all other situations where an immediate or eager rule evaluation is required, it is possible to declaratively specify so by annotating the rule itself with @Propagation(Propagation.Type), where Propagation.Type is an enumeration with 3 possible values:

  • IMMEDIATE means that the propagation is performed immediately.

  • EAGER means that the propagation is performed lazily but eagerly evaluated before scheduled evaluations.

  • LAZY means that the propagation is totally lazy and this is default PHREAK behaviour

This means that the following drl:

will make the rule R to fire if and only if the Integer is inserted after the String, thus behaving in accordance with the semantic of the passive query.

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:

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 always returns an ExecutionResults instance, which allows access to any command results if they specify an out identifier such as the "stilton_id" above.

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

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.

Spring and Camel, covered in the integrations book, facilitate declarative services.

The CommandExecutor returns an ExecutionResults, and this is handled by the pipeline code snippet as well. A similar output for the <batch-execution> XML sample above would be:

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.

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.

The insert element features an "out-identifier" attribute, demanding that the inserted object will also be returned as part of the result payload.

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.

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.