Enterprise Java

JBoss Drools Tutorial for Beginners

If you consider any business process, you will see that is composed of one or more rules. Each rule may be responsible for some task based on some condition. As the rules grow it becomes difficult to manage the rules and to maintain them. This is why we need some tool to manage these rule and Drools fits the bill. It is a Business Rule Management System (BRMS) and rules engine written in Java.
A rule could be:

  1. If you have a couple there is a discount of 5%
  2. If you purchase stuff for value more than 3000 bucks, you will get a flat 2% discount
  3. If you are a first time user, you will get 10 bucks into your wallet

 

 
In order to run through the rules, all we have to do is apply Customer and Cart state on the rules. Rules are static but data is dynamic so the data drives the decision process.
Let’s get started with setup and then examples.

This example uses the following frameworks:

  1. Maven 3.2.3
  2. Java 8
  3. Drools 6.2
  4. Eclipse  as the IDE, version Luna 4.4.1.

1. Installation of Drools

Most simplest way to setup drools is to simply install Drools Eclipse Plugin.

  1. The rule workbench (for Eclipse) requires that you have Eclipse 3.4 or greater. It is also important that you install Eclipse GEF 3.4 or greater. You can install it using the built in update mechanism. Open the Help->Install New Software…->Add Site. Enter http://download.eclipse.org/tools/gef/updates/releases/ in Work with. Select GEF (Graphical Editing Framework). Press next, and agree to install the plug-in (an Eclipse restart may be required). Once this is completed, then you can continue on installing the rules plug-in.
  2. Download Drools Eclipse IDE Plugin. It is a zip file called droolsjbpm-tools-distribution-6.2.0.Final so you need to unzip the file and extract the contents. You need to install the plugin by opening Help->Install New Software…->Add Site. Enter the local location of \droolsjbpm-tools-distribution-6.2.0.Final\binaries\org.drools.updatesite, a name and click on Add. This will install the Drools Eclipse IDE plugin.
  3. Defining a Drools runtime – Download Drools Engine from Drools Download page. Its a zip file, since my drools ver# is 6.2, the file name is called drools-distribution-6.2.0.Final.zip. You need to unzip and extract contents. Go to Preferences->Drools->Installed Drools Runtime. Click on Add. Enter name and path of drools-distribution-6.2.0.Final\binaries. Click on OK to add the Drools Runtime Engine.

2. Create Drools Project

Click on File->New->Other->Drools->Drools Project to create a drools project based on the Drools Eclipse Plugin. The project will automatically create a sample drl file Sample.drl containing a rule. You will also find a java main class DroolsTest to test the rule.

DroolsTest:

package com.sample;

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

/**
 * This is a sample class to launch a rule.
 */
public class DroolsTest {

    public static final void main(String[] args) {
        try {
            // load up the knowledge base
	        KieServices ks = KieServices.Factory.get();
    	    KieContainer kContainer = ks.getKieClasspathContainer();
        	KieSession kSession = kContainer.newKieSession("ksession-rules");

            // go !
            Message message = new Message();
            message.setMessage("Hello World");
            message.setStatus(Message.HELLO);
            kSession.insert(message);
            kSession.fireAllRules();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    public static class Message {

        public static final int HELLO = 0;
        public static final int GOODBYE = 1;

        private String message;

        private int status;

        public String getMessage() {
            return this.message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public int getStatus() {
            return this.status;
        }

        public void setStatus(int status) {
            this.status = status;
        }

    }

}

Sample.drl:

package com.sample
 
import com.sample.DroolsTest.Message;
 
rule "Hello World"
    when
        m : Message( status == Message.HELLO, myMessage : message )
    then
        System.out.println( myMessage );
        m.setMessage( "Goodbye cruel world" );
        m.setStatus( Message.GOODBYE );
        update( m );
end

rule "GoodBye"
    when
        Message( status == Message.GOODBYE, myMessage : message )
    then
        System.out.println( myMessage );
end

Output:

Hello World
Goodbye cruel world

3. Maven Dependencies

You can very well create a Maven project and specify the drools dependencies in pom.xml.
If just want to rely on Maven, you need to add the below dependencies:

  1. knowledge-api – this provides the interfaces and factories
  2. drools-core – this is the core engine, runtime component. This is the only runtime dependency if you are pre-compiling rules.
  3. drools-complier – this contains the compiler/builder components to take rule source, and build executable rule bases. You don’t need this during runtime, if your rules are pre-compiled.

You just need to add drools-compiler dependency to your pom.xml, the other two dependencies are transitive dependencies.

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javacodegeeks.drools</groupId>
	<artifactId>droolsHelloWorld</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>org.drools</groupId>
			<artifactId>drools-compiler</artifactId>
			<version>${drools.version}</version>
		</dependency>		
	</dependencies>
	<properties>
		<drools.version>6.2.0.Final</drools.version>
		<jbpm.version>6.2.0.Final</jbpm.version>
	</properties>
</project>

4. Define a Drools Rule

Here is a simple POJO which contains a topic and method called introduceYourself().

DroolsIntroduction:

package com.javacodegeeks.drools;

/**
 * This is a sample class to launch a rule.
 */
public class DroolsIntroduction {
    private String topic;
    
    public DroolsIntroduction(String topic) {
        this.topic = topic;
    }

    public String getTopic() {
        return topic;
    }
        
    public String introduceYourself() {
        return "Drools 6.2.0.Final";
    }
}

Now let’s define a simple rule. Rule is the above POJO will introduce itself only when the topic is about Drools.

Here is the rule:

hello.drl:

package com.javacodegeeks.drools;
rule "Drools Introduction"
when
$droolsIntro : DroolsIntroduction( topic == "Drools" )
then
System.out.println($droolsIntro.introduceYourself());
end

5. Rule Structure

You need to specify the package of the rule just the way we do it for java. Next follows the import statements, as seen here at the top of the file, are structured the same way as they are
in Java class files. Each rule starts with rule and then its name. Next comes the condition whenthen… end. To access the POJO property, you need to use it directly. You don’t need to call the getters to access properties.

when $droolsIntro : DroolsIntroduction( topic == "Drools" )

The condition starts with the class name DroolsIntroduction. It checks whether the topic property is equal to ‘Drools’. If yes, we set the instance to a variable, $droolsIntro. Next, we take some action desired when our condition is met. We use the variable to call an instance method $droolsIntro.introduceYourself() and print the returned value using System.out.println.

then
System.out.println($droolsIntro.introduceYourself());
end

6. KIE Module

Now its the time to run the rule. In order to run the rule, Drools provides a configuration file called kmodule.xml. It acts as a descriptor that selects resources to knowledge bases and configures those knowledge bases and sessions.

KBase is a repository of all the application’s knowledge definitions. Sessions are created from it and then data is inserted into the session which in turn will be used to start the process.
Here is the configuration file which is located in META-INF directory.

kmodule.xml:

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
    <kbase name="rules" packages="rules">
        <ksession name="ksession-rules"/>
    </kbase>
</kmodule>

In order to run the rule, we need to add the below highlighted code. If yuou note, we create an instance of DroolsIntroduction and insert the instance to the session. Next, we call kSession.fireAllRules() run the rule.

DroolsIntroduction:

package com.javacodegeeks.drools;

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

/**
 * This is a sample class to launch a rule.
 */
public class DroolsIntroduction {
    private String topic;
    
    public DroolsIntroduction(String topic) {
        this.topic = topic;
    }

    public static final void main(String[] args) {
        try {
            // load up the knowledge base
            KieServices ks = KieServices.Factory.get();
            KieContainer kContainer = ks.getKieClasspathContainer();
            KieSession kSession = kContainer.newKieSession("ksession-rules");

            DroolsIntroduction droolsIntroduction = new DroolsIntroduction("Drools");            
            kSession.insert(droolsIntroduction);
            kSession.insert(new DroolsIntroduction("spring"));
            kSession.insert(new DroolsIntroduction("Drools"));
            kSession.fireAllRules();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    public String getTopic() {
        return topic;
    }
        
    public String introduceYourself() {
        return "Drools 6.2.0.Final";
    }
}

Only if the topic is ‘Drools’, you will see an introduction output. Since we have added DroolsIntroduction twice, we see output ‘Drools 6.2.0.Final’ repeating.

Output:

Drools 6.2.0.Final
Drools 6.2.0.Final

7. Global Variable

In this example, I will show you how to assign a global variable to a session.

First declare the global in the rule file, global String topicLevel.

Next, set the global variable to the rule session.

hello.drl:

package com.javacodegeeks.drools;
global String topicLevel
rule "Drools Introduction"
when
$droolsIntro : DroolsIntroduction( topic == "Drools" )
then
System.out.println($droolsIntro.introduceYourself() + ", topic level is " + topicLevel);
end

DroolsIntroduction:

package com.javacodegeeks.drools;

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

/**
 * This is a sample class to launch a rule.
 */
public class DroolsIntroduction {
    private String topic;
    
    public DroolsIntroduction(String topic) {
        this.topic = topic;
    }

    public static final void main(String[] args) {
        try {
            // load up the knowledge base
            KieServices ks = KieServices.Factory.get();
            KieContainer kContainer = ks.getKieClasspathContainer();
            KieSession kSession = kContainer.newKieSession("ksession-rules");

            DroolsIntroduction droolsIntroduction = new DroolsIntroduction("Drools");            
            kSession.insert(droolsIntroduction);
            kSession.insert(new DroolsIntroduction("spring"));
            kSession.insert(new DroolsIntroduction("Drools"));
            kSession.fireAllRules();
            
            kSession.setGlobal("topicLevel", "Beginner");
            kSession.insert(new DroolsIntroduction("Drools"));
            kSession.fireAllRules();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    public String getTopic() {
        return topic;
    }
        
    public String introduceYourself() {
        return "Drools 6.2.0.Final";
    }
}

Output:

Drools 6.2.0.Final, topic level is null
Drools 6.2.0.Final, topic level is null
Drools 6.2.0.Final, topic level is Beginner

8. Functions

To get rid of the ‘null’ topic level, we will introduce a new function called getDefaultIfNull() to our rule.

It will return a default value of the level if the global variable is not set to the session.

hello.drl:

package com.javacodegeeks.drools;
global String topicLevel
rule "Drools Introduction"
when
$droolsIntro : DroolsIntroduction( topic == "Drools" )
then
System.out.println($droolsIntro.introduceYourself() + ", topic level is " + getDefaultIfNull(topicLevel));
end
function String getDefaultIfNull(String topicLevel) {
return topicLevel == null ? "Moderate" : topicLevel;
}

If you run the rule now, you will get a default topic level in the output.

Output:

Drools 6.2.0.Final, topic level is Moderate
Drools 6.2.0.Final, topic level is Moderate
Drools 6.2.0.Final, topic level is Beginner

9. Download the Eclipse Project

This was a beginner tutorial on Drools.

Download
You can download the full source code of this example here: DroolsBasicsMavenWay.zip

Ram Mokkapaty

Ram holds a master's degree in Machine Design from IT B.H.U. His expertise lies in test driven development and re-factoring. He is passionate about open source technologies and actively blogs on various java and open-source technologies like spring. He works as a principal Engineer in the logistics domain.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button