One of the blog readers, who posted a comment in my previous post Drools – tutorial on writing DSL template asked to me to help him with creating DSL for the following rule, so I decided to use his example as a small case study:
For readability, I added some comments to the original rule:
rule 'Rank accomodation name'
salience 90
when
//Matches every AccomodationBase
$accBase: AccomodationBase()
//Uses inline eval to evaluate that there is
//no AccomodationBase of type AccomodationRank
//in the session.
//To remind: inline eval evaluated only once
//and then it is cached by Drools.
not AccomodationBase(eval($accBase
instanceof AccomodationRank))
//Matches every AccomodationRank that has the same
//level and the description as the AccomodationBase
$accRank: AccomodationRank(
level == $accBase.level,
description == $accBase.description)
then
//Increments the score
$accRank.setScore($accRank.getScore()+1);
end
For my solution, I created two POJOs, tester class DSL and DSLR files. The following is my DSL:
[when]AccomodationBaseObj = $accBase: AccomodationBase()
[when]There is Accomodation base object of type Accomodation rank = eval($accBase instanceof AccomodationRank)
[when]AccomodationRankObj = $accRank: AccomodationRank(level == $accBase.level, description == $accBase.description)
[then]IncrementScore = $accRank.setScore($accRank.score+1);
[then]PrintScore = System.out.println("Rank score: " + $accRank.score);
[then]PrintLevel = System.out.println("Base level: " + $accBase.level);
and this is the DSLR file:
package net.javabeansdotasia.casestudy; expander accomodation.dsl import net.javabeansdotasia.casestudy.pojo.AccomodationBase; import net.javabeansdotasia.casestudy.pojo.AccomodationRank; rule "Rank" dialect "mvel" when AccomodationBaseObj not (There is Accomodation base object of type Accomodation rank) AccomodationRankObj then IncrementScore PrintScore PrintLevel end
In the following class I load DSL and DSLR files in to the KnowledgeBuilder and get a KnowledgeBase object. Once I have the KnowledgeBase object, I can get StatefulKnowledgeSession or StatelessKnowledgeSession, depends on what I want to do.
package net.javabeansdotasia.casestudy.utils;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
public class MyKnowledgeBaseFactory {
public static KnowledgeBase
createKnowledgeBaseFromDSL(String dslr,
String dsl) throws Exception {
KnowledgeBuilder builder =
KnowledgeBuilderFactory
.newKnowledgeBuilder();
//Attention!!!!
//Add DSL BEFORE DSLR
builder.add(
ResourceFactory.newClassPathResource(dsl),
ResourceType.DSL);
builder.add(
ResourceFactory.newClassPathResource(dslr),
ResourceType.DSLR);
KnowledgeBuilderErrors errors = builder.getErrors();
if (errors.size() > 0) {
for (KnowledgeBuilderError error : errors) {
System.err.println(error);
}
throw new IllegalArgumentException("Could not parse knowledge.");
}
KnowledgeBase knowledgeBase =
KnowledgeBaseFactory.newKnowledgeBase();
knowledgeBase.addKnowledgePackages(
builder.getKnowledgePackages());
return knowledgeBase;
}
}
Below is my Tester class:
package net.javabeansdotasia.casestudy.test;
import net.javabeansdotasia.casestudy.pojo.AccomodationBase;
import net.javabeansdotasia.casestudy.pojo.AccomodationRank;
import net.javabeansdotasia.casestudy.utils.MyKnowledgeBaseFactory;
import org.drools.KnowledgeBase;
import org.drools.runtime.StatefulKnowledgeSession;
public class Test {
public static final void main(String[] args) {
try {
KnowledgeBase kbase =
MyKnowledgeBaseFactory
.createKnowledgeBaseFromDSL(
"accomodation.dslr",
"accomodation.dsl");
StatefulKnowledgeSession ksession =
kbase.newStatefulKnowledgeSession();
AccomodationBase accomBase =
new AccomodationBase(9, "Just Demo");
AccomodationRank accomRank =
new AccomodationRank(9, "Just Demo");
ksession.insert(accomBase);
ksession.insert(accomRank);
ksession.fireAllRules();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
As you may have noticed, in Drools 5 the process of loading the rule files (DSL and DSLR) and getting a working session is different to Drools 4. In Drools 5 there is a whole new set of APIs. Basically, main change is that Drools now is knowledge oriented, instead of rule oriented. It was a real step forward in order to support other forms of logic, such as work-flow and event processing. You can read about it in Drools 5.0 docs.
That it. Please note that the above example was tested by me and its working fine. I also included source files for the above example as Eclipse project. You can simply create a new Java project from this existing Ant build.xml file.
Also, I wanted to point out that in my Eclipse project setup my Drools binaries located under JAVA_HOME/lib/drools-5.0-bin/ (have a look at the build.xml)
Cheers
loading...
Related posts:
- Drools 5 – Complex Event Processing
From Drools version 4 to version 5, the framework has undergone quite a few improvements. These include support for three additional business modeling... - Drools 5 Case Study 2 – Complex Event Processing
In my previous post Drools 5 – Complex Event Processing, I gave introduction to Drools Fusion module. In the current post, I would... - Drools – Tutorial on Writing DSL Template
Few months ago I wrote a post that describes an example that uses source DRL in conjunction with DSL template. In the current... - Drools – Stop Executing Current Agenda Group and All Rules
Sometimes, depends on your business rules in your application, there is a need to stop current agenda group or all rules from continuing... - Brainteaser Drools: Testing Objects
This can be a hard one, since it requires from you to be familiar with Drools. Consider the condition side of the following...
