Skip to content
πŸš€ Play in Aletyx Sandbox to start building your Business Processes and Decisions today! ×

Visual Guide to Drools Rule Execution

10 min

This guide visually explains how the Drools rule engine processes your business rules and facts. By understanding the underlying mechanisms, you'll be better equipped to write efficient rules.

The Big Picture: How Drools Works

At a high level, Drools follows this sequence when processing rules:

graph TD
    A[Define Rules] --> B[Insert Facts]
    B --> C[Pattern Matching]
    C --> D[Agenda Creation]
    D --> E[Rule Execution]
    E --> F[Update Working Memory]
    F -->|If changes trigger rules| C

Let's break down each of these steps and understand what happens behind the scenes.

1. Inside the Rule Engine

The Drools rule engine has three key components that interact during rule processing:

graph LR
    subgraph "Drools Rule Engine Components"
        PM[Production Memory<br/>Stores Business Rules]
        WM[Working Memory<br/>Stores Facts/Data Objects]
        AG[Agenda<br/>Execution Queue & Order]

        PM -->|Pattern Matching| WM
        WM -->|Rule Activations| AG
        AG -->|Execute Actions| WM
    end

The three key components work together:

  1. Production Memory: Stores your business rules
  2. Working Memory: Stores your facts (data objects)
  3. Agenda: Determines which rules to execute and in what order

Here's a simplified view of how these components interact:

graph TD
    A[Business Rules] --> B[Production Memory]
    B -- Pattern Matching --> C

    subgraph "Rule Engine"
        C[Working Memory<br>Facts/Objects] --> D[Agenda]
    end

    D --> E[Rule Execution]

2. Pattern Matching Process

When facts are inserted into working memory, Drools needs to determine which rules should fire. This process is called pattern matching.

The Rete Network Evolution: From Rete to Phreak

Drools originally used the Rete algorithm (pronounced "REE-tee" or "RAY-tay") for pattern matching. Since Drools 6, it has been completely replaced by Phreak, an enhanced algorithm that provides:

  • Lazy evaluation: Rules are only evaluated when needed
  • Set-oriented propagation: Better performance with large data sets
  • Improved memory usage: More efficient fact storage
  • Better scalability: Handles thousands of rules and facts efficiently

While Phreak is architecturally different from Rete, the conceptual model remains similar, making it easier to understand rule execution.

Here's a simplified visualization of how a Rete/Phreak network might look for a rule:

graph TD
    OTN[Object Type Nodes] --> A[Applicant]
    OTN --> B[Loan]
    OTN --> C[Credit]
    OTN --> D[...]
    A --> AN[Alpha Nodes<br>Property Constraints]
    B --> AN
    C --> AN
    AN --> BN[Beta Nodes<br>Joins]
    BN --> TN[Terminal Nodes<br>Rules]

Let's understand each node type:

  1. Object Type Nodes: Filter facts by their class type
  2. Alpha Nodes: Apply single-fact constraints (e.g., age > 18)
  3. Beta Nodes: Join multiple facts together (e.g., $a: Applicant() and $l: Loan(applicant == $a))
  4. Terminal Nodes: Represent rules that are ready to fire

3. From Rule Definition to Execution

Let's walk through the lifecycle of a rule from definition to execution using a simple example:

Rule Definition

rule "Approve loan for good credit"
when
    $application : LoanApplication(approved == false)
    $applicant : Applicant(creditScore > 700)
then
    modify($application) {
        setApproved(true),
        setReason("Good credit score")
    }
    System.out.println("Loan approved");
end

1. Rule Compilation

When you define rules like the one above, Drools compiles them into a network of nodes:

                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                     β”‚  Object Type    β”‚
                     β”‚  LoanApplicationβ”‚
                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                     β”‚  Alpha Node     β”‚
                     β”‚  approved==falseβ”‚
                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚         Beta Network          β”‚
           β”‚                               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Object Type      β”‚          β”‚    Alpha Node      β”‚
β”‚   Applicant        │─────────▢│    creditScore>700 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                         β”‚
                                         β–Ό
                               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                               β”‚   Terminal Node     β”‚
                               β”‚   (Rule Activation) β”‚
                               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Fact Insertion

When you insert facts, they flow through this network:

Applicant john = new Applicant("John", 30, 720);
LoanApplication johnApp = new LoanApplication(john, 50000);

kSession.insert(john);        // Fact 1
kSession.insert(johnApp);     // Fact 2

Both facts enter working memory and are processed through the network.

3. Pattern Matching and Agenda Creation

As facts flow through the network:

  1. The LoanApplication fact is checked against its constraints (not approved)
  2. The Applicant fact is checked against its constraints (credit score > 700)
  3. If both match, the rule is activated and placed on the agenda
graph LR
    subgraph Agenda ["Rule Execution Agenda"]
        A["⭐ 'Approve loan<br/>for good credit'"]
    end

4. Rule Execution

When you call fireAllRules(), Drools executes the rules on the agenda:

kSession.fireAllRules();  // Execute activated rules

The rule executes its action (the "then" part), which approves the loan application.

5. Working Memory Update

After rule execution, working memory is updated:

Working Memory (Before)          Working Memory (After)
─────────────────────────        ─────────────────────────
Applicant(creditScore=720)       Applicant(creditScore=720)
LoanApplication(approved=false)  LoanApplication(approved=true)

6. Re-evaluation (if needed)

Because we used modify() to change the loan application, Drools automatically re-evaluates any rules that might be affected by this change.

4. The Two-Phase Execution Cycle

When you call fireAllRules(), Drools enters a two-phase execution cycle:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                             β”‚      β”‚                             β”‚
β”‚   Agenda Evaluation Phase   │──────▢  Working Memory Actions     β”‚
β”‚                             β”‚      β”‚  Phase                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚                                  β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. Agenda Evaluation Phase: The rule engine selects rules that can be executed.
  2. If no more rules can be executed, the cycle ends
  3. If executable rules are found, they're registered in the agenda

  4. Working Memory Actions Phase: The rule engine executes the consequences (actions) of activated rules.

  5. After all consequences are complete, or if fireAllRules() is called again, the process returns to the agenda evaluation phase

5. Conflict Resolution

What happens when multiple rules are eligible to fire? Drools uses conflict resolution strategies to determine the execution order:

Salience (Priority)

Rules with higher salience values fire before rules with lower values:

rule "High Priority Rule"
    salience 100
when
    // conditions
then
    // actions
end

rule "Low Priority Rule"
    salience 10
when
    // conditions
then
    // actions
end

In this example, the "High Priority Rule" will fire before the "Low Priority Rule" if both are activated.

Agenda Groups

Rules can be partitioned into agenda groups, and only rules in the focus group are eligible for execution:

graph TD
    subgraph "Agenda"
        A["Agenda Group: <br> 'calculation' (in focus)"]
        B["⭐ Rule 'Calculate tax'"]
        C["⭐ Rule 'Calculate discount'"]
        D["Agenda Group: <br>'reporting'"]
        E["⭐ Rule 'Generate report'"]
        F["⭐ Rule 'Log transaction'"]

        A --> B
        A --> C
        D --> E
        D --> F
    end

Only rules in the "calculation" group will fire until that group is empty or loses focus.

6. Stateful vs. Stateless Sessions Visualized

Stateful Session

A stateful session maintains facts across multiple fireAllRules() calls:

 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
 β”‚   Stateful Session  β”‚
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     Working Memory    β”‚
β”‚  ───────────────────  β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Applicant(John)      │◄────── insert(john)β”‚
β”‚                       β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     Working Memory    β”‚
β”‚  ───────────────────  β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Applicant(John)      │◄────── insert(johnApp)  β”‚
β”‚  LoanApplication(...) β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     Working Memory    β”‚
β”‚  ───────────────────  β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Applicant(John)      │◄────── fireAllRules()   β”‚
β”‚  LoanApplication(...) β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ [AFTER RULE EXECUTION]β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     Working Memory    β”‚
β”‚  ───────────────────  β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Applicant(John)      │◄────── insert(mary)     β”‚
β”‚  LoanApplication(...) β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚  Applicant(Mary)      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     Working Memory    β”‚
β”‚  ───────────────────  β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Applicant(John)      │◄────── dispose()        β”‚
β”‚  LoanApplication(...) β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚  Applicant(Mary)      β”‚
β”‚  [SESSION DESTROYED]  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Stateless Session

A stateless session processes all facts in a single operation and doesn't maintain state:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Stateless Session   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           β”‚
           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Insert all facts     β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Execute all rules    │◄──── execute([john, johnApp])β”‚
β”‚  Dispose automaticallyβ”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Stateless Session   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           β”‚
           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Insert all facts     β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Execute all rules    │◄──── execute([mary, maryApp])β”‚
β”‚  Dispose automaticallyβ”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Each execute() call is a separate, isolated operation with no shared state between calls.

7. Truth Maintenance and Logical Insertions

Drools supports automatic truth maintenance through logical insertions. When you use insertLogical() instead of insert(), the fact is automatically retracted when the conditions that led to its insertion are no longer true.

                   Initial State
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Working Memory                          β”‚
β”‚ ───────────────                         β”‚
β”‚ Person(age=16)                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Rule "Infer Child" fires                β”‚
β”‚ when                                    β”‚
β”‚   $p : Person(age < 18)                 β”‚
β”‚ then                                    β”‚
β”‚   insertLogical(new IsChild($p))        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Working Memory                          β”‚
β”‚ ───────────────                         β”‚
β”‚ Person(age=16)                          β”‚
β”‚ IsChild(person=Person(age=16))          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Update Person age                       β”‚
β”‚ person.setAge(20)                       β”‚
β”‚ update(factHandle, person)              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚
                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Working Memory                          β”‚
β”‚ ───────────────                         β”‚
β”‚ Person(age=20)                          β”‚
β”‚ [IsChild fact automatically retracted]  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

8. Event Processing in Drools

For time-based events, Drools supports two processing modes:

Cloud Mode (Default)

All events are treated as regular facts with no temporal constraints:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Working Memory (Cloud Mode)               β”‚
β”‚ ───────────────────────────               β”‚
β”‚ StockTick(symbol="AAPL", price=150.00)    β”‚
β”‚ StockTick(symbol="MSFT", price=245.00)    β”‚
β”‚ StockTick(symbol="AAPL", price=152.00)    β”‚
β”‚                                           β”‚
β”‚ [Events processed in insertion order      β”‚
β”‚  regardless of their time stamps]         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Stream Mode

Events are processed with temporal awareness:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Working Memory (Stream Mode)              β”‚
β”‚ ───────────────────────────               β”‚
β”‚ Time: 10:01:00                            β”‚
β”‚ StockTick(symbol="AAPL", price=150.00)    β”‚
β”‚                                           β”‚
β”‚ Time: 10:02:00                            β”‚
β”‚ StockTick(symbol="MSFT", price=245.00)    β”‚
β”‚                                           β”‚
β”‚ Time: 10:03:00                            β”‚
β”‚ StockTick(symbol="AAPL", price=152.00)    β”‚
β”‚                                           β”‚
β”‚ [Events processed in chronological order] β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

9. Sliding Windows

In stream mode, you can define sliding windows of time or length to process only recent events:

Time Window

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Sliding Time Window (2 minutes)           β”‚
β”‚ ─────────────────────────────             β”‚
β”‚                                           β”‚
β”‚ Current time: 10:03:00                    β”‚
β”‚                                           β”‚
β”‚ In window:                                β”‚
β”‚ ──────────                                β”‚
β”‚ StockTick(time=10:02:00, symbol="MSFT")   β”‚
β”‚ StockTick(time=10:03:00, symbol="AAPL")   β”‚
β”‚                                           β”‚
β”‚ Outside window (expired):                 β”‚
β”‚ ─────────────────────                     β”‚
β”‚ StockTick(time=10:01:00, symbol="AAPL")   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Length Window

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Sliding Length Window (last 2 events)     β”‚
β”‚ ────────────────────────────────          β”‚
β”‚                                           β”‚
β”‚ In window:                                β”‚
β”‚ ──────────                                β”‚
β”‚ StockTick(time=10:02:00, symbol="MSFT")   β”‚
β”‚ StockTick(time=10:03:00, symbol="AAPL")   β”‚
β”‚                                           β”‚
β”‚ Outside window:                           β”‚
β”‚ ───────────────                           β”‚
β”‚ StockTick(time=10:01:00, symbol="AAPL")   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

10. Temporal Operators

Drools supports temporal operators to define relationships between events:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Temporal Relationship: "after"                                      β”‚
β”‚ ────────────────────────────                                        β”‚
β”‚                                                                     β”‚
β”‚ StockTick(symbol="AAPL", price=150)  β”‚                              β”‚
β”‚                           β”‚          β”‚                              β”‚
β”‚                           β”‚          β”‚                              β”‚
β”‚                           β”‚          β–Ό                              β”‚
β”‚                           β”‚     StockTick(symbol="AAPL", price=152) β”‚
β”‚                           β”‚                                         β”‚
β”‚                           β”‚                                         β”‚
β”‚             Event B occurs after Event A                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Drools supports many temporal operators including: - after/before - coincides - during/includes - finishes/finished by - meets/met by - overlaps/overlapped by - starts/started by

11. Property Reactivity

By default, Drools only re-evaluates rules when properties that are actually used in constraints change:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Rule:                                             β”‚
β”‚ "Approve high value customer"                     β”‚
β”‚ when                                              β”‚
β”‚   Customer(status == "Gold", spending > 1000)     β”‚
β”‚ then                                              β”‚
β”‚   // Actions                                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
                     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Working Memory                                    β”‚
β”‚ ─────────────                                     β”‚
β”‚ Customer(                                         β”‚
β”‚   name="John",                                    β”‚
β”‚   age=35,           ← Changing this property      β”‚
β”‚   status="Gold",    ← Reactive property           β”‚
β”‚   spending=1200     ← Reactive property           β”‚
β”‚ )                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

When you change the age property, the rule isn't re-evaluated because the rule doesn't use it. When you change status or spending, the rule is re-evaluated.

This gives you visibility into when: - Facts are inserted, updated, or deleted - Rules are activated or fired - Agenda groups are pushed or popped

Logging

Configure SLF4J logging to see detailed information:

<logger name="org.drools" level="debug"/>

This creates a log file that can be opened with the Audit View tool.

13. Life Cycle of a Drools Application

Here's the typical lifecycle of a Drools application:

graph TD
    A[Define Facts Models] --> B[Author Rules]
    B --> C[Insert Facts]
    C --> D[Gather Rules Required]
    D --> E[Determine Order to Fire]
    E --> F[Fire Rules]
    F --> G[Get Results]
    G -->|Are there more rules <br> to process?| E
    G -->|Done| H[Complete]

Summary

You've now seen how the Drools rule engine processes rules and facts. Understanding these internal mechanisms will help you:

  1. Write more efficient rules: By understanding how the pattern matching works, you can structure your rules for better performance
  2. Troubleshoot issues: When rules don't fire as expected, you know where to look
  3. Choose the right session type: Based on your use case, you can select stateful or stateless sessions
  4. Work with events: You can process time-based events using stream mode and sliding windows

The visual representations in this guide are simplified, but they provide a mental model of how Drools works under the hood. As you become more familiar with Drools, you'll develop an intuition for how changes to your rules and facts affect rule execution.

Remember that Drools is designed to separate business logic from application code. This separation makes your systems more maintainable and adaptable to changing requirements.