07 — Rules

Building Rules (Declarative)

Annotation-based rules let you define rules as Java classes with annotated methods. This style is ideal for complex rules that benefit from encapsulation, constructor parameters, and reusability.

Basic Structure

@Rule(name = "ConsistentDateRule")
public class ConsistentDateRule {

    @PreCondition
    public boolean shouldRun(LocalDate startDate, LocalDate endDate) {
        return startDate != null && endDate != null;
    }

    @Given
    public boolean isValid(LocalDate startDate, LocalDate endDate) {
        return !endDate.isBefore(startDate);
    }

    @Then
    public void passed() {
        System.out.println("Dates are consistent");
    }

    @Otherwise
    public void failed() {
        System.out.println("End date is before start date!");
    }
}

Annotation Reference

Annotation Returns Purpose
@Rule Marks the class as a rule (name, description)
@PreCondition boolean Should this rule run? (optional)
@Given boolean The IF condition
@Then void Action when condition is true
@Otherwise void Action when condition is false (optional)

Multiple @Then Actions

You can have multiple @Then methods. Use the order attribute to control execution order:

@Then(order = 0)
public void logResult() {
    System.out.println("Logging...");
}

@Then(order = 1)
public void notifyUser() {
    System.out.println("Notifying...");
}

Parameter Binding with @Param

If your method parameter name doesn't match the binding name, use @Param:

@Given
public boolean isValid(@Param("startDate") LocalDate start,
                        @Param("endDate") LocalDate end) {
    return !end.isBefore(start);
}

Building and Running

// From class (new instance created automatically)
Rule rule = Rule.builder().build(ConsistentDateRule.class);

// From instance (you control construction)
Rule rule = Rule.builder().build(new ConsistentDateRule());

// Run it
rule.run(
    startDate -> LocalDate.of(2025, 1, 1),
    endDate -> LocalDate.of(2025, 12, 31)
);