Drools 5 Case Study 1- Writing DSL for DRL rule

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

More from Alexander Zagniotov:

  1. 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....
  2. Drools – Working with Stateless Session
    Drools (now it is also called JBoss Rules) is an amazing open source framework which allows you to create business...
  3. Feedback by the Drools Team
    Today while checking my blog’s referrers, to my pleasant surprise I discovered that few Drools articles I have published on...
  4. 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...
  5. Brainteaser Drools: Testing Objects
    This can be a hard one, since it requires from you to be familiar with Drools. Consider the condition side...