Drools is an open-source business rule management system (BRMS) that helps businesses automate decision-making by defining rules that determine what actions to take in various situations. Drools is a java-based rules engine that allows you to separate business logic from the application code, making it more easier to maintain, update and reuse.
There are several ways to define rules in Drools, making it flexible and accessible for different users from developers to business analysts. Here are the few primary methods:
-
Drools Rule Language (DRL): A native language for writing rules in Drools, similar to Java syntax.
Structure: Rules are written in plain text files with a .drl extension.
Example:
package package-name imports globals functions queries rule "rule name" // Attributes when LHS // Conditions then RHS // Actions end rule "rule2 name" ...
-
Decision Tables: Rules can be defined in spreadsheets, typically Excel.
Advantages: Easier for non-technical users to manage rules in a tabular format. Each row represents a rule with columns for conditions and actions. Example: discount.xls
-
Domain-Specific Languages (DSLs): Allows creation of a custom language tailored to specific business domains.
Structure: A DSL file with a .dsl extension is a text file in a line-oriented format. Its entries are used for transforming a DSLR file into a file according to DRL syntax. Example:
[when]There is a customer with age greater than {age}=Customer(age > {age}) [then]Approve the customer's loan=approveLoan($customer)
In this example we have used Decision Tables by creating excel file spreadsheet inside the spring boot application.
- Clarity and Readability: Presents rules in a clear, tabular format that is easy to read and understand.
- Visualization: Provides a visual representation of rules making it easier to identify gaps or overlaps in logic.
- Ease of Maintenance: Simplifies the process of updating rules as changes can be made directly in the table without delving into complex code.
- Collaboration: Facilitates collaboration between business analysts and developers as both can work from the same table format.
- Efficiency: Reduces redundancy by consolidating multiple related rules into a single table.
- Consistency: Ensures consistent application of rules as the table format reduces the likelihood of errors and omissions.
- Non-Tabular Logic: When the rules do not fit into a tabular structure or involve complex logic that cannot be easily expressed in a table format. Decision tables are not suitable for rules that require intricate conditional logic or multiple interdependencies that are difficult to represent in rows and columns.
- Small Number of Rules: When there are only a few rules to manage. The overhead of setting up and maintaining a decision table might not be justified for a small number of rules, which can be more easily managed directly in code or through simple rule definitions.
- Unstructured Rules: Decision tables work best for rules that have a uniform structure. If the rules are too diverse or unstructured, it can be challenging to fit them into a decision table format.
- Preference Against Spreadsheets: When there is a dislike or organizational policy against using spreadsheet software like Excel or OpenOffice.org.
In this example, we have defined the following rules using a decision table and the application will apply the highest possible discount on the purchase amount.
-
If the total purchase amount is greater than or equal to 60,000 then a maximum highest discount rate 12% will be applied.
-
If the total purchase amount is greater than or equal to 40,000 then 6% discount(3rd highest discount rate) will be applied.
-
If the total purchase amount is greater than or equal to 30,000 and if the user is from Arunachal Pradesh, Jammu and Kashmir, Lakshadweep, or Assam then a state-specific discount (2nd highest discount rate ) will be applied.
Approach: You can add an extra ACTION column and have in it "drools.halt();". Then in the row, put some text (such as "Y" or TRUE or "stop", the specific text doesn't matter as long as there is something present)
- Spring boot version: 3.3.1
- Drools
- Java version 21
Step 1: Create a spring boot application and add required dependencies
Step 2: Creating the Excel spreadsheet drools decision table
DRL format of the above drools decision table:
package rules;
//generated from Decision Table
import org.drools.example.model.RuleDataset;
import java.math.BigDecimal;
import java.math.RoundingMode;
function boolean hasTotalPurchaseAmountReachedThresholdAmount(BigDecimal totalPurchaseAmount, double thresholdAmount) {
return totalPurchaseAmount.compareTo(BigDecimal.valueOf(thresholdAmount)) >= 0;
}
function BigDecimal getPayableAmount( BigDecimal totalPurchaseAmount, int discountRate) {
return totalPurchaseAmount
.subtract(totalPurchaseAmount
.multiply(BigDecimal.valueOf(discountRate))
.divide(BigDecimal.valueOf(100),2, RoundingMode.UP));
}
// rule values at A13, header at A8
rule "Total purchase amount >= 60000"
salience 65535
when
ruleDataset: RuleDataset(hasTotalPurchaseAmountReachedThresholdAmount(ruleDataset.getTotalPurchaseAmount(), 60000))
then
ruleDataset.setDiscountAllowed(true) ;
ruleDataset.setDiscountRate(12);
ruleDataset.setPayableAmount(getPayableAmount(ruleDataset.getTotalPurchaseAmount(), ruleDataset.getDiscountRate()));
drools.halt();
end
// rule values at A20, header at A15
rule "Total purchase amount >= 30000 AND State code is JK"
salience 65534
when
ruleDataset: RuleDataset(hasTotalPurchaseAmountReachedThresholdAmount(ruleDataset.getTotalPurchaseAmount(), 30000), ruleDataset.getStateCode() == "JK")
then
ruleDataset.setDiscountAllowed(true) ;
ruleDataset.setDiscountRate(9);
ruleDataset.setPayableAmount(getPayableAmount(ruleDataset.getTotalPurchaseAmount(), ruleDataset.getDiscountRate()));
drools.halt();
end
// rule values at A21, header at A15
rule "Total purchase amount >= 30000 AND State code LD"
salience 65533
when
ruleDataset: RuleDataset(hasTotalPurchaseAmountReachedThresholdAmount(ruleDataset.getTotalPurchaseAmount(), 30000), ruleDataset.getStateCode() == "LD")
then
ruleDataset.setDiscountAllowed(true) ;
ruleDataset.setDiscountRate(10);
ruleDataset.setPayableAmount(getPayableAmount(ruleDataset.getTotalPurchaseAmount(), ruleDataset.getDiscountRate()));
drools.halt();
end
// rule values at A22, header at A15
rule "Total purchase amount >= 30000 AND State code is AS"
salience 65532
when
ruleDataset: RuleDataset(hasTotalPurchaseAmountReachedThresholdAmount(ruleDataset.getTotalPurchaseAmount(), 30000), ruleDataset.getStateCode() == "AS")
then
ruleDataset.setDiscountAllowed(true) ;
ruleDataset.setDiscountRate(8);
ruleDataset.setPayableAmount(getPayableAmount(ruleDataset.getTotalPurchaseAmount(), ruleDataset.getDiscountRate()));
drools.halt();
end
// rule values at A23, header at A15
rule "Total purchase amount >= 30000 AND State code are AR"
salience 65531
when
ruleDataset: RuleDataset(hasTotalPurchaseAmountReachedThresholdAmount(ruleDataset.getTotalPurchaseAmount(), 30000), ruleDataset.getStateCode() == "AR")
then
ruleDataset.setDiscountAllowed(true) ;
ruleDataset.setDiscountRate(10);
ruleDataset.setPayableAmount(getPayableAmount(ruleDataset.getTotalPurchaseAmount(), ruleDataset.getDiscountRate()));
drools.halt();
end
// rule values at A30, header at A25
rule "Total purchase amount >= 40000"
salience 65530
when
ruleDataset: RuleDataset(hasTotalPurchaseAmountReachedThresholdAmount(ruleDataset.getTotalPurchaseAmount(), 40000))
then
ruleDataset.setDiscountAllowed(true) ;
ruleDataset.setDiscountRate(6);
ruleDataset.setPayableAmount(getPayableAmount(ruleDataset.getTotalPurchaseAmount(), ruleDataset.getDiscountRate()));
drools.halt();
end
Step 3: Add the drools configuration in spring boot application
We configured 'StatelessKieSession' as a Spring bean to be used in the service layer.
Step 4: Create a REST endpoint
Step 5: Add service layer
Step 6: Start the Spring Boot application and open the Swagger endpoint.
http://localhost:8080/swagger-ui/index.html
For further reference, please consider the following sections:
These additional references should also help you: