Skip to main content
The then section of a rule (also known as the Right Hand Side or RHS) contains the actions that execute when the rule’s conditions are met. While the when section uses a specialized pattern-matching syntax, the then section contains plain Java code. This chapter explores how to write effective rule actions that implement your business logic.

Understanding Rule Actions

Rule actions serve several purposes:
  1. Modify facts: Update the properties of matched facts
  2. Add or remove facts: Insert new facts or remove existing ones
  3. Execute business logic: Perform calculations or operations
  4. Trigger side effects: Call external services, log events, or send notifications
Let’s explore the core operations that can be performed in rule actions.

Working with Facts

Facts are the objects that rules operate on. The Drools rule engine maintains a working memory containing all facts, and rule actions can modify this memory.

Modifying Facts

When you match a fact in the when section and need to update its properties, you can modify it directly:
Notice the customers.update($customer) call. This informs the rule engine that the fact has been modified, which can trigger other rules that depend on those properties. Always remember to update the data source after modifying a fact.

The modify Block

As an alternative to directly modifying properties and calling update(), you can use the modify block:
The modify block automatically handles the update for you, which helps prevent errors where you might forget to call update(). It also clearly groups the changes being made to a single object.

Adding New Facts

To add a new fact to working memory, you create the object and add it to the appropriate data source:

Removing Facts

Sometimes you need to remove facts from working memory when they’re no longer relevant:

Logical Insertions

Drools supports the concept of logical insertions with addLogical(). Facts added with this method are automatically removed when the conditions that led to their insertion are no longer true:
If the order total later changes to less than 100 (perhaps due to a cancellation), the ShippingDiscount will be automatically removed from working memory.

Executing Business Logic

Rule actions often need to perform business logic beyond simple fact modifications.

Calculations

You can perform calculations directly in the rule action:

Method Calls

You can call methods on fact objects or utility classes:

Conditional Logic

While you should strive to keep rule actions simple and declarative, sometimes you need conditional logic:
However, consider whether complex conditional logic would be better expressed as multiple rules instead.

Error Handling and Validation

Rule actions should handle errors gracefully and validate data to ensure robustness.

Try-Catch Blocks

When calling external services or performing operations that might fail, use try-catch blocks:

Input Validation

Even though constraints in the when section filter facts, it’s sometimes necessary to perform additional validation in the actions:

Logging and Debugging

Adding logging to rule actions can be invaluable for debugging and monitoring:
For production systems, consider using a proper logging framework like SLF4J or Log4j instead of System.out.

Advanced Action Techniques

Beyond the basics, there are several advanced techniques for rule actions.

Asynchronous Actions

For actions that might take time to complete, consider making them asynchronous:
Note that when working with threads, you need to be careful about how you update facts in the Drools working memory. The example above creates a new KieSession for the asynchronous update.

External Services Integration

Rules often need to interact with external systems:

Reusable Action Methods

For complex operations that are used in multiple rules, consider extracting them to helper methods:

Best Practices for Rule Actions

To keep your rule system maintainable and efficient, follow these best practices:

1. Keep Actions Simple and Focused

Each rule should perform a single, well-defined action. If a rule needs to perform multiple operations, consider whether it should be split into multiple rules. Benefits of simple actions include:
  • Easier to understand: The purpose of the rule is clear
  • Easier to maintain: Changes to one aspect don’t affect others
  • Better performance: Rules can be optimized more effectively
  • Better reuse: Simple actions are more likely to be reusable

2. Use Declarative Style When Possible

Prefer a declarative style (stating what should happen) over imperative style (stating how it should happen) where possible:
If you find your rule actions contain complex conditional logic, consider splitting them into multiple rules with more specific conditions.

3. Always Update Facts After Modification

Remember to call update() after modifying facts or use the modify block:
Without the update, the rule engine won’t recognize that the fact has changed, and other rules that depend on the modified properties won’t be triggered.

4. Be Careful with Side Effects

Rule actions often have side effects like logging, sending emails, or updating databases. Handle these carefully:
  • Idempotence: Can the action safely be performed multiple times?
  • Transactions: Do you need transaction management for database operations?
  • Error handling: What happens if the side effect fails?
  • Asynchronous operations: Should the side effect be performed asynchronously?
Consider using a flag to track whether a side effect has been performed:

5. Use Helper Methods for Complex Logic

Extract complex logic into helper methods:

6. Handle Errors Gracefully

Always include error handling in rule actions that interact with external systems:

7. Avoid Infinite Rule Activations

Be careful not to create infinite loops. This can happen when a rule’s actions trigger the same rule again:
This rule will fire repeatedly because each time it updates the counter, it triggers itself again. Use rule attributes like no-loop or condition constraints to prevent this:

Real-World Examples

Let’s examine some comprehensive examples of rule actions in real-world scenarios.

E-commerce Order Processing

This rule demonstrates processing an order by creating related objects (invoice and fulfillment request) and updating the order status.

Loan Application Approval

This comprehensive example shows:
  1. Setting multiple properties on the application
  2. Using helper methods for calculations
  3. Interacting with external services
  4. Error handling
  5. Creating related objects
  6. Logging

Insurance Claim Processing

This example demonstrates processing an insurance claim by approving it, creating a payment, and updating related objects.

Performance Considerations

Rule actions can impact the performance of your rule system. Consider these tips:

1. Minimize Working Memory Modifications

Every time you update a fact, the rule engine must reevaluate rules that might be affected. Minimize unnecessary updates:

2. Use Property Reactivity

Drools supports property reactivity, which means it only reevaluates rules that depend on the specific properties you’ve changed. Make sure your fact classes properly define getter methods for all properties used in rules.

3. Avoid Expensive Operations in Rule Actions

Expensive operations like database queries, web service calls, or complex calculations should be minimized or optimized:
  • Caching: Cache results of expensive operations
  • Batching: Group operations for batch processing
  • Asynchronous processing: Move expensive operations to background threads
  • Precomputation: Calculate values in advance when possible

Summary

The then section of a rule is where your business logic comes to life. While the condition section determines when a rule should fire, the action section determines what happens when it does. Effective rule actions should be:
  • Clear and focused: Each rule should perform a specific, well-defined action
  • Declarative: State what should happen, not how it should happen
  • Robust: Include proper error handling and validation
  • Efficient: Minimize unnecessary working memory modifications
  • Maintainable: Use helper methods and consistent patterns
By following the best practices outlined in this chapter, you can create rule actions that implement your business logic in a clear, maintainable, and efficient way. In the next chapter, we’ll explore rule attributes, which provide additional control over how and when rules are executed.