Skip to Content

About this Blog

Drools is the most famous open-source rules engine. And It supports jbpm as a business process engine. In Drools both the engines are combined into KnowledgeBase and they are able to trigger each other during the runtime. In this blog we will see how to run it in with a small example.

Prerequisite

Before starting you need to have JDK/JRE, eclispe, Drools plugin and Drools runtime.

Create a New Project

In eclipse create a new Drools project. And copy the following code into your main method.


public static final void main(String[] args) throws Exception {
        // load up the knowledge base
        KnowledgeBase kbase = readKnowledgeBase();
        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
}
private static KnowledgeBase readKnowledgeBase() throws Exception {
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        return kbuilder.newKnowledgeBase();
 }

Now you have the basic structure of an engine. In our approval example we hope to have the following use cases:

  • If price <= 100, approval process 1 will be triggered.
  • If price > 100, approval process 2 and 3 will be triggered in sequence.

The Rule Part

Before defining the DRL file we need to have a data model as following:


public class Approval {
    public int processId;
    public int price;
    public void setProcessId(int id) {
        this.processId = id;
    }
    public int getProcessId() {
        return this.processId;
    }
    public void setPrice(int price) {
        this.price = price;
    }
    public int getPrice() {
        return this.price;
    }
}

Then we can create a rule file approval.drl in the resources folder:


package com.sap.ngom
import com.sap.ngom.dataModel.Approval;
rule "approval1"
  no-loop true
  when
  approval : Approval( price <= 100)
  then
    System.out.println("Process 1 is triggered.");
    approval.setProcessId(1);
    update(approval);
end
rule "approval2"
  no-loop true
  when
  approval : Approval( price > 100)
  then
    System.out.println("Process 2 is triggered.");
    approval.setProcessId(2);
  update(approval);
end

In this rule file we defined two rules which indicate our two use cases respectively. An Approval instance will be inserted in to the ksession. Let’s take rule “approval2” as an example, if the price variable in the Approval instance is larger than 100, then we will print a message to the console and set the selected processId to 2. Then we need to update the Approval instance to confirm the change.

In our main class we can add the rule file into KnowledgeBase.


public static final void main(String[] args) throws Exception {
        // load up the knowledge base
        KnowledgeBase kbase = readKnowledgeBase();
        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        Approval approval = new Approval();
        approval.setPrice(150);
        ksession.insert(approval);
        ksession.fireAllRules();
    }
private static KnowledgeBase readKnowledgeBase() throws Exception {
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newClassPathResource("rule/approval.drl"), ResourceType.DRL);
        return kbuilder.newKnowledgeBase();
    }

Then we run the code and you can see when the price is set to 150, process 2 will be triggered.

The Process Part

For the process part, we want to run process 2 and 3 in sequence when the 2nd process is triggered. We can create a new .bpmn file in our resource folder. And the structure is as following:

1.PNG

In this diagram we have Start Event, End Event as the process entrance and exit. We have three Script Task blocks as the three processes. We have diverge and converge Gateways to deal with the choosing of the processed.

For the three processes we need to define three classes, which only print a message to the console:


public class Process1 {
    public void runProcess() {
        System.out.println("Now in process 1.");
    }
}

Then in the bpmn file we let each Script Task block invoke the corresponding runProcess() method.

  • Click on the “Process_1” block.
  • Modify the action of in the Property perspective.

1.PNG

  • Copy following code into the text editor:

import com.sap.ngom.process.Process1;

Process1 process = new Process1();

process.runProcess();

  • Click OK to save the action.
  • Do the similar changes in the other 2 process blocks.

The Gateway is used to make a decision between two choices. In our case we need a flag variable called processId to indicate which process is chosen. Click on the blank part of the diagram and add processId to the variables.

1.PNG

Click on the diverge Gateway and set the Type to XOR, which indicates that only one process will be ran. Then we can edit the Constraints. PAY ATTENTION that the Type should be code, otherwise the code cannot be executed properly.

1.PNG

1.PNG

Set the Type of the converge Gateway also to XOR.

Make changes in your main class to run the process.


    public static final void main(String[] args) throws Exception {
        // load up the knowledge base
        KnowledgeBase kbase = readKnowledgeBase();
        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        Approval approval = new Approval();
        approval.setDiscount(0.1f);
        approval.setPrice(150);
        ksession.insert(approval);
        ksession.fireAllRules();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("processId", approval.processId);
        ksession.startProcess("com.sample.bpmn.hello", params);
    }
    private static KnowledgeBase readKnowledgeBase() throws Exception {
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newClassPathResource("process/approval.bpmn"), ResourceType.BPMN2);
        kbuilder.add(ResourceFactory.newClassPathResource("rule/approval.drl"), ResourceType.DRL);
        return kbuilder.newKnowledgeBase();
    }

In the code we can see firstly we use the rule engine to determine which process will be triggered and then set the process Id into the process engine. The process Id is used to indicate which process will be ran.

We set price to 150 ant run the program, we could get the following result:

1.PNG

Trouble Shooting

  • If you got an error that class bpmn could not be found, you should add jbpm-bpmn2 as dependency.
  • If you got an error that cannot cast BPMN2ProcessProviderImpl to BPMN2ProcessProvider, that seems to be a mismatch of the code versions. We should change the runtime of Drools. In eclipse go to Windows -> Preference -> Drools -> Installed Drools Runtimes. Click the Add button and create a new Drools runtime. Use the new runtime instead of the old one, then the issue should be solved.

1.PNG

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply