Why at Jar we migrated our business logics to Drools?
Introduction
Managing complex business logic and rules can be challenging in software development. Traditional if-else statements become cumbersome and hard to maintain as the complexity increases. This is where Drools comes in. Drools is a Business Rules Management System (BRMS) that simplifies the process of defining, deploying, managing, and executing business rules. In this blog, we'll explore what Drools is, its key features, and why it might be a better choice than traditional methods or data structures like B+ trees.
How did we come across Drools?
The problem statement was to develop a logic for displaying a cross-sell banner once the user completes a transaction on our application. The cards were first segregated based on the cohorts to which the user belongs. There were a total of four cohorts, determined by the user's previous transactions. For each cohort, we further segregated the cards based on the user's autopay setup. If the user's autopay was set up, we segregated the cards into eight more conditions. If their autopay was not set up, we segregated the cards into three conditions. For each of these sub-conditions, we checked the user's transaction count over the past week, ranging from one to eight. Based on the transaction count, we decided which card to display.
The problem statement had close to 300-350 use cases, and to solve this, we needed an efficient tool. That's how we came across Drools!
Drools vs. Traditional If-Else Statements
Traditional if-else statements can quickly become unwieldy as the number of conditions increases. Here’s how Drools improves upon this:
- Readability and Maintainability: Rules in Drools are more readable and maintainable compared to nested if-else statements.
- Scalability: Drools handles a large number of rules more efficiently, allowing for complex logic to be managed systematically.
- Flexibility: Business rules can be updated without changing the application code, reducing the risk of introducing bugs.
Drools vs. B+ Trees
B+ trees are data structures used for indexing and retrieving data efficiently, commonly used in database systems. While B+ trees are excellent for data management, they are not suited for business rule management. Drools, on the other hand, is designed specifically for managing business rules and offers several advantages:
- Purpose and Use Case: Drools manages dynamic business rules, whereas B+ trees handle static data indexing.
- Complexity Management: Drools can handle complex decision-making processes, while B+ trees are limited to data storage and retrieval.
- Flexibility and Rule Management: Drools allows for dynamic rule changes without modifying the application code, something B+ trees are not designed to handle.
What is Drools?
Drools is an open-source BRMS that uses a forward and backward chaining inference-based rules engine. It allows for the separation of business rules from application code, enabling business analysts and developers to manage rules independently. Drools provides a high-level, declarative way to define business logic using the Drools Rule Language (DRL), decision tables, and domain-specific languages (DSLs).
Key Features of Drools
- Declarative Rule Definition: Drools allows rules to be written in a readable and maintainable format. This makes it easier for non-developers to understand and manage the business logic.
- Separation of Concerns: By separating business rules from application code, Drools ensures that changes in business logic do not require modifications to the application itself.
- Dynamic and Flexible Rule Management: Rules can be added, modified, or removed without changing the underlying application code, providing greater flexibility and adaptability to changing business requirements.
- Advanced Features: Drools supports complex event processing (CEP), forward and backward chaining, and temporal reasoning, enabling sophisticated decision-making processes.
Key Components of Drools: KIE Services, KIE Modules, KIE Containers, and KIE Sessions
To effectively use Drools, it's important to understand its core components: KIE Services, KIE Modules, KIE Containers, and KIE Sessions.
- KIE Services (Knowledge Is Everything Services):
- KIE Services provide the APIs to interact with the Drools engine. It acts as a factory for creating and managing KIE Containers and KIE Sessions.
- Example:
KieServices kieServices = KieServices.Factory.get();
- KIE Module:
- A KIE Module is a collection of resources (rules, processes, decision tables, etc.) that are grouped together. It is typically represented as a Maven project or a JAR file.
- It defines the base structure for organizing rules and processes.
- KIE Container:
- A KIE Container is a runtime environment that holds all the KIE Bases and sessions. It loads the KIE Module and provides access to the knowledge base and sessions.
- Example:
KieContainer kieContainer = kieServices.getKieClasspathContainer();
- KIE Session:
- A KIE Session is the core runtime interface to interact with the rule engine. It allows you to insert facts, fire rules, and manage the execution state.
- Two types of sessions: Stateless KIE Session and Stateful KIE Session.
Example Scenario
Consider an application that needs to select a Marvel character based on their power and speed. Here’s how Drools simplifies this process:
Java Class for Facts:
@Data
public class MarvelCharacter {
private String name;
private int power;
private int speed;
}
Drools Rule (DRL):
package com.example.drools;
import com.example.MarvelCharacter;
rule "Choose Iron Man"
when
$character : MarvelCharacter(power >= 80, speed >= 70)
eval($character.getName().equals("Iron Man"))
then
System.out.println("Selected character: " + $character);
end
rule "Choose Captain America"
when
$character : MarvelCharacter(power >= 60, speed >= 80)
eval($character.getName().equals("Captain America"))
then
System.out.println("Selected character: " + $character);
end
rule "Choose Ms Marvel"
when
$character : MarvelCharacter(power >= 70, speed >= 60)
eval($character.getName().equals("Ms Marvel"))
then
System.out.println("Selected character: " + $character);
end
Java Code to Execute Rules:
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
public class MarvelCharacterSelector {
public static void main(String[] args) {
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("ksession-rules");
MarvelCharacter ironMan = new MarvelCharacter("Iron Man", 85, 75);
MarvelCharacter captainAmerica = new MarvelCharacter("Captain America", 65, 85);
MarvelCharacter msMarvel = new MarvelCharacter("Ms Marvel", 75, 65);
kSession.insert(ironMan);
kSession.insert(captainAmerica);
kSession.insert(msMarvel);
kSession.fireAllRules();
kSession.dispose();
}
}
Efficient Heap Memory Management with ZGC and G1GC
Drools uses heap memory to store facts and execute rules. Efficient heap memory management is crucial to ensure smooth performance and avoid issues like long garbage collection (GC) pauses. Let's compare two modern garbage collectors: G1GC (Garbage First Garbage Collector) and ZGC (Z Garbage Collector), and see how ZGC helps achieve better heap memory management.
G1GC (Garbage First Garbage Collector)
- Design: G1GC is designed to handle large heaps with predictable pause times. It divides the heap into regions and performs garbage collection on selected regions (garbage first).
- Pause Times: G1GC aims to keep pause times short and predictable, but they can still be noticeable in applications with very large heaps.
- Concurrent Phases: G1GC performs most of its work concurrently with the application threads, reducing pause times but still requiring some stop-the-world pauses.
ZGC (Z Garbage Collector)
- Design: ZGC is designed for ultra-low pause times, making it suitable for applications with large heaps and stringent latency requirements. It uses colored pointers and load barriers to perform most of its work concurrently.
- Pause Times: ZGC keeps pause times consistently low (typically sub-millisecond), even for very large heaps.
- Scalability: ZGC can handle multi-terabyte heaps efficiently, making it ideal for memory-intensive applications.
How ZGC is Better than G1GC for Drools
- Ultra-low Pause Times: ZGC's minimal pause times ensure that Drools applications remain responsive and performant, even under heavy loads.
- Scalability: ZGC's ability to handle very large heaps without significant pause times makes it suitable for Drools applications with extensive fact bases and complex rules.
- Concurrent Garbage Collection: ZGC performs most garbage collection work concurrently with application threads, minimizing disruption to Drools rule processing.
Conclusion
Drools provides a powerful and flexible way to manage business rules, making it a better choice than traditional if-else statements and data structures like B+ trees for complex business logic. Its ability to separate business rules from application code, handle dynamic rule changes, and support advanced decision-making features makes it an essential tool for modern software development.
Additional Resources
- Official Drools Documentation: Drools Documentation
- Drools GitHub Repository: Drools GitHub
- Community and Support: Join the Drools community forums for support and discussions.