04b — Core

Binding Matching

When a rule executes, its parameters (conditions, actions) need to be resolved from the available bindings. The BindingMatchingStrategy determines how rule parameters are matched to bindings in the container.

How Matching Works

Each rule parameter declares a name and type. When the rule runs, the matching strategy looks through the available bindings to find the best match for each parameter:

// Rule with parameters "age" (Integer) and "name" (String)
Rule rule = Rule.builder()
    .given(condition((Integer age, String name)
        -> age > 18 && name != null))
    .build();

// Bindings with matching names and compatible types
rule.run(age -> 25, name -> "Alice");
// "age" matches to age parameter, "name" matches to name parameter

BindingMatchingStrategy

The BindingMatchingStrategy interface defines how bindings are resolved for rule parameters:

public interface BindingMatchingStrategy {
    <T> Binding<T> match(Bindings bindings, String name,
                          TypeReference<T> type, boolean required);
}

Match by Name

This strategy matches bindings by name. The parameter name in your condition or action must match the binding name exactly:

// Parameter named "total" will match binding named "total"
Rule rule = Rule.builder()
    .given(condition((BigDecimal total) -> total.compareTo(BigDecimal.ZERO) > 0))
    .build();

rule.run(total -> BigDecimal.valueOf(99.99));  // Matched by name "total"

Match by Type

When a name match is not found, the strategy can fall back to matching by type. If there is exactly one binding of the required type, it will be used:

// If only one BigDecimal binding exists, it matches regardless of name
Bindings bindings = Bindings.builder().standard();
bindings.bind("orderTotal", BigDecimal.valueOf(150));

// Parameter "total" can still match "orderTotal" by type

The default strategy is a combination of the above, firstly it matches bindings by name and if there are no matches it will attempt to match by Type

If you wish to override the matching strategy you can either set it on RuleContext or on individual method parameters using @Param(matchUsing=BindingMatchingStrategyType.MATCH_BY_NAME)

Important: If a required parameter cannot be matched to any binding, a BindingNotFoundException is thrown at execution time. Make sure all required rule parameters have corresponding bindings available.

Tip: Name-based matching is preferred for clarity and predictability. Use descriptive, consistent parameter names across your rules and bindings to avoid ambiguity.