Introduction to Rule Units
Rule Units represent the modern approach to organizing business rules in Drools. Introduced in Drools 7 and significantly enhanced in subsequent versions, Rule Units provide a structured, modular way to organize rules and their associated data. In traditional Drools applications, all rules shared a global working memory (KieSession) with little structure or isolation. Rule Units solve this problem by encapsulating rules with their own data sources, creating self-contained modules that can be developed, tested, and executed independently.Core Concepts of Rule Units
A Rule Unit consists of these key components:- A Rule Unit Class: A Java class that implements
RuleUnitData(orRuleUnitin older versions) - Data Sources: Typed containers for facts that rules operate on
- Global Variables: Values shared across all rules in the unit
- Rules: DRL rules that belong to the unit
- Queries: Named operations for retrieving data from the unit
Rule Unit Classes
A Rule Unit class is a Java class that serves as the container for data sources and global variables. This class implements theRuleUnitData interface, which is a marker interface (has no methods to implement).
Basic Rule Unit Class Structure
- Two data sources:
customersandorders - Two global variables:
taxRateandexpressShipping - Standard getters and setters for all members
Rule Unit Lifecycle Methods
In addition to data sources and global variables, Rule Unit classes can optionally implement lifecycle methods:Data Sources in Rule Units
Data sources are typed containers for facts that rules operate on. They represent the entry points through which data flows into your rules. Rule Units support three types of data sources:1. DataStore
A DataStore is a mutable collection that supports the full CRUD (Create, Read, Update, Delete) lifecycle for facts.2. DataStream
A DataStream is an append-only collection designed for event processing.3. SingletonStore
A SingletonStore holds a single value that can be updated or cleared.DRL Files with Rule Units
DRL files for Rule Units follow a specific structure that associates the rules with a particular unit.Basic Structure
- Declare the unit just after the package of the DRL file
- The unit provides direct access to global variables (like
taxRate) - Notifying the engine that we’ve updated the unit
- The
unitdeclaration, which associates the file with a specific Rule Unit class - OOPath expressions starting with
/to reference data sources - Direct access to global variables (like
taxRate) - Data source operations in rule actions (like
orders.update($order))
Accessing Data Sources in Rules
Data sources are accessed using OOPath syntax, starting with a forward slash:Accessing Global Variables
Global variables defined in the Rule Unit class are directly accessible in the rules:Defining Queries
Queries allow you to extract data from Rule Units:Declaring Rule Units in DRL
Instead of creating a Java class, you can declare Rule Units directly in DRL:Executing Rule Units
Rule Units are executed using theRuleUnitInstance API.
Basic Execution
Using RuleUnitExecutor
For more advanced scenarios, especially when working with multiple rule units, you can use theRuleUnitExecutor:
Continuous Execution
For event-based systems, you can use therunUntilHalt() method:
Rule Unit Coordination
One of the powerful features of Rule Units is the ability to coordinate the execution of multiple units.Explicit Coordination
Data-Driven Coordination
Event-Driven Coordination
For more complex coordination patterns, you can use events to trigger rule units:Advanced Rule Unit Features
Configuring Rule Units
You can configure rule units usingRuleConfig:
Rule Unit DSL
For more complex rule unit interactions, you can use the Rule Unit DSL:Best Practices for Rule Units
1. Design for Modularity
Break down complex rule systems into focused rule units:2. Choose the Right Data Sources
Select the appropriate data source type for each use case:- DataStore: For facts that need full CRUD operations
- DataStream: For events and append-only data
- SingletonStore: For global configuration and shared state
3. Use Consistent Naming Conventions
Establish clear naming conventions for rule units and their components:4. Test Rule Units in Isolation
Create unit tests for each rule unit:5. Document Rule Units and Their Purpose
Add clear documentation to rule unit classes and DRL files:Migrating from Traditional Drools to Rule Units
If you’re transitioning from traditional Drools to Rule Units, here are the key steps:1. Identify Rule Groups
Identify groups of related rules in your existing codebase:- Rules in the same agenda group
- Rules with similar purposes
- Rules operating on the same fact types
2. Define Rule Unit Classes
Create Rule Unit classes for each group:3. Convert Facts to Data Sources
Move facts from global working memory to specific data sources:4. Update DRL Files
Add unit declarations to your DRL files:5. Replace Direct Rule Operations
Update rule actions to use data source operations:Converting Between Classic and Rule Unit APIs
REST Integration with Rule Units
Rule Units integrate seamlessly with REST APIs when using frameworks like Quarkus or Spring Boot.Automatically Generated REST Endpoints
When using Kogito with Rule Units, REST endpoints are automatically generated:Custom REST Controllers
You can also create custom controllers for more control:Real-World Examples
Let’s look at some real-world examples of Rule Units in action.Example 1: Loan Application Processing
Example 2: IoT Monitoring System
Common Patterns with Rule Units
Event-Driven Architecture
Rule Units fit naturally into event-driven architectures:Batch Processing
For batch processing scenarios:Multi-Stage Processing Pipeline
For complex workflows, chain multiple rule units:Debugging Rule Units
Debugging rule units requires understanding both the Rule Unit API and the underlying rule execution.Enable Logging
Configure proper logging for rule execution:Add Event Listeners
Use event listeners for detailed execution information:Use Breakpoints Effectively
Set breakpoints in:- Rule Unit lifecycle methods
- Rule execution (when and then blocks)
- Data source operations
Trace Execution
Create a simple tracing utility:Audit Queries
Create audit queries in your rule units:Performance Considerations
Use the Right Data Source Type
Choose data source types that match your usage patterns:- DataStore for mutable, long-lived facts
- DataStream for high-volume event processing
- SingletonStore for configuration and shared state
Minimize Data Source Size
Keep data sources focused and minimal:Consider Stateless Execution
For high-throughput scenarios, use stateless execution:Use Indexes for Better Performance
Ensure your fact classes have proper indexing:Advanced Topics
Rule Unit Composition
Compose rule units for more complex behaviors:Data Source Subscription
Subscribe to data sources programmatically:Custom Data Sources
Implement custom data sources for specific needs:Conclusion
Rule Units represent a significant advancement in rule organization and execution in Drools. By providing a structured, modular approach to rule management, they enable more maintainable, testable, and scalable rule-based systems. Key takeaways:- Modularity: Rule Units encapsulate rules with their data sources
- Type Safety: Strongly typed data sources prevent type-related errors
- Clarity: Clear separation of concerns with dedicated data sources
- Integration: Seamless integration with modern frameworks and architectures
- Scalability: Better performance and resource utilization