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:
- If you have a couple there is a discount of 5%
- If you purchase stuff for value more than 3000 bucks, you will get a flat 2% discount
- 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. Installation of Drools
Most simplest way to setup drools is to simply install Drools Eclipse Plugin.
- 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.
- 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. - 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 ofdrools-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:
knowledge-api
– this provides the interfaces and factoriesdrools-core
– this is the core engine, runtime component. This is the only runtime dependency if you are pre-compiling rules.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 when
…then
… 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.
You can download the full source code of this example here: DroolsBasicsMavenWay.zip