Back to the basics #1: Getting Started with Drools 6.3.0.Final

I was creating some material for my next Workshop in South America when I thought, let’s create some blog posts about the main topics, so I can share with all of you some basic tutorials that should help you to get started with the latest version of Drools. In this short post I will show how to create a very simple Drools enabled Maven project. I will also be using the CDI capabilities provided by Drools 6.3.0.Final.

Pre Requisites

In order to get started you need to have the following already installed in your environment:

  • Java JDK 1.7 +
  • Maven 3.2.3 +

Creating a Maven Project

(You can find the sources of this project here: https://github.com/Salaboy/drools-workshop/)

Let’s start simple, let’s create a Maven empty project by using the following Maven Goal:

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart

This will create a new maven empty project by asking you the basic information about GroupId, ArtifactId and Version

  • Define value for property ‘groupId’: : org.drools.workshop
  • Define value for property ‘artifactId’: : my-first-drools-project
  • Define value for property ‘version’:  1.0-SNAPSHOT: : <hit enter>
  • Define value for property ‘package’:  org.drools.workshop: : <hit enter>

Then you will see

  • Confirm properties configuration:
  • groupId: org.drools.workshop
  • artifactId: my-first-drools-project
  • version: 1.0-SNAPSHOT
  • package: org.drools.workshop
  • Y: : <hit enter>

After this the project will be create and ready to be opened in your favourite IDE. The project structure will look like this:

Maven Project Structure
Maven Project Structure

We now need to update the pom.xml file to add the specific drools dependencies. Notice that Drools 6.3.0.Final is already in the central maven repository so no need of adding an extra repository. The pom file after editing should look like this:

<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>org.drools.workshop</groupId>
 <artifactId>my-first-drools-project</artifactId>
 <version>1.0-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>my-first-drools-project</name>
 <url>http://salaboy.com</url>

 <properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 <kie.version>6.3.0.Final</kie.version>
 <junit.version>4.11</junit.version>
 <cdi.version>1.2</cdi.version>
 <weld.version>2.3.0.Final</weld.version>
 </properties>

 <dependencies>
 <dependency>
 <groupId>org.kie</groupId>
 <artifactId>kie-api</artifactId>
 <version>${kie.version}</version>
 </dependency>
 <dependency>
 <groupId>org.drools</groupId>
 <artifactId>drools-compiler</artifactId>
 <version>${kie.version}</version>
 </dependency>
 <dependency>
 <groupId>org.drools</groupId>
 <artifactId>drools-core</artifactId>
 <version>${kie.version}</version>
 </dependency>
 <dependency>
 <groupId>javax.enterprise</groupId>
 <artifactId>cdi-api</artifactId>
 <version>${cdi.version}</version>
 </dependency>
 <dependency>
 <groupId>org.jboss.weld.se</groupId>
 <artifactId>weld-se-core</artifactId>
 <version>${weld.version}</version>
 </dependency>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>${junit.version}</version>
 <scope>test</scope>
 </dependency>
 </dependencies>
</project>

At this point I’ve deleted the Junit Test generated by the Archetype that was based on JUnit 3.x. Once we get our dependencies in place we can start using Drools straight away.

Bootstrapping the Rule Engine using CDI

Let’s go to the App.java class that was generated automatically by the Maven Archetype. First of all we need to bootstrap CDI. CDI stands for Context and Dependency Injection and it is basically a standard set of APIs that allows us to benefit from the power of Dependency Injection inside our applications. Because CDI is only a set of APIs we need also to provide an implementation of these interfaces and that’s why we specified weld-se-core as our CDI container. Weld is the CDI reference implementation, but in theory you can use any other CDI implementation.

Our App.java class should look like this now:

package org.drools.workshop;

import javax.inject.Inject;
import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;
import org.kie.api.cdi.KSession;
import org.kie.api.runtime.KieSession;

/**
 * Hello Drools world!
 *
 */
public class App {

 @Inject
 @KSession()
 private KieSession kSession;

 public void bootstrapDrools() {
   // The KieSession was injected so we can use it now
   kSession.insert("Hi There!");
   int rulesFired = kSession.fireAllRules();
   System.out.println("Rules Fired: "+rulesFired);
 }

 public static void main(String[] args) {
   //Boostrap the CDI container, in this case WELD
   Weld w = new Weld();

   WeldContainer wc = w.initialize();
   App app = wc.instance().select(App.class).get();
   app.bootstrapDrools();

   w.shutdown();
 }
}

The main(…) method is bootstrapping Weld and then calling our App.boostrapDrools() method. Because CDI (Weld) is creating the instance of our class App it is able to Inject a new instance of our KieSession. Inside the bootstrapDrools() method we can start using it straight away. Before running this class we still need to add some important things such as our Rules!

Creating our First DRL File

In order to run this class we still need to add three more things. First and mostly important, our rules! So let’s go and create a new “drl” file under the src/main/resources/ directory (yes you need to create this directory). Let’s call it rules.drl:

Screen Shot 2015-10-20 at 16.16.22

Inside this file we can add a very simple rule:


package org.drools.workshop;

rule "My First Drools Rule"
  when
    $o: Object()
  then
    System.out.println("Rule Fired for Object: "+$o.toString());
end

Finally, we need two configuration files listed in the previous screenshot:

  • beans.xml: this is required by CDI, so the container knows that this jar should be scanned so the classes inside can be Injected
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
    </beans>
    
  • kmodule.xml: this file is used by Drools to scan the jar for rules. Here we can configure multiple KieSession and KieBases if we need to separate our rules. For this simple example we will use all the defaults
    <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    </kmodule>
    
    

Now you have set up a new Rule Engine instance with our very simple rule and it is ready to be used.

Running our Application

As you notice we have a very simple Maven Project with a main class ready to be executed. First of all we should build and package the project. We achieve this by executing the following command:


mvn clean install

You should get a BUILD SUCCESS at the end of the execution. If not please post a comment here, I will try to help you.

Because we are using maven, we can leverage the fact that maven will load all the dependencies of our application in the class path for us and run the application by using the following command in the terminal:


mvn exec:java -Dexec.mainClass="org.drools.workshop.App"

After the execution you should be able to see something like this in the output:


Oct 20, 2015 4:37:59 PM org.jboss.weld.environment.se.WeldContainer initialize

INFO: WELD-ENV-002003: Weld SE container STATIC_INSTANCE initialized

<strong>Rule Fired for Object: Hi There!</strong>

<strong>Rules Fired: 1</strong>

Oct 20, 2015 4:38:00 PM org.jboss.weld.environment.se.WeldContainer shutdown

Our Rule Fired!

Summary

We have seen how to create a Drools project from the scratch using Maven. We also look at how to use CDI (and Weld) to create our KieSession (Rule Engine instances) for us. I strongly recommend you opening the project in your favourite IDE and start playing around with Drools.

In my next post I will show you how to add a JUnit test to our project, so you can write more serious rules! And we will continue adding more complex rules to it.

If you have any questions or doubts get in touch!

Advertisements

30 thoughts on “Back to the basics #1: Getting Started with Drools 6.3.0.Final”

  1. Hi Mauricio, really interesting topics,

    I have a doubt about when we need kjar for the rules vs jar like your example. Can you please clarify when use one or other?

    Like

    1. A KJAR is a normal Java Jar Package with an extra kmodule.xml file inside the META-INF/ directory. This is used by drools to identify which JARs contains rules or business processes and the content of the kmodule.xml is used to configure your KieSessions and KieBases. Does it make sense? If not please elaborate your question, which Jar are you referring to?

      Like

      1. Hello, thanks for the reply.

        I’m referring to the jar of your example, you use jar that makes the things really simple (because doesn’t need to configure repositories in maven configuration).

        If I don’t misunderstand it, your example is really equal to a kjar because have in the META-INF/ directory the kmodule.xml file, isn’t it?

        Then my question is when we need to use jar or kjar or are equals if the resulting jar, in the first case, have the kmodule.xml in the META-INF/ directory

        Like

  2. Rafa,
    Yeah, I think that you are overthinking about what a KJAR is. Basically a KJAR is just a simple Jar with a kmodule.xml file. The main advantage of moving our rules to a KJAR where the only thing that we have in there are our rules is that as you will see in my other posts, you can use KIE CI to load those KJARs. This enable you to separate your rules from your application artefacts. If you have a very very simple Drools project you can have the rules inside it, as I’m showing here. But as soon as the project grows you will notice that in order to change your rules you will need to repackage your whole application, and sometimes that will be too much work.
    Does it make more sense now?

    Like

  3. Hi, very interesting and very well explained !
    I was able to run it, but then tried to deploy it using WildFly9 that got following errors, can you help me trying to understand what is happening ? Thanks

    11:46:08,860 INFO [org.drools.compiler.kie.builder.impl.ClasspathKieProject] (ServerService Thread Pool — 58) Found kmodule: vfs:/C:/Users/Antonio/Tools/wildfly-9.0.2.Final/standalone/deployments/WebServices.war/WEB-INF/lib/BusinessRules-1.0-SNAPSHOT.jar/META-INF/kmodule.xml
    11:46:08,861 INFO [org.drools.compiler.kie.builder.impl.ClasspathKieProject] (ServerService Thread Pool — 58) Virtual file physical path = C:\Users\Antonio\Tools\wildfly-9.0.2.Final\standalone\deployments\WebServices.war\WEB-INF\lib\BusinessRules-1.0-SNAPSHOT.jar
    11:46:08,977 ERROR [org.drools.compiler.kie.builder.impl.ClasspathKieProject] (ServerService Thread Pool — 58) Unable to load pom.properties from C:\Users\Antonio\Tools\wildfly-9.0.2.Final\standalone\deployments\WebServices.war\WEB-INF\lib\BusinessRules-1.0-SNAPSHOT.jar
    C:\Users\Antonio\Tools\wildfly-9.0.2.Final\standalone\deployments\WebServices.war\WEB-INF\lib\BusinessRules-1.0-SNAPSHOT.jar (Access is denied)
    11:46:08,977 ERROR [org.drools.compiler.kie.builder.impl.ClasspathKieProject] (ServerService Thread Pool — 58) Unable to build index of kmodule.xml url=vfs:/C:/Users/Antonio/Tools/wildfly-9.0.2.Final/standalone/deployments/WebServices.war/WEB-INF/lib/BusinessRules-1.0-SNAPSHOT.jar/META-INF/kmodule.xml
    null

    Like

  4. I am struggling a bit with this, very new to drools and java environment in general, although I normally get most things right.

    I am using latest version of all but as soon as I try to lunch the demo presented here as is I get some errors.

    Running it on eclipse 4.6 I get:

    Exception in thread “main” java.lang.NoClassDefFoundError: org/jboss/weld/security/GetSystemPropertyAction
    at org.jboss.weld.environment.se.Weld.isEnabled(Weld.java:904)
    at org.jboss.weld.environment.se.Weld.initialize(Weld.java:565)
    at ar.uba.fi.fallas.App.main(App.java:31)
    Caused by: java.lang.ClassNotFoundException: org.jboss.weld.security.GetSystemPropertyAction

    By executing with maven, I get:

    java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:294)
    at java.lang.Thread.run(Thread.java:745)
    Caused by: java.lang.NoClassDefFoundError: javax/enterprise/inject/UnsatisfiedResolutionException
    at ar.uba.fi.fallas.App.main(App.java:29)
    … 6 more
    Caused by: java.lang.ClassNotFoundException: javax.enterprise.inject.UnsatisfiedResolutionException
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    … 7 more

    As if weld is not even found.

    I am on osx and installed with homebrew. Thoughts/help?

    BTW, I am from Buenos Aires, nice you’ve been here.

    Like

    1. Hola Ariel,
      Podemos hacerlo en espaniol entonces (yo soy originalmente de Mendoza).
      Ok primero que nada, tenes que aprender a diferenciar los errores. Has trabajado con Maven antes?

      Te recomendaria primero instalar maven y desde la terminal asegurarte que podes correr: mvn clean install -DskipTests
      Esto compila, empaqueta, e instala los artefactos maven en tu entorno local. Si eso funciona, al menos puedes verificar que tienes la version de Java y Maven correcta en tu entorno.

      Una vez que esto funciona, tenes que entender el IDE que estas usando, en este caso ecplise y como el mismo integra con Maven (en este caso).

      Luego todo llega a analizar las stack traces, como podras ver en el segundo error esta en una clase que has creado en tu proyecto: at ar.uba.fi.fallas.App.main(App.java:29) y por lo tanto es imposible adivinar que estas haciendo en esa clase como para ayudarte.
      Por el tipo y la clase mencionada en el error (javax/enterprise/inject/UnsatisfiedResolutionException) suena a que no tienes una JDK instalada (o probablemente una antigua), tenes que revisar que estes con JDK 8 y que tu IDE la tiene registrada.

      Abrazo

      Like

      1. Genial, gracias!!

        No tengo mucha experiencia con el entorno java ni con Maven, excepto por algún trabajo corto o modificar algo hecho, pero en sí estoy cómodo con cualquier toolset.

        Mi app es tal cual la de este ejemplo y ese error (ar.uba.fi.fallas.App.main(App.java:29) es la primer línea del main:
        Weld w = new Weld();

        mvn clean install funciona bien, y seguí todos los pases que describiste acá.

        La parte del IDE es secundaria, lo puedo ver después igual estoy casi seguro que la versión de Java linkeada es la correcta, pero me interesa tenerlo aunqusea corriendo bien con maven.

        # mvn –version Mon Jul 18 09:03:50 2016
        Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T13:41:47-03:00)
        Maven home: /usr/local/Cellar/maven/3.3.9/libexec
        Java version: 1.8.0_77, vendor: Oracle Corporation
        Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/jre
        Default locale: en_US, platform encoding: UTF-8
        OS name: “mac os x”, version: “10.11.5”, arch: “x86_64”, family: “mac”

        Mi sospecha, es por algún motivo, o la inyección de dependencia esta fallando o por algún motivo no encuentra bien las cosas en classpath. Hoy voy intentar seguir, una lástima trabarse tan al comienzo.

        Muchas Grcacias!!!

        Like

      2. Si el problema Es que weld cuando esta levantando no encuentra cosas en el classpaht y eso Es porque 1) no encuentra clases de la jdk o 2) porque en tu app en el classpath no esta definiendo todo lo necesario para que weld funcione. Maven soluciona todo eso, pero si tu IDE no esta configurando el proyecto para funcionar con maven eso nunca va a correr

        Like

      3. Pero no estoy usando el IDE. Lo probé como alternativa, pero lo estoy haciendo con maven desde línea de comando, todo tal caul está en esta página. Alguna idea? Hice todo como está acá, crear el proyecto maven, editar el pom.txt. Los archivos rules.dsl, beans.xml y kmodule.xml, pero no consigo que mvn exec:java -Dexec.mainClass=”Myapp” funcione.

        Like

      1. Y ahora en pastebin.com el output completo de correr mvn exec:java -Dexec.mainClass=”Myapp”

        al igual que java -version y mvn -version

        Like

      2. Regenere todo otra vez, desde cero, y ahora extrañamente, tira otro error, el que me tiraba antes en el IDE.

        Caused by: java.lang.NoClassDefFoundError: org/jboss/weld/security/GetSystemPropertyAction
        at org.jboss.weld.environment.se.Weld.isEnabled(Weld.java:904)
        at org.jboss.weld.environment.se.Weld.initialize(Weld.java:565)
        at ar.uba.fi.fallas.App.main(App.java:31)

        Igual esta todo lo que me pediste:

        http://pastebin.com/9WKzx7gF

        Y si te interesa:

        https://github.com/hanoii/7567-fallas-2016c1

        Gracias de nuevo!

        Like

      3. Genere todo desde cero, y ahora, extrañamente, me tira otro error:

        Caused by: java.lang.NoClassDefFoundError: org/jboss/weld/security/GetSystemPropertyAction
        at org.jboss.weld.environment.se.Weld.isEnabled(Weld.java:904)
        at org.jboss.weld.environment.se.Weld.initialize(Weld.java:565)
        at ar.uba.fi.fallas.App.main(App.java:31)

        2 líneas más abajo.

        Igual corrí todo lo que me pediste:

        http://pastebin.com/9WKzx7gF

        Y el código es este:

        https://github.com/hanoii/7567-fallas-2016c1.

        Muchas gracias de nuevo!!

        Like

      4. Probé de todo, acá quise usar las últimas versiones, pero si uso 2.3.0 me da otro error:

        http://pastebin.com/WET3tNsD

        Caused by: java.lang.NoClassDefFoundError: com/google/common/base/Function
        at org.jboss.weld.bootstrap.WeldBootstrap.(WeldBootstrap.java:54)
        at org.jboss.weld.environment.se.Weld.initialize(Weld.java:524)
        at ar.uba.fi.fallas.App.main(App.java:31)

        Que raro, avisame si te estoy volviendo loco.. y muchas gracias por el tiempo.. Yo sigo viendo que puede ser, pero raro que una app tan sencilla no corra de una.

        Lo corrí con -X
        http://pastebin.com/Wt1CfJzP

        Like

      5. Yo acabo de clonar y correr tu codigo en mi entorno y todo corre como deberia. Hay algo raro ahi que esta molestando.
        Yo tengo una version de Maven un poco mas antigua pero eso no deberia molestar tampoco (Apache Maven 3.2.5).

        Pregunta.. despues de cambiar la version de weld, corriste mvn clean install ? Suena a quede que tengas corrupto tu .m2/repository, lo cual puede causar que clases que deberian estar ahi no esten. Es un problema que suele suceder muy esporadicamente, pero cada tanto aparece.
        Yo probaria con: rm -rf ./m2/repository/com/google y rm -rf ./m2/repository/org/jboss y luego corres mvn clean install para que baje nuevamente todas las dependencias.

        Like

      6. Genio! Está corriendo!

        Sí, había hecho mvn clean install, pero se ve que no hace demasiada diferencia.

        Hice lo que me dijiste y tiró otro error, algo distinto de Weld y unas dependencias. Entonces directamente borré todo el ~/.m2/repository y después de un mvn clean install, corrió bien!

        Definitivamente un buen dato para saber que el repositorio de maven puede quedar fuera de sincronía.

        Gracias! Ahora a ver de empezar con algo de drools!

        Like

      7. Y solo a título informativo, acabo de hacer lo mismo con Weld 2.3.5.Final, lo de borrar el repositorio de maven entero y volver a correr mvn clean install y mvn exec:java y también funcionó! En fin.. gracias de nuevo!

        PD: Tal vez amerita un pequeño update en el blog post haciendo referencia a esto, como TIP o algo, le puede ahorrar algo de tiempo al próximo!

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s