DRL File Structure
A typical DRL file contains the following components, usually in this order:Packages in DRL
The package declaration is required at the beginning of every DRL file and serves two important purposes:- Organizational structure: Packages group related rules together, similar to Java packages
- Namespace definition: Provides a unique namespace for rules, queries, and declared types
Syntax
Example
Best Practices
- Logical grouping: Organize rules into packages based on business domain or functionality
- Consistency with Java: Align DRL packages with your Java package structure
- Avoid default package: Always specify a package explicitly for clarity and organization
Package Scope
Rules, queries, and declared types are scoped to their package. This means:- Rule names must be unique within a package
- Imported classes are available to all rules in the package
- Global variables are accessible throughout the package
Rule Units in DRL
Rule units are a modern approach to organizing related rules and their data sources. A rule unit:- Defines the data sources that rules can act upon
- Groups related rules into a cohesive unit
- Provides clear boundaries and encapsulation
- Enables more targeted rule execution
Declaring a Rule Unit
Unit Implementation in Java
For each rule unit declared in DRL, you’ll need a corresponding Java class:Data Sources
Rule units work with three types of data sources:- DataStore: A mutable collection that supports adding, removing, and updating facts
- DataStream: An append-only stream of facts, similar to a queue
- SingletonStore: A container for a single value that can be set or cleared
Using Data Sources in Rules
To reference facts from a data source, use the OOPath syntax with a leading slash:Benefits of Rule Units
- Encapsulation: Related rules and data are bundled together
- Modularity: Units can be developed, tested, and deployed independently
- Clarity: Clear boundaries for rule scope and data access
- Performance: Rules only react to relevant data sources
- REST Integration: Units can be automatically exposed as REST endpoints
Import Statements in DRL
Import statements in DRL work similarly to Java imports, allowing you to use external classes without their fully qualified names.Syntax
Examples
Types of Imports
- Class Imports: Standard Java class imports
import java.util.Date; - Package Imports: Import all classes from a package
import ai.aletyx.model.*; - Static Imports: Import static methods or fields
import static ai.aletyx.Constants.MAX_LOAN_AMOUNT; - Function Imports: Import functions for use in rules
import function ai.aletyx.utils.DateUtils.daysBetween; - Accumulate Function Imports: Import custom accumulate functions
import accumulate ai.aletyx.functions.WeightedAverage weightedAvg;
Automatic Imports
Drools automatically imports:- Classes from the same package as the DRL file
- Classes from the
java.langpackage
Best Practices
- Explicitly import classes for clarity
- Use fully qualified names for occasional usage to avoid unnecessary imports
- Group imports logically (Java standard, domain-specific, etc.)
- Consider package organization to minimize import complexity
Type Declarations
Type declarations allow you to define new fact types directly in DRL files. This is useful when:- You don’t want to create Java classes for simple fact types
- You need to add metadata to existing types
- You’re prototyping and want to quickly define a data model
Declaring a New Type
Example
Adding Metadata to Types
Extending Types
Using Declared Types
Once declared, you can use these types in your rules:Common Type Metadata
- @role(fact|event): Specifies if the type is a regular fact or an event
- @timestamp: Defines which field contains the event timestamp
- @duration: Specifies which field defines the event duration
- @expires: Sets a time after which events automatically expire
- @key: Marks fields to be used in equals and hashCode methods
Rule Structure
Now let’s examine the structure of individual rules in detail:Rule Name
Every rule must have a unique name within its rule unit. Names can contain spaces and should be descriptive of the rule’s purpose.Rule Attributes
Rule attributes modify the behavior of the rule. They are optional and are placed before thewhen section:
- salience: Sets rule priority (higher executes first)
- no-loop: Prevents the rule from re-activating due to its own actions
- date-effective/date-expires: Time window when the rule is active
- duration: Delay before rule actions execute
- timer: Schedule-based execution timing
- lock-on-active: Stronger version of no-loop
Conditions (when)
Thewhen section defines the conditions under which the rule should fire. It consists of one or more patterns that match against facts in working memory:
- Data source matching (
/orders) - Constraints (
total > 1000) - Bindings to variables (
$order: /orders) - Property access (
customer.status) - Conditional elements (
and,or,not,exists, etc.)
Actions (then)
Thethen section defines the actions to take when the conditions are met. This is Java code that executes when the rule is triggered. Unlike the when section, which uses its own pattern matching syntax, the then section contains plain Java code:
- Modifying matched facts
- Creating new facts
- Adding/removing facts from data sources
- Logging or sending notifications
- Calling external services
Summary
In this section, we’ve covered the fundamental building blocks of DRL:- Packages: Namespaces that organize related rules
- Rule Units: Containers for related rules and data sources
- Imports: References to external classes and functions
- Type Declarations: Definitions for fact types
- Rule Structure: The components of individual rules