Drools Rule Basic Examples
In modern software development, business logic frequently undergoes rapid changes and iterations. Traditional hardcoded approaches often lead to prolonged development lifecycles and exorbitant maintenance costs. As a leading open-source rule engine based on Java, Drools effectively decouples business logic from application code, managing policies declaratively. This article walks you through a foundational example to help you quickly master the basics of the Drools rule engine.
Before diving into the code, it is essential to understand three core concepts in Drools:
- Working Memory: The data repository of the rule engine where applications insert facts, allowing the engine to match rules against them.
- Fact: The Java objects passed into the rule engine, acting as the primary data source for rule evaluation.
- Knowledge Base: The centralized repository containing all rules, processes, and functions, serving as the core carrier for the rule engine.
First, configure the necessary Drools dependencies in your Maven project. Open yourpom.xmlfile and include the following dependencies (the stable 7.x release series is recommended):
<dependencies>
<!-- Drools Core Dependency -->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.73.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.73.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>kie-api</artifactId>
<version>7.73.0.Final</version>
</dependency>
</dependencies>
Creating the Fact Data Model
Drools primarily processes standard Java objects. Let us create a simple Order class to compute member discounts based on customer purchase amounts.
public class Order {
private String customerName;
private double originalPrice;
private double discountPrice;
private String discountType;
public Order(String customerName, double originalPrice) {
this.customerName = customerName;
this.originalPrice = originalPrice;
}
public double getOriginalPrice() { return originalPrice; }
public void setDiscountPrice(double discountPrice) { this.discountPrice = discountPrice; }
public void setDiscountType(String discountType) { this.discountType = discountType; }
public String getCustomerName() { return customerName; }
}
Writing the DRL Rule File
Drools rules are typically authored in .drl (Drools Rule Language) files. Create a file named discount.drl under the src/main/resources/rules directory of your project.
The rule logic is defined as follows:
- If the consumption amount is less than 100, no discount is applied.
- If the consumption amount is between 100 and 500, a 10% discount is applied.
- If the consumption amount exceeds 500, a 20% discount is applied.
package rules;
import com.example.model.Order;
rule "Order_No_Discount"
when
$order: Order(originalPrice < 100)
then
$order.setDiscountPrice($order.getOriginalPrice());
$order.setDiscountType("No Discount");
System.out.println("Rule Triggered: Amount under 100, original price charged.");
end
rule "Order_Bronze_Discount"
when
$order: Order(originalPrice >= 100 && originalPrice <= 500)
then
$order.setDiscountPrice($order.getOriginalPrice() * 0.9);
$order.setDiscountType("10% Off");
System.out.println("Rule Triggered: Amount between 100 and 500, 10% discount applied.");
end
rule "Order_Gold_Discount"
when
$order: Order(originalPrice > 500)
then
$order.setDiscountPrice($order.getOriginalPrice() * 0.8);
$order.setDiscountType("20% Off");
System.out.println("Rule Triggered: Amount over 500, 20% discount applied.");
end
Writing the Java Test Code
Once the rule file is ready, write a Java program to load the rules, insert Fact objects into the working memory, and trigger rule execution.
Create DroolsTest.java:
import com.example.model.Order;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
public class DroolsTest {
public static void main(String[] args) {
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("rulesSession");
Order order1 = new Order("Alice", 80.0);
Order order2 = new Order("Bob", 300.0);
Order order3 = new Order("Charlie", 1000.0);
kieSession.insert(order1);
kieSession.insert(order2);
kieSession.insert(order3);
kieSession.fireAllRules();
System.out.println("---------------- Settlement Results ----------------");
System.out.println(order1.getCustomerName() + " Spent: " + order1.getOriginalPrice() + ", Final: " + order1.getDiscountPrice() + " (" + order1.getDiscountType() + ")");
System.out.println(order2.getCustomerName() + " Spent: " + order2.getOriginalPrice() + ", Final: " + order2.getDiscountPrice() + " (" + order2.getDiscountType() + ")");
System.out.println(order3.getCustomerName() + " Spent: " + order3.getOriginalPrice() + ", Final: " + order3.getDiscountPrice() + " (" + order3.getDiscountType() + ")");
kieSession.dispose();
}
}
Note: The code above references rulesSession. You must configure this session in src/main/resources/META-INF/kmodule.xml to allow Drools to load the rules properly:
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="rulesKB" packages="rules">
<ksession name="rulesSession"/>
</kbase>
</kmodule>
Summary
Through these steps, we have successfully implemented a lightweight business rule application powered by Drools. By externalizing business logic into DRL files, promotional updates only require modifications to the rule scripts rather than core Java code, significantly enhancing system flexibility and maintainability. In production environments, you can further integrate database loaders to achieve a dynamic, highly scalable rule engine architecture.