Jump to: navigation, search

Stardust/Knowledge Base/Integration/Application/DroolsRuleFromPOJO

Introduction

A business rule can be defined using Drools and it can be called from Stardust . These rules can be changed / modified on-the-fly and there is no need to restart the server. Stardust already provides a Drools Rules Engine Application Type where one can specify the location of a Drools rules file (.DRL) or a Guvnor package. This article discusses an alternative approach where a Drools rule file is invoked from a POJO executed through a Stardust process.

Calling Drools Rule from Stardust POJO

This section describes how to call a business rule using Stardust-POJO application.

Basically, there can be different ways to specify the location of a rule file. e.g

  • A rule is defined using Guvnor package and mention the URL of the rule file while calling the rule.
  • Copy the rule file at any location and read the file from that location.
  • Copy the rule file in the classpath of the project and read from there.

Irrespective of the approach, the rule can be changed on-the-fly and there is no need to restart the server. The basic code to call the business rule will be almost same all three above approach; only the method of the API will change, as per the approach.

The steps to call a business rule from POJO application are:

  • Define the business rule/ rule file.
  • Design the model and use POJO application to call the rule.

Let's take a simple example to understand the steps. The business rule defined is as follows: "To define the priority of the customer on the basis of sum assured. If the sum assured is greater than 500000 then priority is 1."

The Customer object is passed to the rules engine and Drools will check for the sum assured and then accordingly set the priority of the Customer. The updated Customer object can be accessed inside Stardust/POJO for further use.

Define the business rule

The business rule is defined as follows:

Stardust Integration Application DroolsRuleFromPOJO image 1.png

This screen shot is taken from drool-guvnor web application. The business rule is defind under a package called CustomerPackage.

This rule can be written inside a rule file and can be copied at any location or at classpath and then accessed by the POJO. The steps for this approach will be discussed at the end of the document.

Design the model

The next step is to design the model from where the rule will be invoked. The model shown below in the screenshot has a manual activity "Enter Sum Assured" in which SumAssured will be entered from the UI. Next is an application activity "Call Drools Rule" which will call a POJO and internally the POJO will call the rules engine. The return/updated value will be displayed in the UI in "Display Priority" activity.

These steps/activities are just an example to get/read the value for SumAssured & display Priority. The actual model will change as per the requirement.

Stardust Integration Application DroolsRuleFromPOJO image 2.png

JARs to be copied

There are certain Jars which are required at run time to call Drool rule. These JARs are to be copied at WEB-INF/lib folder of the web application. They are

Stardust Integration Application DroolsRuleFromPOJO image 3.png

Here the Customer Jar has Customer object which will be used for the interaction between Stardust & Drools.

Code inside Customer class

package com.test;
 
import java.io.Serializable;
 
public class Customer implements Serializable{
 
                private int sumAssured;         
                private String hni;   
                private int priority;
 
                public int getPriority() {
                               return priority;
                }
 
                public void setPriority(int priority) {
                               this.priority = priority;
                }
 
                public int getSumAssured() {
                               return sumAssured;
                }
 
                public void setSumAssured(int sumAssured) {
                               this.sumAssured = sumAssured;
                }
 
                public String getHni() {
                               return hni;
                }
 
                public void setHni(String hni) {
                               this.hni = hni;
                }
 
}

Code inside POJO

package com.test;
 
import java.util.Collection;
 
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.definition.KnowledgePackage;
import org.drools.event.rule.DebugAgendaEventListener;
import org.drools.event.rule.DebugWorkingMemoryEventListener;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;
 
public class TestDroolRule {
 
                public TestDroolRule(){
 
                }              
 
                public int callDroolRule(int sumAssured) {
 
                               final KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
 
                               // Use this line if calling rule defined using guvnor package
                               kbuilder.add(ResourceFactory.newUrlResource
("http://localhost:8080/drools-guvnor/org.drools.guvnor.Guvnor/package/CustomerPackage/LATEST.drl"),
                                                               ResourceType.DRL);
 
                               // Use this line if calling rule defined inside a rule file which is copied at any location 
//                             kbuilder.add(ResourceFactory.newFileResource("D://CustomerPackage.drl"), ResourceType.DRL);
 
                               // Use this line if calling rule defined inside a rule file which is copied at classpath
//                             kbuilder.add(ResourceFactory.newClassPathResource("CustomerPackage.drl",
//                                                             Customer.class), ResourceType.DRL);
 
 
                               // Check the builder for errors
                               if (kbuilder.hasErrors()) {
                                               System.out.println(kbuilder.getErrors().toString());
                                               throw new RuntimeException("Unable to compile the rule file.");
                               }else{
                                               System.out.println(".....Rule File is Read Successfully....");
                               }
 
                               // get the compiled packages (which are serializable)
                               final Collection pkgs = kbuilder
                                                               .getKnowledgePackages();
 
                               // add the packages to a knowledgebase (deploy the knowledge packages).
                               final KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
                                kbase.addKnowledgePackages(pkgs);
 
                               final StatefulKnowledgeSession ksession = kbase
                                                               .newStatefulKnowledgeSession();
 
                               ksession.addEventListener(new DebugAgendaEventListener());
                               ksession.addEventListener(new DebugWorkingMemoryEventListener());
 
                                Customer customer = new Customer();
                               customer.setSumAssured(sumAssured);                            
                               customer.setPriority(0);
 
                               ksession.insert(customer);
                               ksession.fireAllRules();          
                               ksession.dispose();
 
                               System.out.println("Got back the response...");
                               System.out.println("Customer Priority : " + customer.getPriority());
 
                               return customer.getPriority();
 
                }
 
}

Using a Rule file

As mentioned above, a rule can be defined inside a Drools rule file and the rule file can be copied in the classpath or at any location from where it can be read. In this case, only the method of ResuorceFactory class will be changed. The sample code is shown above and the code is commented out with proper documentation.

A sample rule file for example under will have code like this:
package CustomerPackage
import com.test.Customer
 
rule 'CustomerRule'
dialect 'mvel'
no-loop true
 
when
$customer : Customer(sumAssured >= "500000")   
 
then
        System.out.println( "Sum Assured is : " + $customer.sumAssured );
        modify($customer) {priority =5 }
        System.out.println( "Priority is changed to 5");
 end