Skip to: Site menu | Main content

Drools

Java Rules Engine

FAQ Print

What happened to Drools 1.0?

It was sent to live on a farm with some nice people. It has plenty of room to run around and is good friends with the goats. No, you can never go visit it there.

Backward Chaining

Backward Chaining are query based system where an application queries a fact space to see if something is true. Prolog is one of the original backward chaining systems. Backward Chaining systems are Imperative based systems. See Resources#Backward Chaining Systems for a list implementations.

Forward Chaining

Forward chaining systems are event based and consequences are triggered based on the information in the fact space. Forwarding chaining systems are Declarative based systems. See Resources#Forward Chaining Systems for a list of implementations.

Detailed explanation on Forward and Backward Chaining?

Charles Forgey at his rulespower website provides two excellent articles on forward and backward chaining:

Forward and Backward Chaining Part I - http://www.rulespower.com/contents/article1.html

Forward and Backward Chaining Part II - http://www.rulespower.com/contents/article1b.html

What kind of rule engine is Drools?

Drools is, at its core, an engine for processing Rete graphs and is a Forward Chaining system. Rete is an algorithm that evaluates a declarative predicate against a changing set of set in real time. Consider an SQL select statement that executes a WHERE clause to find matching rows. Rete uses a progressive relational join to update a view of matching rows. As rows are added to any table, it's evaluated against the predicate and mapped into or out of the matching view.

Drools wraps the semantics of the normal relational Rete into an [object-oriented] model that's more compatible with Java objects. Additionally, by mapping to objects, Domain Specific Languages can be created that operate upon an application's own object model.

A note about 'business rules'

A higher-level form of rule is the business rule. Business rules do not necessarily follow the if-then form, but may be specified in different formats that are not as closely linked to the underlying rule-engine implementation. Business rules tend to use the must or must not form to expression constraints or inferences.

  • An order must not be billed before it ships.
  • An applicant for store credit must be 18 years of age.

    Drools does not directly support this level of business rules, but other projects built upon Drools may easily support such notation.

Fact manipulation

The Working Memory is where all knowledge is contained, each item of knowledge is called a Fact. The working memory is often referred to as the fact space; facts can be asserted, modified and retracted from the working memory. see Working Memory.

How do I pass information to Working Memory without having to assert them as facts?

Drools provides a mechanism called Application Data to allow a user to make information available the Working Memory without the user having to assert the objects as facts. The Pet Store Example uses this to pass a reference of the JFrame to allow for user interation.

workingMemory.setApplicationData( "frame", frame );

The consequence can then access that information by name:

<java:consequence>
            import javax.swing.JOptionPane;

            Object[] options = {"Yes",
                                "No"};
            int n = JOptionPane.showOptionDialog(frame,
                                                 "Would you like to buy a tank for your "
                                                 + cart.getItems( "Gold Fish" ).size() + " fish?",
                                                 "Purchase Suggestion",
                                                 JOptionPane.YES_NO_OPTION,
                                                 JOptionPane.QUESTION_MESSAGE,
                                                 null,
                                                 options,
                                                 options[0]);

Please see Application Data for more details.

Infinite Recursion

During the evaluation of a Rule's Consequence, if facts are modified which create a match for the current activated rule recursion may happen, potentially an infite recursion:

<rule name="example rule">
  <parameter identifier="s">
    <java:class>State</java:class>
  </parameter>

  <java:condition>s.getState() == true</java:condition>

  <java:consequence>
    s.setState(true);
    drools.modifyObject(s);
  </java:consequence>
</rule>

To stop the current rule from being able to place itself back onto the Agenda use the no-loop attribute for a rule:

<rule name="example rule" no-loop="true">

The default for this property is "false"

Condition Ordering

How do I build with Ant?

Just go to the main drools directory and type "ant".

Why are you using Maven

What dependencies does Drools have?

If you are using the org.drools.io.RuleBaseBuilder to build your RuleBases or to run drools-examples - which needs io.RuleBaseBuilder - you must include the following jars:

  • drools-core
  • drools-smf
  • drools-io
  • drools-base

Then depending on which semantic module you are using you must include drools-<semantic> and also its dependencies.

  • drools-java
    • antlr
    • janino
  • drools-python
    • jython
  • drools-groovy
    • asm
    • asm-util
    • groovy

Why does Drools have multiple jars?

I get the error "no semantic module for namespace '<namespace>'"

When building a RuleSet, Drools uses the Semantics Module Framework (SMF) and its factory classes. The SMF registers all available Semantic Modules. If your drl attempts to use XML tags from a namespace not registered to the SemanticRepository you get the error NoSuchSemanticModuleException. For instance if you did not include the drools-base dependancy, which is needed for all semantic modules, you would get the error:

no semantic module for namespace 'http://drools.org/rules'

Semantic modules and the namespaces used

How are drl files loaded?

org.drools.io.RuleBaseBuilder uses org.drools.io.RuleSetReader to parse the drl file. org.xml.sax.helpers.DefaultHandler is the base class of io.RuleSetReader which has handler methods for each element in the drl. DefaultHandler passes the namespace being used in the element to the RuleSetReader handler method which in turn calls SemanticRepository.lookupSemanticModule( uri ). If the namespace is not currently handled, i.e. the module jar is not in the classpath, the SemanticRespository throws NoSuchSemanticModuleException.

SemanticRepository.lookupSemanticModule( uri ) returns SemanticModule which makes factory classes available for the specified semantic. These factory classes are used to instantiate the members of a Rule: Parameters, Conditions, Extractors and Consequences. The Rule in turn is added to a RuleSet which eventually is passed to org.drools.reteoo.Builder which transforms the RuleSet into a Reteoo network.

What happened to BeanShell? What is Janino?

After the 2.0-beta-16 release of Drools, the technology underlying the Java SMF was changed from BeanShell to Janino. Your existing Java DRL files should continue to work, but there are a couple incompatibilities you should be aware of.

  • With BeanShell, trailing semi-colons were allowed in conditions. With Janino, they are not allowed so you must delete those trailing semi-colons. That means a condition like this:
    <java:condition>one.equals(two);</java:condition>

    needs to be converted to look like this:

    <java:condition>one.equals(two)</java:condition>
  • With BeanShell, import statements could be placed almost anywhere in consequences. With Janino, import statements may only occur as the first lines of the consequence before any other Java statements. You should also always place only one import statement on a line. This means a consequence like this:
    <java:consequence>
      System.out.println();
      import java.util.List; import java.util.ArrayList;
      List list = new ArrayList();
    </java:consequence>

    needs to be converted to look like this:

    <java:consequence>
      import java.util.List;
      import java.util.ArrayList;
      System.out.println();
      List list = new ArrayList();
    </java:consequence>
  • With BeanShell, sometimes import statements were not necessary. With Janino, you may find you need to add import statements for classes that weren't required with BeanShell. This means a consequence like this:
    <java:consequence>
      List list = new ArrayList();
    </java:consequence>

    needs to be converted to look like this:

    <java:consequence>
      import java.util.List;
      import java.util.ArrayList;
      List list = new ArrayList();
    </java:consequence>
  • BeanShell plays fast and loose with casting. Janino requires explicit casting, like Java, and will not allow runtime resolution of method dispatching.

    Code like
    list.get(0).someBusinessMethod()

    must be converted to using explicit casts such as

    ((MyBizObject)list.get(0)).someBusinessMethod()

Is Drools fully compliant with the JSR-94 Java Rule Engine API?

As of Drools 2.0 beta 17, Drools is a fully JSR-94 compliant rule engine, according to self-certification done using JSR-94 TCK v1.1.

The drools-jsr94 module exists to provide the necessary classes to enable Drools to be fully compliant with JSR-94. The JSR-94 Drools interface is demonstrated in the following examples:

For instructions on how to run Drools under the JSR-94 Technology Compatibility Kit and determine for yourself just how compliant Drools is, please see:

Can I use Javascript, OGNL, <your language here> in Drools?

Drools currently has language support for Java, Python and Groovy via the semantic module implementations; as these are the only languages that have been requested by users. It's easy to implement your own language support, as long as there is a java implementation available; each semantic module implementation must pass the Semantics Module Framework test suite and update all examples as well as be maintained/updated as new tests and examples are added. Additional language support will be included in the default distribution if there are enough user requests and active developers to maintin it.

My DRL file is huge; can I split it into several smaller files?

Absolutely. With the use of XML entities it is possible to have a master DRL file that includes the contents of several other DRL files. For more details, see:

When serializing a WorkingMemory back into memory values are not updated/correct

When serialising a WorkingMemory back into memory you have to remember that it effectively makes a clone of your knowledge; the WorkingMemory and main application no longer reference the same object. When you serialize back into memory you must get your objects again using the FactHandle, or search for it via the returned collection using the get Objects() method.

Using Drools with OC4J

Drools depends on each semantic modudule having its own drools.conf definition; see Semantics Module Framework for more details. OC4J is unable to allow getResources to return an array for each of the available drools.conf URLS, this leads to error messages like:

  • no semantic module for namespace - http:.drools.org/rules

Which means that it has been able to find the drools.conf file for the drools-base module. To overcome this you need to create a custom drools.conf file, in the classpath, with the contents of all of the other META-INF/drools.conf files then set system property 'drools.conf' to point to the location within the classpath to your custom drools.conf, ie:

  • -Ddrools.conf=com/myco/MyDrools.conf

This new drools.conf file will look something like:

drools-base
drools-groovy
drools-java
drools-python

Mark stack overflow errors

When repeatedly rebuilding RuleSets Janino will recompile the classes each time, when the jvm option "noclassgc" is enabled this can cause memory leaks as the classes from the previous build are never garbage collected - it is suggested you do not use this JVM option.

Distribution Goals

Drools provides several goals to help with packaging and distribution which also may be helpful to other users:

  • jar-all
    • compiles all modules to jars and copies to ${basedir}/lib/
  • drools:jar-all
    • Creates a single jar of all the class files, with concatenated drools.conf in ${basedir}/lib/
  • drools:dist
    • runs all other distribtion goals
  • drools:dist-bin
    • create zip and tar.gz in ${basedir}/target/dist/ of compiled jars, with javadocs
  • drools:dist-bin-withdeps
    • Create zip and tar.gz in ${basedir}/target/dist/ of compiled jars and deps with javadocs
  • drools:dist-src
    • create zip and tar.gz in ${basedir}/target/dist/ of source code

      drools:get-deps -
    • download and copy all drools-* dependencies to ${basedir}/target/dependencies

Drools uses maven.jar.override to stop local repository install each time we recompile drools.

Dealing with Immutable Objects - Integer, Float etc

During the consequence you don't need to deal with fact handles as the KnowledgeHelper, "drools", does an object->handle lookup based upon identity of the object passed in. This can cause a problem if the identity of the object changes, such as when you try to update an immutable object like Integer, String etc. If the identity of the object changes then there is no handle associated with the new object.

There are two solutions for this; mutable object wrappers or the two arg version of modifyObject.

Two arg modifyObject:

modifyObject(Object oldObject, Object newObject);

MutableWrapper example:

public class MutableInteger {
    private int integer;
    public MutableInteger(int integer) { set(integer); }
    public void set(int integer) { this.integer = integer; }
    public int get() { return this.integer; }
    public String toString() { return String.valueOf(this.integer); }
    // you'll also need to write an equals() method for a complete working solution
}

Why do I get "UnsupportedClassVersionError"?

Some of the drools jars are dependent java5 features (eg, drools-annotations.jar, drools-spring-jdk5.jar) and will only run under jdk1.5+. To eliminate this error, either remove the java5 dependent features from your classpath or run with jdk1.5+.

Does Drools run on .Net

Yes Drools runs on .Net - see http://www.drools.org/DotNet