Drools Rule Example Walkthrough
Drools is a powerful, open-source rule engine built on Java that separates volatile business logic from core application code. By managing requirements through declarative DRL (Drools Rule Language) files, it achieves a clean decoupling of business rules from software implementation. This article explores the syntax structure and execution mechanics of Drools through a comprehensive order-discount scenario.
A standard Drools rule consists of a rule name, optional attributes, a Left-Hand Side (LHS) for conditions, and a Right-Hand Side (RHS) for actions. Its structural skeleton appears as follows:
package rules
import com.demo.model.Order
rule "Rule Name"
salience 10 // Attribute section
when
// LHS: Fact pattern matching
then
// RHS: Business action execution
end
package: Defines the namespace for the rule file and must be placed on the first line.import: Imports necessary Java classes for use within the rules.rule ... end: Encloses the rule definition. Attributes reside beforewhen, conditions betweenwhenandthen, and executable actions betweenthenandend.
Consider the following business requirements:
- Orders exceeding 1,000 currency units receive a 10% discount.
- VIP members receive an additional 50-unit discount on top of the initial reduction.
First, define the fact object in Java:
public class Order {
private double amount; // Order total amount
private boolean vip; // VIP status flag
private double discount; // Calculated discount amount
// Getters and setters omitted for brevity
}
The corresponding DRL rules are structured as follows:
package rules
import com.demo.model.Order
rule "Large Order Ten Percent Off"
salience 20
when
$o : Order(amount > 1000, discount == 0)
then
$o.setDiscount($o.getAmount() * 0.1);
update($o);
end
rule "VIP Additional Fifty Off"
salience 10
no-loop true
when
$o : Order(vip == true, discount > 0)
then
$o.setDiscount($o.getDiscount() + 50);
update($o);
end
The Matching Syntax of the Condition Section (LHS)
The LHS comprises one or more patterns used to match fact objects residing inside the Working Memory:
- In
$o : Order(amount > 1000, discount == 0),$oserves as a binding variable, making it easy to reference the matched object in the action block. - Multiple constraints inside parentheses default to an
andlogical relationship, though explicit operators like&&and||are also supported. - Conditional elements like
notandexistsare supported. For instance, to verify if a high-value order exists in the Working Memory:
when
exists Order(amount > 10000)
then
// Execute corresponding logic
The Action Section (RHS) and Inference Control
The RHS executes a block of Java code once a rule matches and activates. Beyond standard business logic, it can invoke built-in engine methods to modify the state of facts:
update($o): Notifies the engine that the object has changed, triggering re-matching for related rules.insert(new Xxx()): Inserts a brand-new fact into the Working Memory.retract($o): Removes a fact from the Working Memory.
Care must be taken with update, as it triggers re-evaluation. In our example, the "VIP Additional Fifty Off" rule modifies the discount field, but since the condition discount > 0 remains true afterward, the rule could repeatedly activate itself and cause an infinite loop. Using no-loop true prevents this. Alternatively, the modify block is recommended because it merges property changes and engine notifications into a single, clean operation:
then
modify($o) {
setDiscount($o.getDiscount() + 50)
}
end
Executing Rules in Java
KieServices ks = KieServices.Factory.get();
KieContainer kc = ks.getKieClasspathContainer();
KieSession session = kc.newKieSession("orderKS"); // Corresponds to kmodule.xml configuration
Order order = new Order();
order.setAmount(1500);
order.setVip(true);
session.insert(order);
session.fireAllRules();
session.dispose();
System.out.println("Discount amount: " + order.getDiscount()); // Outputs 200.0
The execution flow proceeds as follows: facts are inserted into the session, the engine performs pattern matching on all rules to generate activations, and rules fire in descending order of salience. In the sample case, the order first triggers the ten-percent-off rule for a 150-unit discount, and subsequent updates activate the VIP rule for an extra 50 units, yielding a final discount of 200 units.
Common Rule Attributes and Best Practices
salience: Higher numerical values represent higher execution priorities, governing the sequence of rule evaluation.no-loop: Prevents a rule from re-activating due to modifications made by its own execution.date-effective/date-expires: Restricts rule validity within specific time windows.agenda-group/activation-group: Facilitates rule partitioning and mutually exclusive execution blocks.
Best practices recommend dividing rule files by business domain with semantic naming conventions. The RHS should focus strictly on simple assignments and state transitions, avoiding complex procedural workflows. Additionally, writing comprehensive unit tests for critical rules ensures that system behavior remains verifiable after adjustments.
Through these concepts, Drools organizes business logic via a pattern-matching and inference-execution paradigm. Combined with mechanisms like salience, update, and no-loop, it offers a flexible, highly controllable approach to managing complex business rules.