September 30, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Rev Up the Drools 5 Java Rule Engine

  • May 19, 2009
  • By Anghel Leonard
  • Send Email »
  • More Articles »

Main Classes of the Drools API

At first, Drools was rules oriented. The API was hard to understand, poorly documented, and didn't cover things like event processing properly. In time, Drools became knowledge oriented and much easier to use and implement in projects. Before seeing Drools in action, get to know the main classes of the Drools API (you will recognize these classes later in a real example that will transform the spaghetti code from the introduction):
  • org.drools.builder.KnowledgeBuilder – Transforms a source file into a KnowledgePackage of rule and process definitions that a KnowledgeBase can consume. (Later, you will see how to create a source file, like a .drl or .xls file.)
  • org.drools.KnowledgeBase – A repository of all the application's knowledge definitions; contains rules, processes, functions, type models.
  • org.drools.agent.KnowledgeAgent – Provides automatic loading, caching, and re-loading of resources, and is configured from a properties file.
  • org.drools.runtime.StatefulKnowledgeSession – The most common way to interact with a rule engine. A StatefulKnowledgeSession allows the application to establish an iterative conversation with the engine, where the reasoning process may be triggered multiple times for the same set of data. After the application finishes using the session, though, it must call the dispose() method in order to free the resources and used memory.
  • org.drools.runtime.StatelessKnowledgeSession – A convenience API that wraps a StatefulKonwledgeSession. It removes the need to call dispose(). Stateless sessions do not support iterative insertions and fireAllRules from Java code. The act of calling execute(...) is a single shot method that will internally instantiate a StatefullKnowledgeSession, add all the user data and execute user commands, call fireAllRules, and then call dispose().

These interfaces are sustained by a set of factory classes:

  • org.drools.builder.KnowledgeBuilderFactory – This factory is used to build the knowledge base definitions that are held collectively in KnowledgePackages. The KnowledgePackage also provides the role of "namespacing." You can supply an optional KnowlegeBuilderConfiguration, which is itself created from this factory. The KnowledgeBuilderConfiguration allows you to set the ClassLoader to be used along with other settings like the default dialect and compiler, as well as many other options.
  • org.drools.io.ResourceFactory – A convenience factory to provide resource implementations for the desired IO resource.
  • org.drools.KnowledgeBaseFactory – This factory will create and return a KnowledgeBase instance. An optional KnowledgeBaseConfiguration can be provided. The KnowlegeBaseConfiguration is also itself created from this factory.
  • org.drools.agent.KnowledgeAgentFactory – The KnowlegeAgent is created by the KnowlegeAgentFactory. The KnowlegeAgent provides automatic loading, caching, and re-loading of resources, and is configured from a properties file. The KnowledgeAgent can update or rebuild this KnowlegeBase as the resources it uses change. The configuration given to the factory determines the strategy for this, but it is typically pull based using regular polling.

The above descriptions are available in the official Javadoc for Drools 5 (see bottom of that page for download information).

Loading a Rule Resource Using Drools API

With an understanding of the Drools API descriptions in the previous section, you are ready to follow a conventional set of steps to load a rule resource and make a test. For this exercise, you will load the vote.drl rule resource:
  1. Create a KnowledgeBuilder to add a resource (you will add the vote.drl, but in the same manner you can load a decision table):
    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    kbuilder.add(ResourceFactory.newClassPathResource("vote.drl"), ResourceType.DRL);
  2. Check for potential errors:
    KnowledgeBuilderErrors errors = kbuilder.getErrors();
         if (errors.size() > 0) {
              for (KnowledgeBuilderError error: errors) {
                   System.err.println(error);
              }
              throw new IllegalArgumentException("Could not parse knowledge.");
         }
  3. Create a KnowledgeBase that contains all the relevant process definitions and other knowledge types like rules:
    KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
    kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
  4. You need to create a session to interact with the engine:
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
  5. Obtain a logger for getting the generated events (you will use a file logger, but a console logger is also available):
    KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "log");
  6. Provide a test case to the vote.drl. Here you will provide a Vote instance, but you can adjust this according to your DRL:
    ksession.insert(vote);
    Where, for example, vote is:
    Vote vote = new Vote();
    vote.setAverage(8.4f);
  7. "Fire all rules," so that all the rules from your DRL will be checked against your test case:
    ksession.fireAllRules();
  8. Clean up.
    logger.close();
    ksession.dispose();

Now, you can put everything together in a complete functional application (DroolsTest.java). You can execute this as you would any Java application, as long as the vote.drl and Drools libraries are available.

DroolsTest.java
 
package com.sample;
 
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;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.runtime.StatefulKnowledgeSession;
 
/**
 * 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
               KnowledgeBase kbase = readKnowledgeBase();
               StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
               KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "log");
               
               // go !
               Vote vote = new Vote();
               vote.setAverage(8.4f);
               
               //insert the "vote"
               ksession.insert(vote);
               
               //"fire all rules"
               ksession.fireAllRules();
               
               //clean up
               logger.close();
               ksession.dispose();
               
          } catch (Throwable t) {
               t.printStackTrace();
          }
     }
 
     private static KnowledgeBase readKnowledgeBase() throws Exception {
          KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
          kbuilder.add(ResourceFactory.newClassPathResource("vote.drl"), ResourceType.DRL);
          KnowledgeBuilderErrors errors = kbuilder.getErrors();
          if (errors.size() > 0) {
               for (KnowledgeBuilderError error: errors) {
                    System.err.println(error);
               }
               throw new IllegalArgumentException("Could not parse knowledge.");
          }
          KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
          kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
          return kbase;
     }
 
     public static class Vote {
          
         private String vote;
          private float average;
 
          public String getVote() {
               return this.vote;
          }
 
          public void setVote(String vote) {
               this.vote = vote;
          }
 
          public float getAverage() {
               return this.average;
          }
 
          public void setAverage(float average) {
               this.average = average;
          }
          
     }
 
}

The output, conforming to vote.drl, will be the text "Excellent!"


Tags: Java, JBoss, Drools, Rule engine, Business logic



Page 3 of 4



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel