The Price of all “Rest with Spring” course packages will increase by $50 next Friday:

>>> GET ACCESS NOW

1. Overview

Drools is a Business Rule Management System (BRMS) solution. It provides a rule engine which processes facts and produces output as a result of rules and facts processing. Centralization of business logic makes it possible to introduce changes fast and cheap.

It also bridges the gap between the Business and Technical teams by providing a facility for writing the rules in a format which is easy to understand.

2. Maven Dependencies

To get started with Drools, we need to first add a couple of dependencies in our pom.xml:

<dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-ci</artifactId>
    <version>7.1.0.Beta1</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-decisiontables</artifactId>
    <version>7.1.0.Beta1</version>
</dependency>

The latest version of both dependencies is available on Maven Central Repository as kie-ci and drools-decisiontables.

 3. Drools Basics

We are going to look at basic concepts of Drools:

  • Facts – represents data that serves as input for rules
  • Working Memory –  a storage with Facts, where they are used for pattern matching and can be modified, inserted and removed
  • Rule – represents a single rule which associates Facts with matching actions. It can be written in Drools Rule Language in the .drl files or as Decision Table in an excel spreadsheet
  • Knowledge Session – it holds all the resources required for firing rules; all Facts are inserted into session, and then matching rules are fired
  • Knowledge Base – represents the knowledge in the Drools ecosystem, it has the information about the resources where Rules are found, and also it creates the Knowledge Session
  • Module – A module holds multiple Knowledge Bases which can hold different sessions

4. Java Configuration 

To fire rules on a given data, we need to instantiate the framework provided classes with information about the location of rule files and the Facts:

4.1. KieFileSystem

First, we need to set the KieFileSystem bean; this is an in-memory file system provided by the framework. Following code provides the container to define the Drools resources like rules files, decision tables, programmatically:

public KieFileSystem kieFileSystem() throws IOException {
    KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
        for (Resource file : getRuleFiles()) {
            kieFileSystem.write(
              ResourceFactory.newClassPathResource(RULES_PATH + file.getFilename(), "UTF-8"));
        }
        return kieFileSystem;
}

Here RULES_PATH denotes the location of rule files on the file system. Here we are reading the files from classpath which is typically /src/main/resources in case of a Maven project.

4.2. KieContainer

Next, we need to set the KieContainer which is a placeholder for all the KieBases for particular KieModule. KieContainer is built with the help of other beans including KieFileSystem, KieModule, and KieBuilder.

The buildAll() method invoked on KieBuilder builds all the resources and ties them to KieBase. It executes successfully only when it’s able to find and validate all of the rule files:

public KieContainer kieContainer() throws IOException {
    KieRepository kieRepository = getKieServices().getRepository();

    kieRepository.addKieModule(new KieModule() {
        public ReleaseId getReleaseId() {
            return kieRepository.getDefaultReleaseId();
        }
    });

    KieBuilder kieBuilder = getKieServices()
      .newKieBuilder(kieFileSystem())
      .buildAll();
    

    return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());
}

4.3. KieSession

The rules are fired by opening a KieSession bean – which can be retrieved from KieContainer:

public KieSession kieSession() throws IOException {
    return kieContainer().newKieSession();
}

5. Implementing Rules

Now that we’re done with the setup, let’s have a look at a couple of options for creating rules.

We’ll explore the rule implementation by an example of categorizing an applicant for a specific role, based on his current salary and number of years of experience he has.

5.1. Drools Rule File (.drl)

Simply put, the Drools rule file contains all business rules.

A rule includes a When-Then construct, here the When section lists the condition to be checked, and Then section lists the action to be taken if the condition is met:

package com.baeldung.drools.rules;

import com.baeldung.drools.model.Applicant;

global com.baeldung.drools.model.SuggestedRole suggestedRole;

dialect  "mvel"

rule "Suggest Manager Role"
    when
        Applicant(experienceInYears > 10)
        Applicant(currentSalary > 1000000 && currentSalary <= 
         2500000)
    then
        suggestedRole.setRole("Manager");
end

This rule can be fired by inserting the Applicant and SuggestedRole facts in KieSession:

public SuggestedRole suggestARoleForApplicant(
    Applicant applicant,SuggestedRole suggestedRole){
    KieSession kieSession = kieContainer.newKieSession();
    kieSession.insert(applicant);
    kieSession.setGlobal("suggestedRole",suggestedRole);
    kieSession.fireAllRules();
    // ...
}

It tests two conditions on Applicant instance and then based on the fulfillment of both conditions it sets the Role field in the SuggestedRole object.

This can be verified by executing the test:

@Test
public void whenCriteriaMatching_ThenSuggestManagerRole(){
    Applicant applicant = new Applicant("David", 37, 1600000.0,11);
    SuggestedRole suggestedRole = new SuggestedRole();
        
    applicantService.suggestARoleForApplicant(applicant, suggestedRole);
 
    assertEquals("Manager", suggestedRole.getRole());
}

In this example, we’ve used few Drools provided keywords. Let’s understand their use:

  • package – this is the package name we specify in the kmodule.xml, the rule file is located inside this package
  • import – this is similar to Java import statement, here we need to specify the classes which we are inserting in the KnowledgeSession
  • global – this is used to define a global level variable for a session; this can be used to pass input parameter or to get an output parameter to summarize the information for a session
  • dialect – a dialect specifies the syntax employed in the expressions in the condition section or action section. By default the dialect is Java. Drools also support dialect mvel; it is an expression language for Java-based applications. It supports the field and method/getter access
  • rule – this defines a rule block with a rule name
  • when – this specifies a rule condition, in this example the conditions which are checked are Applicant having experienceInYears more than ten years and currentSalary in a certain range
  • then – this block executes the action when the conditions in the when block met. In this example, the Applicant role is set as Manager

5.2. Decision Tables

A decision table provides the capability of defining rules in a pre-formatted Excel spreadsheet. The advantage with Drools provided Decision Table is that they are easy to understand even for a non-technical person.

Also, it is useful when there are similar rules, but with different values, in this case, it is easier to add a new row on excel sheet in contrast to writing a new rule in .drl files. Let’s see what the structure of a decision table with an example of applying the label on a product based on the product type:

The Decision Table is grouped in different sections the top one is like a header section where we specify the RuleSet (i.e. package where rule files are located), Import (Java classes to be imported) and Notes (comments about the purpose of rules).

The central section where we define rules is called RuleTable which groups the rules which are applied to the same domain object.

In the next row, we have column types CONDITION and ACTION. Within these columns, we can access the properties of the domain object mentioned in one row and their values in the subsequent rows.

The mechanism to fire the rules is similar to what we have seen with .drl files.

We can verify the outcome of applying these rules by executing the test:

@Test
public void whenProductTypeElectronic_ThenLabelBarcode() {
    Product product = new Product("Microwave", "Electronic");
    product = productService.applyLabelToProduct(product);
    
    assertEquals("BarCode", product.getLabel());
}

6. Conclusion

In this quick article, we have explored making use of Drools as a business rule engine in our application. We’ve also seen the multiple ways by which we can write the rules in the Drools rule language as well as in easy to understand the language in spreadsheets.

As always, the complete code for this article is available over on GitHub.

The Price of all “Rest with Spring” course packages will increase by $50 next Friday:

>>> GET ACCESS NOW