Chapter 6. Getting Started with Rules and Facts

To create business rules, you need an appropriate fact model on which your business rules will operate. A fact is an instance of an application object represented as a POJO. You then author rules containing the business logic using either the Business Central web interface or your JBoss Developer Studio.
The conditions on the WHEN clause of a rule, query for fact combinations that match it's criteria. So, when a particular set of conditions occur as specified in your rule's WHEN clause, then the specified list of actions in the THEN clause are executed. A rule's action asserts a fact, retracts a fact, or updates a fact on to the Rule engine. As a result, other rules may then be fired.
This is how rules are processed:
  1. BRMS parses all the .drl rule files into the knowledge base.
  2. Each fact is asserted into the working memory. As the facts are asserted, BRMS uses PHREAK or RETE algorithm to infer how the facts relate to the rules. So the working memory now contains a copy of the parsed rules and a reference to the facts.
  3. The fireAllRules() method is called. This triggers all the interactions between facts and rules and the rule engine evaluates all the rules against aal the facts and concludes which rules should be fired against which facts.
  4. All the rule-facts combination (when a particular rule matches against one or more sets of facts), are queued within a data construct called an agenda.
  5. Finally, activations are processed one-by-one from the agenda, calling the consequence of the rule on the facts that activated it. Note that the firing of an activation on the agenda can modify the contents of the agenda before the next activation is fired. The PHREAK or RETE algorithm are used to handle such situatiobs edfficiently.

6.1. Create Your First Rule

In this section, you will learn to create and execute your first rule.
As with most Java applications, you can create a rule in plain Java and that is what we will start with. This will allow you to get comfortable with the idea of using rules without getting distracted with tooling.
Since a lot of developers are more comfortable with using Maven, we will next show you how to create the same rule using Maven.
We will then move on to creating (and executing) the same rule using JBoss Developer Studio with the JBoss BRMS plug-in.
Finally, we will move to creating and executing the same rule in the Business Central environment of JBoss BRMS.
This will help you decide which environment is right for you to learn about rules. Let's get started.

6.1.1. Create and Execute Your First Rule Using Plain Java

Procedure 6.1. Create and Execute your First Rule using plain Java

  1. Create your fact model

    Create a POJO based on which your rule runs. For example, create a Person.java file in a directory called my-project. The Person class contains the getter and setter methods to retrieve and set values of first name, last name, hourly rate, and wage of a person:
    import org.kie.api.KieServices;
    import org.kie.api.runtime.KieContainer;
    import org.kie.api.runtime.KieSession;  
    
      public class Person {
        private String firstName;
        private String lastName;
        private Integer hourlyRate;
        private Integer wage;
           
          public String getFirstName() {
        	  return firstName;
        	}
    
        	public void setFirstName(String firstName) {
        	  this.firstName = firstName;
        	}
    
        	public String getLastName() {
        	  return lastName;
        	}
    
        	public void setLastName(String lastName) {
        	  this.lastName = lastName;
        	}
    
        	public Integer getHourlyRate() {
        	  return hourlyRate;
        	}
    
        	public void setHourlyRate(Integer hourlyRate) {
        	  this.hourlyRate = hourlyRate;
        	}
        		
        	public Integer getWage(){
        	  return wage;
        	}
    
        	public void setWage(Integer wage){
        	  this.wage = wage;
        	}
        }
  2. Create your rule

    Create your rule file in .drl format under my-project directory. Here is the simple rule file called Person.drl, which does a calculation on the wage and hourly rate values and displays a message based on the result.
    dialect "java"
     
    rule "Wage"
    
      when
       
        Person(hourlyRate*wage > 100)
        Person(name : firstName, surname : lastName)
       
      then
        System.out.println( "Hello" + " " + name + " " + surname + "!" );
        System.out.println( "You are rich!" );
    
    end
  3. Create a main class

    Create your main class (say, DroolsTest.java) and save it in the same my-project directory as your POJO. This file will load the knowledge base and fire your rules:
    In the DroolsTest.java file:
    1. Add the following import statements to import the KIE services, container, and session:
      import org.kie.api.KieServices;
      import org.kie.api.runtime.KieContainer;
      import org.kie.api.runtime.KieSession;
    2. Load the knowledge base and fire your rule from the main() method:
      public class DroolsTest {
          public static final void main(String[] args) {
            try {
              // load up the knowledge base
              KieServices ks = KieServices.Factory.get();
              KieContainer kContainer = ks.getKieClasspathContainer();
              KieSession kSession = kContainer.newKieSession();
           
              // go !
              Person p = new Person();
              p.setWage(12);
              p.setFirstName("Tom");
              p.setLastName("Summers");
              p.setHourlyRate(10);
                
              kSession.insert(p);
              kSession.fireAllRules();
              } 
            
            catch (Throwable t) {
              t.printStackTrace();
            }
          }
      }
      The main() method passes the model to the rule, which contains the first name, last name, wage, and hourly rate.
  4. Download the BRMS Engine jar files

    Download the BRMS engine jar files and save them under my-project/BRMS-engine-jars/. These files are available from the Red Hat Customer Portal under the generic deployable version.
  5. Create the kmodule.xml metadata file

    Create a file called kmodule.xml under my-project/META-INF to create the default session. At the minimum, this file contains the following:
    <?xml version="1.0" encoding="UTF-8"?>
    <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
    </kmodule>
  6. Build your example

    Navigate to the my-project directory and execute the following command from the command line:
    javac -classpath "./BRMS-engine-jars/*:." DroolsTest.java
    This will compile and build your java files.
  7. Run your example

    If there were no compilation errors, you can now run the DroolsTest to execute your rule:
    java -classpath "./BRMS-engine-jars/*:." DroolsTest
    The expected output is:
    Hello Tom Summers!
    You are rich!

6.1.2. Create and Execute Your First Rule Using Maven

Procedure 6.2. Create and Execute your First Rule using Maven

  1. Create a basic Maven archetype

    Navigate to a directory of choice in your system and execute the following command:
    mvn archetype:generate -DgroupId=com.sample.app -DartifactId=my-app  -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
    This creates a directory called my-app with the following structure:
    my-app
    |-- pom.xml
    `-- src
        |-- main
        |   `-- java
        |       `-- com
        |           `-- mycompany
        |               `-- app
        |                   `-- App.java
        `-- test
            `-- java
                `-- com
                    `-- mycompany
                        `-- app
                            `-- AppTest.java
    The my-app directory comprises:
    • A src/main directory for storing your application's sources.
    • A src/test directory for storing your test sources.
    • A pom.xml file containing the Project Object Model (POM) for your project. At this stage, the pom.xml file contains the following:
      <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/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.sample.app</groupId>
        <artifactId>my-app</artifactId>
        <packaging>jar</packaging>
        <version>1.0-SNAPSHOT</version>
        <name>my-app</name>
        <url>http://maven.apache.org</url>
        <dependencies>
          <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
          </dependency>
        </dependencies>
      </project>
  2. Create your Fact Model

    Once you are done with the archetype, create a class based on which your rule runs. Create the POJO called Person.java file under my-app/src/main/java/com/mycompany/app folder. This class contains the getter and setter methods to retrieve and set values of first name, last name, hourly rate, and wage of a person.
    package com.mycompany.app;
    
      public class Person {
      
        private String firstName;
        private String lastName;
        private Integer hourlyRate;
        private Integer wage;
    
    
        public String getFirstName() {
          return firstName;
        }
        
        public void setFirstName(String firstName) {
          this.firstName = firstName;
        }
        
        public String getLastName() {
          return lastName;
        }
        
        public void setLastName(String lastName) {
          this.lastName = lastName;
        }
        
        public Integer getHourlyRate() {
          return hourlyRate;
        } 
        
        public void setHourlyRate(Integer hourlyRate) {
          this.hourlyRate = hourlyRate;
        }
        
        public Integer getWage(){
          return wage;
        }
        
        public void setWage(Integer wage){
          this.wage = wage;
        }
                
      }
  3. Create your rule

    Create your rule file in .drl format under my-app/src/main/resources/rules.
    Here is the simple rule file called Person.drl, which imports the Person class:
    package com.mycompany.app;
    import com.mycompany.app.Person;
     
    dialect "java"
     
    rule "Wage"
     
      when
        Person(hourlyRate*wage > 100)
        Person(name : firstName, surname : lastName)
       
      then
        System.out.println( "Hello " + name + " " + surname + "!" );
        System.out.println( "You are rich!" );
        
    end
    As before, this rule does a simple calculation on the wage and hourly rate values and displays a message based on the result.
  4. Create the kmodule.xml metadata file

    Create an empty file called kmodule.xml under my-app/src/main/resources/META-INF to create the default session. This file contains the following:
    <?xml version="1.0" encoding="UTF-8"?>
    <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
    </kmodule>
  5. Set project dependencies in the pom.xml configuration file

    As Maven manages the classpath through this configuration file, you must declare in it the libraries your application requires. Edit the my-app/pom.xml file to set the JBoss BRMS dependencies and setup the GAV values for your application, as shown below:
    <?xml version="1.0" encoding="UTF-8"?>
    <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>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0.0</version>
    <repositories>
      <repository>
        <id>jboss-ga-repository</id>
        <url>http://maven.repository.redhat.com/techpreview/all</url>
      </repository>
    </repositories>
    <dependencies>
      <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-compiler</artifactId>
        <version>LATEST</version>
      </dependency>
      <dependency>
        <groupId>org.kie</groupId>
        <artifactId>kie-api</artifactId>
        <version>LATEST</version>
      </dependency>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
      </dependency>
    </dependencies>
    </project>
  6. Test it!

    After you add the dependencies in the pom.xml file, use the testApp method of the my-app/src/test/java/com/mycompany/app/AppTest.java (which is created by default by Maven) to instantiate and test the rule.
    In the AppTest.java file:
    1. Add the following import statements to import the KIE services, container, and session:
      import org.kie.api.KieServices;
      import org.kie.api.runtime.KieContainer;
      import org.kie.api.runtime.KieSession;
    2. Load the knowledge base and fire your rule from the testApp() method:
      public void testApp() {
      
        // load up the knowledge base
        KieServices ks = KieServices.Factory.get();
        KieContainer kContainer = ks.getKieClasspathContainer();
        KieSession kSession = kContainer.newKieSession();
      
        // set up our Person fact model
        Person p = new Person();
        p.setWage(12);
        p.setFirstName("Tom");
        p.setLastName("Summers");
        p.setHourlyRate(10);
      
        // insert him into the session
        kSession.insert(p);
        
        // and fire all rules on him
        kSession.fireAllRules();
        
        // we can assert here, but the rule itself should output something since the person's wage is more than our baseline rule
      }
      
      The testApp() method passes the model to the rule, which contains the first name, last name, wage, and hourly rate.
  7. Build your example

    Navigate to the my-app directory and execute the following command from the command line:
    mvn clean install
    When you run this command for the first time, it may take a while as Maven downloads all the artifacts required for this project such as JBoss BRMS jar files.
    The expected output is:
    Hello Tom Summers!
    You are rich!
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.194 sec
    
    Results :
    
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    
    [INFO]
    ...
    
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 6.393 s
    ...
    [INFO] ------------------------------------------------------------------------
    
    
That is it! You have run the rule using Maven!

6.1.3. Create and Execute Your First Rule Using JBoss Developer Studio

Procedure 6.3. Create and Execute your First Rule using JBoss Developer Studio

To execute a rule project in JBoss Developer Studio successfully, ensure that you have installed the JBoss BRMS tools plug-in support, and configured the JBoss EAP 6 running BRMS and the BRMS runtime.
  1. Create a BRMS Project.

    1. Start JBoss Developer Studio and navigate to FileNewProject.
      This opens a New Project dialog box.
    2. In the New Project dialog box, select DroolsDrools Project and click Next.
    3. Type a name for your project and click Next.
      The New Project dialog box provides you choice to add some default artifacts to your project, such as sample rules, decision tables and Java classes for them. Let us select the first two check boxes and click Next.
    4. Select the configured BRMS runtime in the Drools Runtime dialog box. If you have not already configured your BRMS runtime, click Configure Workspace Settings... link and configure the BRMS runtime jars.
    5. Select Drools 6.0.x for Generate code compatible with: field and provide values for groupId, artifactId, and version. These values form your project's fully qualified artifact name. Let us provide the following values:
      • groupId: com.mycompany.app
      • artifactId: my-app
      • version: 1.0.0
    6. Click Finish.
      This sets up a basic project structure, classpath and sample rules for you to get started with.
      My-Project
      `-- src/main/java
          |-- com.sample
          |   `-- DroolsTest.java
          |        
       `-- src/main/rules
          | -- Sample.drl
          |                   
        `-- JRE System Library
          |                   
        `-- Drools Library
          |                   
        `-- src
          |                   
        `-- pom.xml
      This newly created project called My-Project comprises the following:
      • A rule file called Sample.drl under src/main/rules directory.
      • An example java file called DroolsTest.java under src/main/java in the com.sample package. You can use the DroolsTest class to execute your rules in the BRMS engine.
      • The Drools Library directory. This acts as a custom classpath container that contains all the other jar files necessary for execution.
  2. Create your fact model

    The sample DroolsTest.java file contains a sample POJO called Message with getter and setter methods. You can edit this class or create another similar POJO. Let us remove this POJO and create a new POJO called Person, which sets and retrieves values of first name, last name, hourly rate, and wage of a person:
    public static class Person {
           	  private String firstName;
           	  private String lastName;
           	  private Integer hourlyRate;
           	  private Integer wage;
           	  
           	  public String getFirstName() {
           	    return firstName;
           	  }
    
           	  public void setFirstName(String firstName) {
           	    this.firstName = firstName;
           	  }
    
           	  public String getLastName() {
           	    return lastName;
           	  }
    
           	  public void setLastName(String lastName) {
           	    this.lastName = lastName;
           	  }
    
           	  public Integer getHourlyRate() {
           	    return hourlyRate;
           	  }
    
           	  public void setHourlyRate(Integer hourlyRate) {
           	    this.hourlyRate = hourlyRate;
           	  }
        		
           	  public Integer getWage(){
           	    return wage;
           	  }
    
           	  public void setWage(Integer wage){
           	    this.wage = wage;
           	  }
  3. Update the main method

    The sample DroolsTest.java file contains a main() method that loads up the knowledge base and fires the rules. Update this main() method to pass the Person object to the rule:
      public static final void main(String[] args) {
          try {
            // load up the knowledge base
              KieServices ks = KieServices.Factory.get();
              KieContainer kContainer = ks.getKieClasspathContainer();
              KieSession kSession = kContainer.newKieSession("ksession-rules");
    
            // go !
              Person p = new Person();
              p.setWage(12);
              p.setFirstName("Tom");
              p.setLastName("Summers");
              p.setHourlyRate(10);
                
              kSession.insert(p);
              kSession.fireAllRules();
                
              } 
            
            catch (Throwable t) {
              t.printStackTrace();
            }
        }

    Note

    To load the knowledge base, you first get the KieServices instance and the classpath based KieContainer. Then you build your KieSession with the KieContainer. Here, we are passing the session name ksession-rules that matches the one defined in kmodule.xml file.
  4. Create your rule

    The sample rule file Sample.drl contains a basic skeleton of a rule. You can edit this file or create a new one to write your own rule.
    In your rule file:
    1. Include the package name:
      package com.sample
      
    2. Import facts into the rule:
      import com.sample.DroolsTest.Person;
    3. Create the rule in "when", "then" format.
      dialect "java"
      
      rule "Wage"
       
          when
            Person(hourlyRate*wage > 100)
            Person(name : firstName, surname : lastName)
         
          then
            System.out.println( "Hello" + " " + name + " " + surname + "!" );
            System.out.println( "You are rich!" );
      
      end
      
  5. Test your rule

    Right-click the DroolsTest.java file and select Run AsJava Application.
Expected output at the console view:
Hello Tom Summers!
You are rich!

6.1.4. Create and Execute Your First Rule Using Business Central

Prerequisite

Ensure that you have successfully installed JBoss BPM Suite before you run this simple rule example using Business Central interface.

Procedure 6.4. Create and Execute your First Rule using Business Central

  1. Login to Business Central

    1. On the command line, move into the $SERVER_HOME/bin/ directory and execute the following command:
      ./standalone.sh
    2. Once your server is up and running, open the following in a web browser:
      http://localhost:8080/business-central
      This opens the Business Central login page.
    3. Log in to the Business Central with the user credentials created during installation.
  2. Create a repository structure and create a project under it

    1. On the main menu of Business Central, go to AuthoringAdministration.
    2. In the displayed Organizational Unit Manager view, click Add.
    3. In the displayed Add New Organizational Unit dialog box, define the unit properties. For example:
      • Name: EmployeeWage
      • Owner: Employee
      Click OK.
    4. On the perspective menu, click RepositoriesNew repository.
    5. In the displayed Create Repository dialog box, define the repository properties. For example:
      • Repository Name: EmployeeRepo
      • Organizational Unit: EmployeeWage
      Click Finish.
    6. Go to AuthoringProject Authoring.
    7. In the Project Explorer, under the organizational unit drop-down box, select EmployeeWage, and in the repository drop-down box select EmployeeRepo.
    8. On the perspective menu, go to New ItemProject.
    9. In the displayed Create new Project dialog box, provide a name (for example, MyProject) for your project properties and click Ok.
    10. In the New Project dialog box, define the maven properties of the Project. For example:
      • Group ID: org.bpms
      • Artifact ID: MyProject
      • Version ID: 1.0.0
      Click Finish.
  3. Create a fact model

    1. On the perspective menu, go to New ItemData Object.
    2. In the displayed Create new Data Object dialog box, provide the values for object name and package. For example:
      • Data Object: Person
      • Package: org.bpms.myproject
      Click Ok.
    3. In the displayed Create new field window of the newly created Person data object, add a variable name in the Id field, select data type for the variable in the Type field. For example:
      • Id: firstName
        Type: String
      • Id: lastName
        Type: String
      • Id: hourlyRate
        Type: Integer
      • Id: wage
        Type: Integer
      Click Create and then Save.
  4. Create a rule

    1. On the perspective menu, click New ItemDRL File.
    2. In the Create new dialog box, provide the name and package name of your rule file. For example:
      • DRL file name: MyRule
      • Package: org.bpms.myproject
      Click Ok.
    3. In the displayed DRL editor with the MyRule.drl file, write your rule as shown below:
      package org.bpms.myproject;
      rule "MyRule"
      ruleflow-group "MyProjectGroup"
        when
         
          Person(hourlyRate*wage > 100)
          Person(name : firstName, surname : lastName)
         
        then
          System.out.println( "Hello" + " " + name + " " + surname + "!" );
          System.out.println( "You are rich!" );
      
      end
    4. Click Save.
  5. Create a Business Process and add a Business Rule Task

    1. On the main menu of Business Central, go to AuthoringProject Authoring.
    2. In the Create new Business Process dialog box, provide values for Business Process name and package. For example:
      • Business Process: MyProcess
      • Package: org.bpms.myproject
      Click Ok
      The Process Designer with the canvas of the created Process definition opens.
    3. Expand the Object Library palette with Process Elements.
      A Start Event element appears on the canvas.
    4. From the Object Library, navigate to Tasks and drag a Business Rule Task to the canvas. Then, integrate the Business Rule task into the process workflow.
    5. Select the Business Rule Task and set the following properties in the Properties panel under Core Properties:
      • Name:Rule_Task
      • DataInputSet
        When you click on the DataInputSet field, an editor for Data Input opens. Click Add Data Input and provide the data input elements. For example:
        • Name:person_Task
        • Defined Types:org.bpms.myproject.Person
          Click Ok.
      • Assigments
        When you click on the Assigments field, an editor for Data Assignments opens. Provide the assignment values here. For example:
        • Assignment Type: DataInput
        • From Object:person_proc
        • Assignment Type: is mapped to
        • To Object:person_Task
        • Ruleflow Group: MyProjectGroup
        Click Ok.
        Now you have successfully created an object that maps to the variables you have set in your fact model. Your business process passes this object as an input to your rule.
      • Click Generate all Forms.
      • Save the Process.
  6. Build and deploy your rule

    1. Open Project Editor and click Build & Deploy.
      A green notification appears in the upper part of the screen informing you that the project has been built and deployed successfully to the Execution Server.
    2. Go to Process ManagementProcess Definitions.
      You can see your newly built process listed in the Process Definitions window.
    3. Click button under Actions to start your Process.
      A MyProcess dialog box opens.
    4. In the MyProcess dialog box, provide the following values of the variables defined in your fact model and click Submit:
      • firstName: Tom
      • hourlyRate: 12
      • lastName: Summers
      • wage: 10
      As these values satisfy the rule condition, the expected output at the console is:
      16:19:58,479 INFO  [org.jbpm.kie.services.impl.store.DeploymentSynchronizer] (http-/127.0.0.1:8080-1) Deployment unit org.bpms:MyProject:1.0 stored successfully
      16:26:56,119 INFO  [stdout] (http-/127.0.0.1:8080-5) Hello Tom Summers!
      16:26:56,119 INFO  [stdout] (http-/127.0.0.1:8080-5) You are rich!