Skip to main content

Introduction to Data Sources

Data sources are a fundamental concept in rule units that provide a structured way to work with facts (data objects) in your rules. Think of data sources as specialized containers that manage how facts are stored, updated, and shared between rules. Unlike traditional Drools working memory, data sources are strongly typed and provide clear entry points for facts to enter and exit your rule systems. In simpler terms, data sources are “fact containers” that your rules can observe and interact with. When facts in these containers change, relevant rules are automatically triggered.

Why Use Data Sources?

Data sources solve several common problems in rule-based systems:
  1. Type Safety: Data sources are strongly typed, preventing type-related errors
  2. Isolation: Each rule unit has its own data sources, reducing unintended interactions
  3. Declarative API: Clear methods for adding, updating, and removing facts
  4. Reactive Processing: Changes in data sources automatically trigger rule evaluation
  5. Improved Testability: Data sources can be mocked and verified in tests

Types of Data Sources

Drools supports three primary types of data sources, each designed for specific use cases:

1. DataStore

A DataStore is the most versatile data source type. It functions similar to a collection that supports the complete lifecycle of facts: adding, updating, and removing. When to use DataStore:
  • For facts that need to be added, updated, or removed during rule execution
  • When working with domain objects that change over time
  • For most traditional rule use cases
Key characteristics:
  • Mutable collection of facts
  • Complete CRUD (Create, Read, Update, Delete) operations
  • Notifies rule engine when facts change

Creating a DataStore

DataStore Operations

Using DataStore in Rules

2. DataStream

A DataStream is an append-only data source designed for event processing. It allows you to add facts but not update or remove them, making it perfect for event streams where history matters. When to use DataStream:
  • For processing events in sequential order
  • When you need an audit trail of all events
  • For immutable facts that don’t change once created
  • In Complex Event Processing (CEP) scenarios
Key characteristics:
  • Append-only collection
  • Facts cannot be updated or removed
  • Optimized for sequential processing
  • Good for event-based systems

Creating a DataStream

DataStream Operations

Using DataStream in Rules

3. SingletonStore

A SingletonStore holds a single value that can be updated or cleared. This is useful for configuration settings, global state, or reference data that all rules need to access. When to use SingletonStore:
  • For global configuration settings
  • For reference data that all rules need to access
  • When you need a reactive global variable
  • For state that affects all rules in a unit
Key characteristics:
  • Contains at most one element
  • Can be set, updated, or cleared
  • All rules react to changes in the singleton
  • Similar to a global variable but reactive

Creating a SingletonStore

SingletonStore Operations

Using SingletonStore in Rules

DataHandle: Managing Fact References

When you add facts to a DataStore, you receive a DataHandle in return. This handle is a reference to the fact within the data source and is essential for updating or removing the fact later.
If you lose the handle but need to update a fact, you can still use the overloaded methods that locate the handle for you, but this is less efficient:

Practical Examples

Let’s examine some real-world examples of using different data sources together:

Example 1: Order Processing System

Corresponding DRL:

Example 2: IoT Sensor Monitoring

Best Practices for Working with Data Sources

1. Choose the Right Data Source Type

  • Use DataStore for facts that need full lifecycle management
  • Use DataStream for events and immutable facts
  • Use SingletonStore for global configurations and state

2. Optimize Update Operations

  • Always keep track of DataHandles for facts you’ll update
  • Group related updates together to minimize rule activations
  • Use the modify block in rule actions when available

3. Manage Memory Efficiently

  • Remove facts from DataStore when they’re no longer needed
  • Consider using event expiration for DataStream facts
  • Be cautious with large collections in SingletonStore

4. Design for Modularity

  • Keep data sources focused on a specific domain concept
  • Share data sources between rule units when appropriate
  • Use multiple smaller rule units instead of one large unit

5. Ensure Type Safety

  • Use generics consistently with data sources
  • Avoid mixing different fact types in the same data source
  • Consider creating wrapper types for primitive values

Common Pitfalls and Solutions

Pitfall 1: Forgetting to Update Data Sources

When you modify facts in rule actions, remember to notify the data source:

Pitfall 2: Overusing SingletonStore

SingletonStore should be used sparingly for truly global state:

Pitfall 3: Inefficient Data Source Operations

Perform operations efficiently:

Converting from Traditional Drools to Rule Units

If you’re migrating from traditional Drools to Rule Units, here’s how the traditional operations map to data source operations:

Conclusion

Data sources are the foundation of effective rule units. By understanding the different types of data sources and when to use each one, you can design more modular, maintainable, and efficient rule systems. The right data source type depends on your specific use case:
  • Use DataStore for most traditional rule use cases with mutable facts
  • Use DataStream for event processing and audit trails
  • Use SingletonStore for configuration and global state
By choosing the appropriate data source type and following the best practices outlined in this guide, you’ll be able to create more robust rule systems that are easier to develop, test, and maintain.