Sample Drools Program - rules engine - drools tutorial - business rules engine
- In this, we will generate a Drools project for the following problem statement:
- Depending upon the city and the kind of product find out the local tax related to that city.
- We have two DRL files for our Drools project.
- The two DRL files will indicate two cities (Lucknow and Noida) and four types of products (Gadgets, medicines, watches, and luxury goods).
- The tax on medicines in both the cities is considered as zero.
- For Gadgets, we have assumed a tax of Rs 2 in Lucknow and Rs 1 in Noida.
- We have used the same selling price to demonstrate different outputs. Note that all the rules are getting fired in the application.
Example:
package com.sample;
import java.math.BigDecimal;
public class ItemCity {
public enum City {
LUCKNOW, NOIDA
}
public enum Type {
GADGETS, MEDICINES, WATCHES, LUXURYGOODS
}
private City purchaseCity;
private BigDecimal sellPrice;
private Type typeofItem;
private BigDecimal localTax;
public City getPurchaseCity() {
return purchaseCity;
}
public void setPurchaseCity(City purchaseCity) {
this.purchaseCity = purchaseCity;
}
public BigDecimal getSellPrice() {
return sellPrice;
}
public void setSellPrice(BigDecimal sellPrice) {
this.sellPrice = sellPrice;
}
public Type getTypeofItem() {
return typeofItem;
}
public void setTypeofItem(Type typeofItem) {
this.typeofItem = typeofItem;
}
public BigDecimal getLocalTax() {
return localTax;
}
public void setLocalTax(BigDecimal localTax) {
this.localTax = localTax;
}
}
DRL Files
- Here we used two DRL files: Lucknow.drl and Noida.drl.
Lucknow.drl
- This is the DRL file that executes rules for Lucknow city
package droolsexample
// list any import classes here.
import com.sample.ItemCity;
import java.math.BigDecimal;
// declare any global variables here
dialect "java"
rule "Lucknow Medicine Item"
when
item : ItemCity (purchaseCity == ItemCity.City.LUCKNOW,
typeofItem == ItemCity.Type.MEDICINES)
then
BigDecimal tax = new BigDecimal(0.0);
item.setLocalTax(tax.multiply(item.getSellPrice()));
end
rule "Lucknow Gadgets Item"
when
item : ItemCity(purchaseCity == ItemCity.City.LUCKNOW,
typeofItem == ItemCity.Type.GADGETS)
then
BigDecimal tax = new BigDecimal(2.0);
item.setLocalTax(tax.multiply(item.getSellPrice()));
end
Noida.drl
- This is the DRL file that executes rules for Noida city
package droolsexample
// list any import classes here.
import com.sample.ItemCity;
import java.math.BigDecimal;
// declare any global variables here
dialect "java"
rule "Noida Medicine Item"
when
item : ItemCity(purchaseCity == ItemCity.City.NOIDA,
typeofItem == ItemCity.Type.MEDICINES)
then
BigDecimal tax = new BigDecimal(0.0);
item.setLocalTax(tax.multiply(item.getSellPrice()));
end
rule "Noida Gadgets Item"
when
item : ItemCity(purchaseCity == ItemCity.City.NOIDA,
typeofItem == ItemCity.Type.GADGETS)
then
BigDecimal tax = new BigDecimal(1.0);
item.setLocalTax(tax.multiply(item.getSellPrice()));
end
- The DRL files based on city, as it gives us extensibility to add any number of rule files later if new cities are being added.
- To demonstrate that all the rules are getting triggered from our rule files, we have used two item types (medicines and Gadgets); and medicine is tax-free and Gadgets are taxed as per the city.
- Our test class loads the rule files, inserts the facts into the session, and produces the output.
Droolstest.java
package com.sample;
import java.math.BigDecimal;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;
import com.sample.ItemCity.City;
import com.sample.ItemCity.Type;
/* This is a sample class to launch a rule. */
public class DroolsTest {
public static final void main(String[] args) {
try {
// load up the knowledge base
KnowledgeBase kbase = readKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
ItemCity item1 = new ItemCity();
item1.setPurchaseCity(City.LUCKNOW);
item1.setTypeofItem(Type.MEDICINES);
item1.setSellPrice(new BigDecimal(10));
ksession.insert(item1);
ItemCity item2 = new ItemCity();
item2.setPurchaseCity(City.LUCKNOW);
item2.setTypeofItem(Type.GADGETS);
item2.setSellPrice(new BigDecimal(10));
ksession.insert(item2);
ItemCity item3 = new ItemCity();
item3.setPurchaseCity(City.NOIDA);
item3.setTypeofItem(Type.MEDICINES);
item3.setSellPrice(new BigDecimal(10));
ksession.insert(item3);
ItemCity item4 = new ItemCity();
item4.setPurchaseCity(City.NOIDA);
item4.setTypeofItem(Type.GADGETS);
item4.setSellPrice(new BigDecimal(10));
ksession.insert(item4);
ksession.fireAllRules();
System.out.println(item1.getPurchaseCity().toString() + " "
+ item1.getLocalTax().intValue());
System.out.println(item2.getPurchaseCity().toString() + " "
+ item2.getLocalTax().intValue());
System.out.println(item3.getPurchaseCity().toString() + " "
+ item3.getLocalTax().intValue());
System.out.println(item4.getPurchaseCity().toString() + " "
+ item4.getLocalTax().intValue());
} catch (Throwable t) {
t.printStackTrace();
}
}
private static KnowledgeBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("Lucknow.drl"), ResourceType.DRL);
kbuilder.add(ResourceFactory.newClassPathResource("Noida.drl"), ResourceType.DRL);
KnowledgeBuilderErrors errors = kbuilder.getErrors();
if (errors.size() > 0) {
for (KnowledgeBuilderError error: errors) {
System.err.println(error);
}
throw new IllegalArgumentException("Could not parse knowledge.");
}
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
return kbase;
}
}
Output
LUCKNOW 0
LUCKNOW 20
NOIDA 0
NOIDA 10
- For both Lucknow and Noida, when the item is a medicine, the local tax is zero; whereas when the item is a gadget product, the tax is as per the city. More rules can be added in the DRL files for other products.
Call an External Function form a DRL File
- Here we will demonstrate how to call a static function from a Java file within your DRL file.
- First of all, create a class HelloCity.java in the same package com.sample.
package com.sample;
public class HelloCity {
public static void writeHello(String name) {
System.out.println("HELLO " + name + "!!!!!!");
}
}
- Thereafter, add the import statement in the DRL file to call the writeHello method from the DRL file.
Example
package droolsexample
// list any import classes here.
import com.sample.ItemCity;
import java.math.BigDecimal;
import com.sample.HelloCity;
//declare any global variables here
dialect "java"
rule "Lucknow Medicine Item"
when
item : ItemCity(purchaseCity == ItemCity.City.LUCKNOW, typeofItem == ItemCity.Type.MEDICINES)
then
BigDecimal tax = new BigDecimal(0.0);
item.setLocalTax(tax.multiply(item.getSellPrice()));
HelloCity.writeHello(item.getPurchaseCity().toString());
end
rule "Lucknow Gadgets Item"
when
item : ItemCity(purchaseCity == ItemCity.City.LUCKNOW, typeofItem == ItemCity.Type.GADGETS)
then
BigDecimal tax = new BigDecimal(2.0);
item.setLocalTax(tax.multiply(item.getSellPrice()));
end
Output
HELLO LUCKNOW!!!!!!
LUCKNOW 0
LUCKNOW 20
NOIDA 0
NOIDA 10
- The advantage to call a Java method is that we can write any utility/helper function in Java and call the same from a DRL file.