Skip to: Site menu | Main content

Drools

Java Rules Engine

Groovy Semantic Module Print

The Groovy semantic module allows us to use the Groovy scripting language to specify rules in our DRL files.

Groovy is very easy for java developers to pick up and start using. Most Java semantic module rules can changed to Groovy rules by simply changing the xml namespace from java to groovy. Groovy has several powerful language features which can make your rules very concise and much less verbose than it's java counterpart.

Groovy is currently submitted as a JSR 241. See the Groovy website for more information on Groovy features and syntax.

XML Syntax

xml namespace

To start writing rules using the Groovy semantic module, you should first declare the xml namespace in your DRL file like the following, substituting your rule set name.

<rule-set name="CheesyBob RuleSet"
          xmlns="http://drools.org/rules"
          xmlns:groovy="http://drools.org/semantics/groovy">

condition element

This element is used to determine if a specific condition exists. A rule requires one or more conditions, and each condition must evaluate to true if the consequence is to fire.

Example:
<groovy:condition> bob.likesCheese() == true </groovy:condition>

Notice how the conditional expression does not end with a semicolon. You mustn't use semicolons in your conditional expressions--these are not executable blocks. Conditions are not mutators. Altering values in the parameter objects in your conditions is bad form and it'll probably break your rule set at execution time. Just Say No.

<groovy:condition> bob.poundsOfCheeseEaten() &amp;lt;= 3 </groovy:condition>

The above condition is correct. You cannot use left or right angle brackets directly inside your conditional expressions. In order to use the < and > operators you've got to write &lt; and &gt;, respectively.

consequence element

The consequence element lets you use Java language semantics to alter information in the Working Memory via the drools variable, which is an instance of KnowledgeHelper. There are a few guidelines you need to bear in mind when writing Groovy consequence blocks.

First, you can use any variables declared in a parameter element earlier in the rule, you also have access to application-data. If you want to create other variables, you must import their class types inside the consequence; unless they are already imported via a rule-set's import or they are from the java.lang package.

Example:
<grooy:consequence>
    import org.drools.example.simple.Cheese;

    cheese = new Cheese("mozzarella");
    drools.assertObject(cheese);
    bob.needsCheese(true);
    System.out.println( " ${bob.getName()} really needs some cheese. 
                        Some ${cheese.getName()} would do great!" );
</groovy:consequence>

The block above imports the Cheese class, instantiates a new Cheese object and asserts the cheese Object into the Working Memory. It also alters the state of the Bob object. Notice that every line of Java code ends in a semicolon. In the consequence block, you must use semicolons.

The following example of a Groovy consequence demonstrates one of the more powerful language features of Groovy, closures. In the following block, we assume the Bob object has a shopping list of all the cheeses he is going to purchase. We can iterate over the list and assert each item in the list into Working Memory in one line of code.

Example:
<groovy:consequence>
    bob.getShoppingList().each { item | drools.assertObject( item ) } ;
</groovy:consequence>

One of the powers of the consequence block is that it can assert objects into and remove them from the working memory at runtime. This is absolutely crucial to declarative programming and working with rules. The consequence element has three built-in methods that it uses to alter the contents of the working memory.

Method Signature* What it does
void assertObject(Object object) Asserts an object, notice that it does not return the FactHandle.
void assertObject(Object object, boolean dynamic) Asserts an object specifying that it implement the onPropertyChange listener, notice that it does not return the FactHandle.
void modifyObject(Object object) Modifies an object. Notice that the FactHandle is not passed so the implementation must lookup the FactHandle form the working memory.
void modifyObject(Object oldObject, Object newObject) Modifies an object by looking up the handle of the oldObject and replacing the oldObject with the newObject for the FactHandle. This isu sed for updating immutable objects.
vooid retractObject(Object object) Retracts an object from the WorkingMemory. All Activations on the Agenda that are cancelled should emit ActivationCancelled events.
String getRuleName() The current rule name.
List getObjects() A List of the objects in the WorkingMemory.
List getObjects(Class objectClass) All the Objects in the WorkingMemory that match the given Class filter.
void clearAgenda() Clears the agenda causing all existing Activations to fire ActivationCancelled events.