JBoss.orgCommunity Documentation

Chapter 2. Drools Release Notes

2.1. What is New and Noteworthy in Drools 5.2.0
2.1.1. Knowledge API (renamed from Drools API)
2.1.2. Drools Expert and Fusion
2.1.3. Drools and jBPM integration
2.1.4. Merging Drools Flow into jBPM5
2.1.5. Guvnor
2.1.6. Eclipse
2.1.7. Maven artifactId changes
2.2. What is New and Noteworthy in Drools 5.1.0
2.2.1. Drools API
2.2.2. Core
2.2.3. Expert
2.2.4. Flow
2.2.5. Guvnor
2.2.6. Eclipse
2.2.7. Known Issues
2.3. What is New and Noteworthy in Drools 5.0.0
2.3.1. Drools API
2.3.2. Drools Guvnor
2.3.3. Drools Expert
2.3.4. Drools Flow
2.3.5. Drools Fusion
2.3.6. Eclipse IDE
2.4. What is new in Drools 4.0
2.4.1. Language Expressiveness Enhancements
2.4.2. Core Engine Enhancements
2.4.3. IDE Enhancements
2.4.4. Business Rules Management System - BRMS
2.4.5. Miscellaneous Enhancements
2.5. Upgrade tips from Drools 3.0.x to Drools 4.0.x
2.5.1. API changes
2.5.2. Rule Language Changes
2.5.3. Drools Update Tool
2.5.4. DSL Grammars in Drools 4.0
2.5.5. Rule flow Update for 4.0.2

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

The default order is the declared order, but this can be overiden using @Position

declare Cheese
    name : String @position(1)
    shop : String @position(2)
    price : int @position(0)

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.

Cheese( "stilton", "Cheese Shop", p; )
Cheese( "stilton", "Cheese Shop"; p : price )
Cheese( "stilton"; shop == "Cheese Shop", p : price )
Cheese( name == "stilton"; shop == "Cheese Shop", p : price )

Drools now provides Prolog style derivation queries, as an experimental feature. What this means is that a query or the 'when' part of a rule may call a query, via a query element. This is also recursive so that a query may call itself. A query element may be prefixed with a question mark '?' which indicuates that we have a pattern construct that will pull data, rather than the normal reactive push nature of patterns. If the ? is ommitted the query will be executed as a live "open query" with reactiveness, similar to how normal patterns work.

A key aspect of BC is unification. This is where a query parameter may be bound or unbound, when unbound it is considered an output variable and will bind to each found value.

In the example below x and y are parameters. Unification is done by subsequent bindings inside of patterns. If a value for x is passed in, it's as though the pattern says "thing == x". If a value for x is not passed in it's as though "x: thing" and x will be bound to each found thing.

Because Drools does not allow multiple bindings on the same variable we introduce ':=' unification symbol to support this.

declare Location
    thing : String 
    location : String 

query isContainedIn( String x, String y ) 
    Location( x := thing, y := location)
    ( Location(z := thing, y := location) and ?isContainedIn( x := x, z := y ) )

Positional and mixed positional/named are supported.

declare Location
    thing : String 
    location : String 

query isContainedIn( String x, String y ) 
    Location(x, y;)
    ( Location(z, y;) and ?isContainedIn(x, z;) )

Here is an example of query element inside of a rule using mixed positional/named arguments.

package org.drools.test

import java.util.List
import java.util.ArrayList

dialect "mvel"

declare Here
   place : String

declare Door
   fromLocation : String
   toLocation : String

declare Location
   thing : String
   location : String

declare Edible
   thing : String

query connect( String x, String y )
   Door(x, y;)
   Door(y, x;)

query whereFood( String x, String y )
   ( Location(x, y;) and
      Edible(x;) )
   ( Location(z, y;) and
      whereFood(x, z;) )

query look(String place, List things, List food, List exits)
   things := List() from accumulate( Location(thing, place;), collectList( thing ) )
   food := List() from accumulate( ?whereFood(thing, place;), collectList( thing ) )
   exits := List() from accumulate( ?connect(place, exit;), collectList( exit ) )

rule reactiveLook 
      Here( $place : place)
      ?look($place, $things; $food := food, $exits := exits)
      System.out.println( \"You are in the \" + $place);
      System.out.println( \"  You can see \" + $things );
      System.out.println( \"  You can eat \" + $food );
      System.out.println( \"  You can go to \" + $exits );

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

query isContainedIn( String x, String y ) 
    Location(x, y;)
    ( Location(z, y;) and isContainedIn(x, z;) )

rule look when 
    Person( $l : likes ) 
    isContainedIn( $l, 'office'; )
   insertLogical( $l + 'is in the office' );

Literal expressions can passed as query arguments, but at this stage you cannot mix expressions with variables.

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. The following example will return all objects contained in the office.

results = ksession.getQueryResults( "isContainedIn", new Object[] {  Variable.v, "office" } );
l = new ArrayList<List<String>>();
for ( QueryResultsRow r : results ) {
    l.add( Arrays.asList( new String[] { (String) r.get( "x" ), (String) r.get( "y" ) } ) );

The algorithm uses stacks to handle recursion, so the method stack will not blow up.

The existing Guided Decision Table has been replaced to provide a foundation on which to build our future guided Decision Table toolset. The initial release largely provides an equivalent feature-set to the obsolete Guided Decision Table with a few improvements, as explained in more detail below. A change from the legacy table was essential for us to begin to realise our desire to provide the number one web-based decision table available. With this foundation we will be able to expand the capabilities of our Guided Decision Table toolset to provide a feature rich, user-friendly environment.

A couple of maven artifacts (jars, wars, ...) have been renamed so it is more clear what they do. Below is the list of the GAV changes, adjust your pom.xml files accordingly when upgrading to the new version.

Table 2.1. Maven GAV changes overview

Old groupIdOld artifactIdNew groupIdNew artifactId
org.droolsdrools (the parent pom)org.droolsdroolsjbpm-parent
org.droolsdrools-examples-fusion / drools-examples-drl (jBPM using parts)org.droolsdroolsjbpm-integration-examples

For example: before, in your pom.xml files, you declared drools-api like this:


And now, afterwards, in your pom.xml files, you declare knowledge-api like this instead:


Drools now has extensive Spring support, the XSD can be found in the the drools-spring jar. The namespace is "http://drools.org/schema/drools-spring"

Example 2.2. KnowledgeBuilder example

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                           http://drools.org/schema/drools-spring http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-container/drools-spring/src/main/resources/org/drools/container/spring/drools-spring-1.0.0.xsd
                           http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
  <drools:resource id="resource1" type="DRL" source="classpath:org/drools/container/spring/testSpring.drl"/>

  <drools:kbase id="kbase1">
      <drools:resource type="DRL" source="classpath:org/drools/container/spring/testSpring.drl"/>
      <drools:resource ref="resource1"/>
      <drools:resource source="classpath:org/drools/container/spring/IntegrationExampleTest.xls" type="DTABLE">
        <drools:decisiontable-conf input-type="XLS" worksheet-name="Tables_2" />

      <drools:mbeans enabled="true" />
      <drools:event-processing-mode mode="STREAM" />

KnowledgeBase takes the following configurations: "advanced-process-rule-integration, multithread, mbeans, event-processing-mode, accumulate-functions, evaluators and assert-behavior".

From the the kbase reference ksessions can be created

Like KnowledgeBases Knowlege sessions can take a number of configurations, including "work-item-handlers, "keep-references", "clock-type", "jpa-persistence".

StatefulKnowledgeSessions can be configured for JPA persistence

Example 2.5. JPA configuration for StatefulKnowledgeSessions

<bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="org.h2.Driver" />
  <property name="url" value="jdbc:h2:tcp://localhost/DroolsFlow" />
  <property name="username" value="sa" />
  <property name="password" value="" />

<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="dataSource" ref="ds" />
  <property name="persistenceUnitName" value="org.drools.persistence.jpa.local" />

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
  <property name="entityManagerFactory" ref="myEmf" />

<drools:ksession id="jpaSingleSessionCommandService" type="stateful" kbase="kbase1">
      <drools:transaction-manager ref="txManager" />
      <drools:entity-manager-factory ref="myEmf" />
         <drools:persister for-class="javax.persistence.Entity" implementation="org.drools.persistence.processinstance.persisters.JPAVariablePersister"/>
         <drools:persister for-class="java.lang.String" implementation="org.drools.container.spring.beans.persistence.StringVariablePersister"/>
         <drools:persister for-class="java.io.Serializable" implementation="org.drools.persistence.processinstance.persisters.SerializableVariablePersister"/>

Knowledge Sessions can support startup batch scripts, previous versions used the "script" element name, this will be updated to "batch". The following commands are supported: "insert-object", "set-global", "fire-all-rules", "fire-until-halt", "start-process", "signal-event". Anonymous beans or named "ref" attributes may be used.

ExecutionNodes are supported in Spring , these provide a Context of registered ksessions; this can be used with Camel to provide ksession routing.

Spring can be combined with Camel to provide declarative rule services. a Camel Policy is added from Drools which provides magic for injecting the ClassLoader used by the ksession for any data formatters, it also augments the Jaxb and XStream data formatters. In the case lf Jaxb it adds additional Drools related path info and with XStream it registers Drools related converters and aliases.

You can create as many endpoints as you require, using different addresses. The CommandMessagBodyReader is needed to allow the payload to be handled by Camel.

Camel routes can then be attached to CXF endpoints, allowing you control over the payload for things like data formatting and executing against Drools ksessions. The DroolsPolicy adds some smarts to the route. If JAXB or XStream are used, it would inject custom paths and converters, it can also set the classloader too on the server side, based on the target ksession. On the client side it automatically unwrapes the Response object.

This example unmarshalls the payload using an augmented XStream DataFormat and executes it against the ksession1 instance. The "node" there refers to the ExecutionContext, which is a context of registered ksessions.

The Drools endpoint "drools:node/ksession1" consists of the execution node name followed by a separator and optional knowledge session name. If the knowledge session is not specified the route will look at the "lookup" attribute on the incoming payload instace or in the head attribute "DroolsLookup" to find it.

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.

A Drools blog article contains an example of Glazed Lists integration for live queries,


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

Interval "int:" timers follow the JDK semantics for initial delay optionally followed by a repeat interval. Cron "cron:" timers follow standard cron expressions:

Calendars can now controll when rules can fire. The Calendar api is modelled on Quartz http://www.quartz-scheduler.org/ :

Calendars are registered with the StatefulKnowledgeSession:

They can be used in conjunction with normal rules and rules including timers. The rule calendar attribute can have one or more comma calendar names.

Appearance has been cleaned, for example less pop ups. Reminders for save after changes in assets and information about actions that were taken, also better error reporting if something goes wrong.

Guided Editor has basic support for From, Accumulate and Collect Patterns. You can add any of these structures as regular Patterns. New expression builder component was created to add support for nested method calls of a variable. Using the “plus” button at the top of rule’s WHEN section or using the new “Add after” button present in every Pattern will open the popup to add new conditional elements to your rule. In the list of possible elements you will find three new entries: ”From”, “From Accumulate” and “From Collect”.

When you add a new “From” element, you will see something like the image below in the guided editor. The left pattern of the “From” conditional element is a regular Pattern. You can add there any type of conditional element you want.The right section of the “From” pattern is an expression builder.

When using 'from collect' In the left pattern you can choose from “java.util.Collection”, “java.util.List” or “java.util.Set” Fact Types. This Fact Types will be automatically included in the package’s Fact Types list.

The right pattern of the collect conditional element could be one of this patterns:

  • Fact Type Pattern

  • Free Form Expression

  • From Pattern

  • From Collect Pattern

  • From Accumulate Pattern

When using 'from accumulate' The left pattern could be any Fact Type Pattern. The right section of this conditional element is splited in two:

The left pattern could be any Fact Type Pattern. The right section of this conditional element is splited in two:

  • Source Pattern: (Bed $n, in the screenshot) could be any Fact Type, From, Collect or Accumulate pattern.

  • Accumulate function: Here you will find a tabbed panel where you can enter an accumulate function (sum() in the screenshot) or you can create an online custom function using the “Custom Code” tab.

Drools now has complete api/implementation separation that is no longer rules oriented. This is an important strategy as we move to support other forms of logic, such as workflow and event processing. The main change is that we are now knowledge oriented, instead of rule oriented. The module drools-api provide the interfaces and factories and we have made pains to provide much better javadocs, with lots of code snippets, than we did before. Drools-api also helps clearly show what is intended as a user api and what is just an engine api, drools-core and drools-compiler did not make this clear enough. The most common interfaces you will use are:

Factory classes, with static methods, provide instances of the above interfaces. A pluggable provider approach is used to allow provider implementations to be wired up to the factories at runtime. The Factories you will most commonly used are:

A Typical example to load a process resource. Notice the ResourceType is changed, in accordance with the Resource type:

'kbuilder', 'kbase', 'ksession' are the variable identifiers often used, the k prefix is for 'knowledge'.

It is also possible to configure a KnowledgeBase using configuration, via a xml change set, instead of programmatically.

The other big change for the KnowledgeAgent, compared to the RuleAgent, is that polling scanner is now a service. further to this there is an abstraction between the agent notification and the resource monitoring, to allow other mechanisms to be used other than polling.

There are two new interfaces added, ResourceChangeNotifier and ResourceChangeMonitor. KnowlegeAgents subscribe for resource change notifications using the ResourceChangeNotifier implementation. The ResourceChangeNotifier is informed of resource changes by the added ResourceChangeMonitors. We currently only provide one out of the box monitor, ResourceChangeScannerService, which polls resources for changes. However the api is there for users to add their own monitors, and thus use a push based monitor such as JMS.

ResourceFactory.getResourceChangeNotifierService().addResourceChangeMonitor( myJmsMonitor);

In addition to the ability of configuring options in drools through configuration files, system properties and by setting properties through the API setProperty() method, Drools-API now supports type safe configuration. We didn't want to add specific methods for each possible configuration methods for two reasons: it polutes the API and every time a new option is added to Drools, the API would have to change. This way, we followed a modular, class based configuration, where a new Option class is added to the API for each possible configuration, keeping the API stable, but flexible at the same time. So, in order to set configuration options now, you just need to use the enumerations or factories provided for each option. For instance, if you want to configure the knowledge base for assert behavior "equality" and to automatically remove identities from pattern matchings, you would just use the enums:

For options that don't have a predefined constant or can assume multiple values, a factory method is provided. For instance, to configure the alpha threshold to 5, just use the "get" factory method:

As you can see, the same setOption() method is used for the different possible configurations, but they are still type safe.

Batch Executor allows for the scripting of of a Knowledge session using Commands, which can also re, both the StatelessKnowledgeSession and StatefulKnowledgeSession implement this interface Commands are created using the CommandFactory and executed using the "execute" method, such as the following insert Command:

Typically though you will want to execute a batch of commands, this can be achieved via the composite Command BatchExecution. BatchExecutionResults is now used to handle the results, some commands can specify "out" identifiers which it used to add the result to the BatchExecutionResult. Handily querries can now be executed and results added to the BatchExecutionResult. Further to this results are scoped to this execute call and return via the BatchExecutionResults:

The CommandFactory details the supported commands, all of which can marshalled using XStream and the BatchExecutionHelper. This can be combined with the pipeline to automate the scripting of a session.

Using the above for a rulset that updates the price of a Cheese fact, given the following xml to insert a Cheese instance using an out-identifier:

We then get the following BatchExecutionResults:

The MarshallerFactory is used to marshal and unmarshal StatefulKnowledgeSessions. At the simplest it can be used as follows:

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 the user can implement their own. The two supplied 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 int id for each user object and stores them in a Map the id is written to the stream. When unmarshalling it simply looks to the IdentityMarshallingStrategy map to retrieve the instance. This means that if you use the IdentityMarshallingStrategy it's stateful for the life of the Marshaller instance and will create ids and keep references to all objects that it attempts to marshal.

For added flexability we can't assume that a single strategy is suitable for this we have added the ObjectMarshallingStrategyAcceptor interface that each ObjectMarshallingStrategy has. 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 one implementation is provided the ClassFilterAcceptor. This allows strings and wild cards to be used to match class names. The default is "*.*", so in the above the IdentityMarshallingStrategy is used which has a default "*.*" acceptor. But lets say we want to serialise all classes except for one given package, where we will use identity lookup, we could do the following:

The KnowlegeAgent is created by the KnowlegeAgentFactory. The KnowlegeAgent provides automatic loading, caching and re-loading, of resources and is configured from a properties files. The KnowledgeAgent can update or rebuild this KnowlegeBase 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 Following example constructs an agent that will build a new KnowledgeBase from the files specified in the path String. It will poll those files every 30 seconds to see if they are updated. If new files are found it will construct a new KnowledgeBase, instead of updating the existing one, due to the "newInstance" set to "true" (however currently only the value of "true" is supported and is hard coded into the engine):

Example 2.43. Constructing an agent

// Set the interval on the ResourceChangeScannerService if you are to use it and default of 60s is not desirable.
ResourceChangeScannerConfiguration sconf = ResourceFactory.getResourceChangeScannerService().newResourceChangeScannerConfiguration();
sconf.setProperty( "drools.resource.scanner.interval",
                  "30" ); // set the disk scanning interval to 30s, default is 60s
ResourceFactory.getResourceChangeScannerService().configure( sconf );
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
aconf.setProperty( "drools.agent.scanDirectories",
                  "true" ); // we want to scan directories, not just files, turning this on turns on file scanning
aconf.setProperty( "drools.agent.newInstance",
                  "true" ); // resource changes results in a new instance of the KnowledgeBase being built,
                            // this cannot currently be set to false for incremental building
KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent( "test agent", // the name of the agent
                                                                kbase, // the KnowledgeBase to use, the Agent will also monitor any exist knowledge definitions
                                                                aconf );
kagent.applyChangeSet( ResourceFactory.newUrlResource( url ) ); // resource to the change-set xml for the resources to add

KnowledgeAgents can take a empty KnowledgeBase or a populated one. If a populated KnowledgeBase is provided, the KnowledgeAgent will iterate KnowledgeBase and subscribe to the Resource that it finds. While it is possible for the KnowledgeBuilder to build all resources found in a directory, that information is lost by the KnowledgeBuilder so those directories will not be continuously scanned. Only directories specified as part of the applyChangeSet(Resource) method are monitored.

Drools 4.0 had simple "RuleFlow" which was for orchestrating rules. Drools 5.0 introduces a powerful (extensible) workflow engine. It allows users to specify their business logic using both rules and processes (where powerful interaction between processes and rules is possible) and offers a unified enviroment.

Drools 5.0 brings to the rules world the full power of events processing by supporting a number of CEP features as well as supporting events as first class citizens in the rules engine.

Drools 4.0 is a major update over the previous Drools 3.0.x series. A whole new set of features were developed which special focus on language expressiveness, engine performance and tools availability. The following is a list of the most interesting changes.

As mentioned before Drools 4.0 is a major update over the previous Drools 3.0.x series. Unfortunately, in order to achieve the goals set for this release, some backward compatibility issues were introduced, as discussed in the mail list and blogs.

This section of the manual is a work in progress and will document a simple how-to on upgrading from Drools 3.0.x to Drools 4.0.x.