05 — Core

RuleContext

A RuleContext is the execution environment that holds everything a rule needs to run: bindings, locale, converters, message formatters, a tracer, a clock, and an executor service.

Creating a RuleContext

// From bindings
Bindings bindings = Bindings.builder().standard();
bindings.bind("name", "Alice");

RuleContext ctx = RuleContext.builder().build(bindings);

// From lambda declarations
RuleContext ctx2 = RuleContext.builder().build(name -> "Alice", age -> 30);

What's Inside a RuleContext?

Component Purpose
Bindings Shared variable workspace
Matching Strategy Rule parameter matching strategy
Locale For locale-aware formatting
ConverterRegistry Type conversion between binding values
MessageResolver Looks up message templates
MessageFormatter Formats messages with placeholders
Tracer Logs rule execution for debugging
Clock Provides current time (useful for testing)
ExecutorService For async rule execution

When Do You Need a RuleContext?

Most of the time, you don't need to create one manually. When you call rule.run(bindings) or rule.run(name -> "Alice"), a default context is created for you. Create one explicitly when you need to customize locale, converters, or tracing.

// Running with an explicit context
RuleContext ctx = RuleContext.builder().build(name -> "Alice");
RuleResult result = rule.run(ctx);

Accessing Context Inside a Rule

In annotated rules, you can receive the RuleContext as a parameter:

@Given
public boolean when(RuleContext context) {
    Bindings bindings = context.getBindings();
    return bindings.contains("name");
}