This tutorial discusses how to run Drool Rules from within a jBPM process, and how to handle the interactions between Process and Rules. (Updated to November 2021 )
Getting started with Drools WorkFlow
Firstly, let’s start with some definitions for Processes and Rules:
Business processes: Represent what the business does.
Business rules: Represent decisions that the business does.
Therefore, although processes and rules are two different thing, there is a clear advantage if your end users are allowed to combine processes and rules. This means, for example, that:
- Rules can define which processes to invoke,
- Rules can specify decisions in that process
- To assign Tasks to Human actors
- Rules can augment (or even override) the behavior specified in the process (for example to handle exceptional cases)
- Rules can alter dynamically the behavior of your process
Finally, by delegating important decision to be taken into your rules system, your business processes become much more resilient to change.
Installing the Eclipse plugins to create Drools/jBPM projects
There are several options to design your process with jBPM.
- Firstly, you can use the KIE Sandbox online editor which is ideal solution if you don’t want to edit your processes locally. ( To check out how to open BPMN Diagrams with the Kie Sandbox see: How to open a BPMN Diagram online? )
- Otherwise, we will show how to use the JBoss tools Eclipse plugins to create Drools rules and to design BPMN2 processes.
In order to handle Drools and jBPM projects from Eclipse first we need to install their plug-in.
- Choose: Help > Install New Software…
- Enter “https://downloads.jboss.org/jbpm/release/7.48.0.Final/updatesite/” from the drop-down list next to the “Add…” button, and press enter. Select “Drools and jBPM” in the next screen.
In order to design BPMN2 diagrams from Eclipse first we need to install as well a plug-in.
- Choose: Help > Install New Software…
- Enter “https://download.eclipse.org/bpmn2-modeler/updates/2021-06/1.5.3” from the drop-down list next to the “Add…” button, and press enter. Select “Eclipse BPMN2 Modeler” in the next screen.
You will need to reboot Eclipse for changes to take effect.
Create a new Drools Rule Engine Project
Start by creating a new Drools project:
Next, choose to build the Project with Maven, which means you don’t need to download the Drools Runtime by yourself. Choose the Maven settings for your project:
In this very simple rule, we will check a model class (Account) against some validation properties. The first rule is trivial: we just check that the Account instance has some money in it:
import com.sample.Account; rule "nameRequired" no-loop true ruleflow-group "helloworldgroup" when $account : Account( money <= 0 ) then System.out.println( "Account needs to have some money in it!"); end
Now add the Account class to your project:
package com.sample; public class Account { private long money; private String name; // getters and setters omitted for brevity @Override public String toString() { return "Account [money=" + money + ", name=" + name + "]"; } public Account() { } }
Good. Now add a new Drools jBPM Process Diagram to your Project:
Choose a name to your Process. In our case we will set the name attribute to “HelloWorld“.
Then, let’s add a Business Rule Task to it:
The Business Rule Task will be in charge to fire our Rule. How do we connect to our Rule ? we can do this through the ruleflow-group attribute by setting it to “helloworldgroup“:
In the META-INF folder we will add a kmodule.xml file which will define our KieSession. In our example it will define a single KieSession where both the Rule and the Process are available:
<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> <kbase name="processrules" packages="com.sample.process"> <ksession name="sample-process-rules"/> </kbase> </kmodule>
Coding class to Test our Process
Now let’s add a Main class to test our project. An example class follows here:
import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; public class ProcessMain { public static void main(String[] args) throws Exception { KieContainer kc = KieServices.Factory.get().getKieClasspathContainer(); KieSession ksession2 = kc.newKieSession("sample-process-rules"); Account account = new Account(); account.setMoney(0); ksession2.insert(account); ksession2.startProcess("com.sample.HelloWorld"); ksession2.fireAllRules(); } }
Here is a tree view of our project:
src └── main ├── java │ └── com │ └── sample │ ├── Account.java │ └── ProcessMain.java └── resources ├── com │ └── sample │ ├── dtables │ ├── process │ │ ├── HelloWorld.bpmn2 │ │ └── Rule.drl │ └── rules ├── logback-test.xml └── META-INF ├── kmodule.xml └── maven └── pom.properties
Before running the class, let’s have a look at the dependencies. When you generate a Drools Rule Engine project with the Eclipse plugin, the dependencies are versioned based on the runtime.version of Drools and JBPM.
We recommend using BOM files to manage the dependencies, so let’s change them in the pom.xml to look like this:
<dependencyManagement> <dependencies> <dependency> <groupId>org.drools</groupId> <artifactId>drools-bom</artifactId> <type>pom</type> <version>${runtime.version}</version> <scope>import</scope> </dependency> <dependency> <groupId>org.jbpm</groupId> <artifactId>jbpm-bom</artifactId> <type>pom</type> <version>${runtime.version}</version> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.kie</groupId> <artifactId>kie-api</artifactId> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-core</artifactId> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-decisiontables</artifactId> </dependency> <dependency> <groupId>org.jbpm</groupId> <artifactId>jbpm-test</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> </dependencies>
In your properties section you will include the Runtime version of Drools and jBPM (7.62.0 November 2021):
<runtime.version>7.62.0.Final</runtime.version>
Please note that some dependencies such as jbpm-persistence-jpa and jbpm-human-task-core are not needed in this basic example, however as expand your project you will probably need to use Human Tasks
When launched the Console, the Drools Rule engine will start and you should see on your console the following message:
Account needs to have some money in it!
Of course verify that setting a positive value for money, the message will not be displayed.
The source code for this example is available here: https://github.com/fmarchioni/mastertheboss/tree/master/drools/drools-jbpm
Using Global variables in your rules
Global variables are variables assigned to a session. They can serve to different purposes:
- You can use them as constants in your session
- Treat them as output of your rule (think about a reporting—a rule could write some message to a global report variable)
- You can use it as entry points for some services such as logging
Firstly, let’s create our global object named RiskyAccounts which is a vector containing all accounts which have money less than zero:
package com.sample; import java.util.ArrayList; public class RiskyAccounts { private ArrayList accounts = new ArrayList(); public void add(Account acc) { accounts.add(acc); } public void listRiskyAccounts() { for (Account acc : accounts) System.out.println(acc); } }
Next, we will import the RiskyAccounts class as global into our rule:
import com.sample.Account; import com.sample.RiskyAccounts; global RiskyAccounts risky; rule "enoughMoney" ruleflow-group "helloworldgroup" when $account : Account( money < 0 ) then System.out.println( "Not enough money on the account!"); risky.add($account); end
This rule simply adds the rule into the vector if money < 0. Finally, we will modify our main class to include in the KSession the global variable RiskyAccount:
package com.sample; import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; public class App { public static void main(String[] args) throws Exception { KieServices ks = KieServices.Factory.get(); KieContainer kContainer = ks.getKieClasspathContainer(); KieSession kSession = kContainer.newKieSession(); Account account = new Account(); account.setName("frank"); account.setMoney(-10); RiskyAccounts risky = new RiskyAccounts(); kSession.setGlobal("risky", risky); kSession.insert(account); kSession.startProcess("demo.test"); kSession.fireAllRules(); } }
Now your process will use the RiskyAccounts to store all Accounts which have a negative value for money attribute. Pretty simple, isn’t it ?