Hi,

Drools is a business rule management system (BRMS) with a forward chaining inference based rules engine. Drools can be called as “Business Logic integration Platform (BLiP)” – the BRMs is dead :) The future is for a unified and integrated solution for Rules, Processes and CEP – this is what users want and this is what we are aiming for.
The best thing here is that “JBoss AS7 executes Drools much faster compared to other So Called Application Servers present in the market, which is needed by an Enterprise”.

Drools 5.0 has splited up into 4 main sub projects, the documentation has already been split to reflect this:
.

Drools Guvnor (BRMS/BPMS)
Drools Expert (rule engine),
Drools Flow (process/workflow)
Drools Fusion (cep/temporal reasoning)

Drools 5.4.0.Beta2 is the current release. It’s new features are mentioned in the following link: http://docs.jboss.org/drools/release/5.4.0.Beta2/droolsjbpm-introduction-docs/html/index.html

In this example we will mainly focus on following points

Point-1). In this example we will see how we can use a Drools 5.3.0.Final inside JBoss AS7 Application Server. This version of Drools can be downloaded from the following link : http://www.jboss.org/drools/downloads

Point-2). How to create a Drools module inside the JBoss AS7 so that the Jars which are provided by the Drools 5.3 will be available for the applications deployed on JBoss AS7.

Point-3). How to use simple Drools rule file and How to create the Drools Engine to execute those rules.

So here we will begin with the steps which can be used to run a drools based application inside JBoss AS7.
The Source code of this Demo is present in the following link:
https://github.com/jaysensharma/MiddlewareMagicDemos

JBoss AS7 Side Drools Module Configurations

Step-1). Here we are using JBoss AS7.1.0 CR1b which can be downloaded from the following link: http://www.jboss.org/jbossas/downloads. We are using “jboss-as-7.1.0.CR1b” in this demo.

Step-2). Download the Drools 5.3.0.Final from the following link “http://www.jboss.org/drools/downloads

Step-3). Extract the downloaded Drools “drools-distribution-5.3.0.Final.zip” (74.6 MB)

Step-4) Create a directory with name “drools/main” inside the JBoss AS7 modules directory “/home/userone/jboss-as-7.1.0.CR1b/modules”

Step-5) Copy and paste all the binaries (JAR) files from “drools-distribution-5.3.0.Final/binaries” and then paste them inside the “/home/userone/jboss-as-7.1.0.CR1b/modules/drools/main”

Step-6) Create a file “module.xml” inside “/home/userone/jboss-as-7.1.0.CR1b/modules/drools/main” as following:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="drools">
  <resources>
    <resource-root path="antlr-2.7.7.jar"/>
    <resource-root path="antlr-3.3.jar"/>
    <resource-root path="antlr-runtime-3.3.jar"/>
    <resource-root path="bcmail-jdk14-138.jar"/>
    <resource-root path="bcprov-jdk14-138.jar"/>
    <resource-root path="commons-collections-3.1.jar"/>
    <resource-root path="dom4j-1.6.1.jar"/>
    <resource-root path="drools-clips-5.3.0.Final.jar"/>
    <resource-root path="drools-compiler-5.3.0.Final.jar"/>
    <resource-root path="drools-core-5.3.0.Final.jar"/>
    <resource-root path="drools-decisiontables-5.3.0.Final.jar"/>
    <resource-root path="droolsjbpm-introduction-docs-5.3.0.Final.jdocbook"/>
    <resource-root path="drools-jsr94-5.3.0.Final.jar"/>
    <resource-root path="drools-persistence-jpa-5.3.0.Final.jar"/>
    <resource-root path="drools-templates-5.3.0.Final.jar"/>
    <resource-root path="drools-verifier-5.3.0.Final.jar"/>
    <resource-root path="ecj-3.5.1.jar"/>
    <resource-root path="ejb3-persistence-1.0.2.GA.jar"/>
    <resource-root path="google-collections-1.0.jar"/>
    <resource-root path="hibernate-annotations-3.4.0.GA.jar"/>
    <resource-root path="hibernate-commons-annotations-3.1.0.GA.jar"/>
    <resource-root path="hibernate-core-3.3.2.GA.jar"/>
    <resource-root path="hibernate-entitymanager-3.4.0.GA.jar"/>
    <resource-root path="itext-2.1.2.jar"/>
    <resource-root path="javassist-3.12.0.GA.jar"/>
    <resource-root path="jsr94-1.1.jar"/>
    <resource-root path="jta-1.1.jar"/>
    <resource-root path="jxl-2.6.10.jar"/>
    <resource-root path="knowledge-api-5.3.0.Final.jar"/>
    <resource-root path="log4j-1.2.14.jar"/>
    <resource-root path="mvel2-2.1.0.drools4.jar"/>
    <resource-root path="persistence-api-1.0.jar"/>
    <resource-root path="slf4j-api-1.6.0.jar"/>
    <resource-root path="stringtemplate-3.2.1.jar"/>
    <resource-root path="xml-apis-1.3.04.jar"/>
    <resource-root path="xmlpull-1.1.3.1.jar"/>
    <resource-root path="xpp3_min-1.1.4c.jar"/>
    <resource-root path="xstream-1.4.1.jar"/>
  </resources>
</module>

Step-7) Now Start your JBoss Profile as following from inside the directory “/home/userone/jboss-as-7.1.0.CR1b/bin”:
./standalone.sh -c standalone-full.xml

NOTE: If you don’t want to follow all the above 7 Steps to create a JBoss Module , then as an alternative you will need to place all the above JARs inside your Application’s “WEB-INF/lib” directory.

Developing Drools Based Application

Step-8). Create a directory somewhere in your file system as “/home/userone/DroolsTest” then create another directory “src” inside the “/home/userone/DroolsTest”.

Step-9). Create a directory with name “drools_lib” inside “/home/userone/DroolsTest” Just to place all the Jars of drools here. Copy and paste all the Jars from “drools-distribution-5.3.0.Final/binaries” to “home/userone/DroolsTest/drools_lib”. This step is just required to set the classpath in our ANT.

Step-10). Write a simple program “Message.java” as following inside the directory “/home/userone/DroolsTest/src”:

package test;
public class Message
  {
    public static final int HELLO   = 0;
    public static final int GOODBYE = 1;

    private String          message;
    private int             status; 

    public void setMessage(String message)
     {
         this.message=message;
         System.out.println("[Message] 'setMessage' method called with message : "+message);
     }
    public void setStatus(int status)
     {
         this.status=status;
         System.out.println("[Message] 'setStatus' method called with status : "+status);
     }
    public int getStatus()
     {
         System.out.println("[Message] 'getStatus' method called retuning status : "+status);
         return status;
     }
    public String getMessage()
     {
         System.out.println("[Message] 'getMessage' method called retuning message : "+message);
         return message;
     }
  }

Step-11). Write a simple Drools rule file “testRule.drl” as following inside the directory “/home/userone/DroolsTest/src”:

package rules
import test.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

Step-12). Write the Rule Engine program “MyRuleEngine.java” as following inside the directory “/home/userone/DroolsTest/src”

package engine;
import test.Message;

import java.io.IOException;
import org.drools.KnowledgeBase;
import org.drools.builder.KnowledgeBuilder;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;

public class MyRuleEngine
  {
    /**
     * Creates a Drools KnowledgeBase and adds the given rules file into it
     */
    private static KnowledgeBase createKnowledgeBase( final String rulesFile ) {
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add( ResourceFactory.newClassPathResource( rulesFile ), ResourceType.DRL );
        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
        return kbase;
    }

    /**
     * Creates a Drools Stateful Knowledge Session
     */
    private static StatefulKnowledgeSession createKnowledgeSession( final KnowledgeBase kbase ) {
        final StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        return ksession;
    }

     public static void executeRuleEngile(String rulesFile,String userInput) throws Exception
       {
          KnowledgeBase kbase = createKnowledgeBase(rulesFile);
          StatefulKnowledgeSession ksession = createKnowledgeSession(kbase);

          Message message = new Message();
          message.setMessage(userInput);
          message.setStatus(Message.HELLO);
          ksession.insert(message);

          ksession.fireAllRules();
          ksession.dispose();
       }
  }

Step-13). Write a simple Servlet3.0 to invoke the rule engine “DroolsInvokerServlet.java” as following inside the directory “/home/userone/DroolsTest/src”:

package servlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;

@WebServlet(value="/DroolsInvokerServlet")
public class DroolsInvokerServlet extends HttpServlet
  {
     public void service(HttpServletRequest req,HttpServletResponse res) throws ServletException,IOException
       {
            PrintWriter out=res.getWriter();
            System.out.println("[DroolsInvokerServlet] Inside service() of DroolsInvokerServlet.");
            try
             {
               String ruleFile = "testRule.drl";
               System.out.println("[DroolsInvokerServlet] ruleFile = "+ruleFile);
               engine.MyRuleEngine.executeRuleEngile(ruleFile,"Hello World");
               out.println("Check JBoss Console for the Output of Drools Execution.");
             }
            catch(Exception e)
             {
                 System.out.println("[DroolsInvokerServlet] throws Exception: "+e);
                 e.printStackTrace();
             }
            System.out.println("Exiting service() of DroolsInvokerServlet.");
       }
  }

Step-14). Now we will just write a simple “index.jsp” file to invoke the above Servlet as following inside the directory “/home/userone/DroolsTest/src”:

<html>
  <head>
      <title>Drools Demo App</title>
  </head>
  <body>
      <center><h2>
         <a href="DroolsInvokerServlet">Click Here to hit the DroolsInvokerServlet</a>
      </h2></center>
  </body>
</html>

Step-15). Now we will write simple ANT build script “build.xml” which will build / deploy our Drools based application as following inside the directory “/home/userone/DroolsTest”:

<project name="RuleEngine_DroolsProject" default="deploy">
<property name="current.dir" value="." />
<property name="jboss.home" value="/home/userone/jboss-as-7.1.0.CR1b" />
<property name="drools.jar.dir" value="${current.dir}/drools_lib" />
<property name="jboss.module.dir" value="${jboss.home}/modules" />

<property name="basedir" value="." />
<property name="tmp.dir" value="tmp" />
<property name="output.dir" value="build" />
<property name="src.dir" value="src" />
<property name="war.name" value="DroolsHelloWorldDemo.war" />

        <path id="jboss.classpath">
           <fileset dir="${jboss.module.dir}">
              <include name="**/*.jar"/>
           </fileset>
           <fileset dir="${drools.jar.dir}">
              <include name="**/*.jar"/>
           </fileset>
        </path>

        <target name="init">
           <delete dir="${output.dir}" />
           <mkdir dir="${output.dir}" />
           <delete dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}" />
        </target>

        <target name="build" depends="init">
           <mkdir dir="${tmp.dir}/WEB-INF/lib"/>
           <mkdir dir="${tmp.dir}/WEB-INF/classes"/>
           <mkdir dir="${tmp.dir}/META-INF"/>

           <copy file="${src.dir}/index.jsp" tofile="${tmp.dir}/index.jsp"/>
           <copy file="${src.dir}/testRule.drl" todir="${tmp.dir}/WEB-INF/classes"/>
           <javac srcdir="${src.dir}" destdir="${tmp.dir}/WEB-INF/classes"  includes="*.java" classpathref="jboss.classpath"/>

           <!-- NOTE: we are creating a JAR which contains the  "testRule.drl" and the "engine.MyRuleEngine" class -->
           <jar jarfile="${tmp.dir}/WEB-INF/lib/MyDroolsApp.jar" basedir="${tmp.dir}/WEB-INF/classes" compress="true" />

           <copy todir="${tmp.dir}/WEB-INF">
                <fileset dir="${src.dir}">
                  <include name="*.java"/>
                </fileset>
           </copy>
           <delete dir="${tmp.dir}/WEB-INF/classes" />

           <!-- MOST IMPORTANT PART== Copy all the drools related Jars inside "WEB-INF/lib" If You don't want to create a JBoss Module
           <copy todir="${tmp.dir}/WEB-INF/lib">
                <fileset dir="${drools.jar.dir}/">
                  <include name="*.jar"/>
                </fileset>
           </copy>
           -->

           <jar jarfile="${tmp.dir}/${war.name}" basedir="${tmp.dir}"  compress="true" >
              <manifest>
                 <!-- Make Sure that the [Dependencies: drools] is added in the ${war.name}/META-INF/MANIFEST.MF file -->
                 <attribute name="Dependencies" value="drools"/>
              </manifest>
           </jar>

           <copy file="${tmp.dir}/${war.name}" tofile="${output.dir}/${war.name}"/>
           <delete includeEmptyDirs="true">
              <fileset dir="${tmp.dir}"/>
           </delete>
        </target>

        <target name="deploy" depends="build">
            <echo message="*******************  Deploying the WAR file ${war.name} *********************" />
            <echo message="********** ${output.dir}/${war.name} to ${jboss.home}/standalone/deployments **********" />
            <copy todir="${jboss.home}/standalone/deployments/">
                <fileset dir="${output.dir}/">
                  <include name="${war.name}"/>
                </fileset>
            </copy>
            <echo message="*******************  Deployed Successfully   *********************" />
        </target>
</project>

NOTE: The only change in the above file you need to do is to change the “jboss.home” directory path in the second line of the above script to point to your own JBoss AS7 directory.

Step-16). Now before running your ANT script to build and deploy the above webapplication you should have the ANT as well as JAVA set in the $PATH variable of the Shell / command prompt as following:

For Unix Based OS:
export PATH=/home/userone/jdk1.6.0_21/bin:/home/userone/org.apache.ant_1.6.5/bin:$PATH

For Windows Based OS:
set PATH=C:/jdk1.6.0_21/bin;C:/org.apache.ant_1.6.5/bin;%PATH%

Step-17). Now once the PATH is set In the command/Shell prompt you can move inside the directory “/home/userone/DroolsTest” and then run the ant to build and deploy the Drools based application on your JBoss Standalone full profile, by running the command “ant deploy”

[userone@localhost DroolsTest]$ ant deploy
Buildfile: build.xml

init:
   [delete] Deleting directory /home/userone/DroolsTest/build
    [mkdir] Created dir: /home/userone/DroolsTest/build
   [delete] Deleting directory /home/userone/DroolsTest/tmp
    [mkdir] Created dir: /home/userone/DroolsTest/tmp

build:
    [mkdir] Created dir: /home/userone/DroolsTest/tmp/WEB-INF/lib
    [mkdir] Created dir: /home/userone/DroolsTest/tmp/WEB-INF/classes
    [mkdir] Created dir: /home/userone/DroolsTest/tmp/META-INF
     [copy] Copying 1 file to /home/userone/DroolsTest/tmp
     [copy] Copying 1 file to /home/userone/DroolsTest/tmp/WEB-INF/classes
    [javac] Compiling 3 source files to /home/userone/DroolsTest/tmp/WEB-INF/classes
      [jar] Building jar: /home/userone/DroolsTest/tmp/WEB-INF/lib/MyDroolsApp.jar
     [copy] Copying 3 files to /home/userone/DroolsTest/tmp/WEB-INF
   [delete] Deleting directory /home/userone/DroolsTest/tmp/WEB-INF/classes
      [jar] Building jar: /home/userone/DroolsTest/tmp/DroolsHelloWorldDemo.war
     [copy] Copying 1 file to /home/userone/DroolsTest/build

deploy:
     [echo] *******************  Deploying the WAR file DroolsHelloWorldDemo.war *********************
     [echo] ********** build/DroolsHelloWorldDemo.war to /home/userone/jboss-as-7.1.0.CR1b/standalone/deployments **********
     [copy] Copying 1 file to /home/userone/jboss-as-7.1.0.CR1b/standalone/deployments
     [echo] *******************  Deployed Successfully   *********************

BUILD SUCCESSFUL
Total time: 2 seconds

As soon as the WebService will be deployed on the JBoss AS7 you will see the following kind of output on your JBoss Console (STDOUT):


00:44:44,849 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-3) Stopped deployment DroolsHelloWorldDemo.war in 84ms
00:44:44,850 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-3) Starting deployment of "DroolsHelloWorldDemo.war"
00:44:44,913 INFO  [org.jboss.web] (MSC service thread 1-4) registering web context: /DroolsHelloWorldDemo
00:44:44,926 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018565: Replaced deployment "DroolsHelloWorldDemo.war" with deployment "DroolsHelloWorldDemo.war"

Step-18). Now we will try to access the Drools based application from the following URL:

http://localhost:8080/DroolsHelloWorldDemo/DroolsInvokerServlet

As soon as you will hit the above URL in the browser you will see that the rule got executed and the following kind of output you will see in the JBoss AS7 Console.

00:44:49,298 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) [DroolsInvokerServlet] Inside service() of DroolsInvokerServlet.
00:44:49,298 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) [DroolsInvokerServlet] ruleFile = testRule.drl
00:44:49,335 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) [Message] 'setMessage' method called with message : Hello World
00:44:49,335 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) [Message] 'setStatus' method called with status : 0
00:44:49,336 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) [Message] 'getStatus' method called retuning status : 0
00:44:49,336 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) [Message] 'getStatus' method called retuning status : 0
00:44:49,337 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) [Message] 'getMessage' method called retuning message : Hello World
00:44:49,338 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) Hello World
00:44:49,338 INFO  [stdout] (http-localhost-127.0.0.1-8080-3) Exiting service() of DroolsInvokerServlet.

Some Issues you may face

POINTER-A You may see a NullPointerException while loading the “testRule.drl” file inside your RuleEngine class. So to avoid that issue you should always place the Rule Engine class “engine.MyRuleEngine” and “testRule.drl” inside the same JAR file.

POINTER-B while using jboss module dependencies, If you see any ClassNotFoundException while invoking the Rules, which means the Drools classes are not loaded by JBoss or those jars are not available for your Application. So to avoid this issue better make sure that your WAR file has the right dependencies defined inside the “${WAR.FILE}/META-INF/MANIFEST.MF” as following:

Dependencies: drools

Where “drools” is the name of the module which we created in First 7 Steps of this article.

.
.
Thanks :)
Middleware Magic Team