03 — Getting Started

Rule Scanning & Discovery

rulii-spring automatically discovers your @Rule classes and registers them as Spring beans. There are two ways this happens: explicit scanning with @RuleScan, or automatic fallback scanning.

@RuleScan (Recommended)

Place @RuleScan on your main application class or any @Configuration class. It accepts an array of base packages to scan.

@SpringBootApplication
@RuleScan(scanBasePackages = {"com.example.rules", "com.example.validation"})
public class MyApp { }

If you omit scanBasePackages, the scanner defaults to the package of the annotated class:

// Scans com.example and all sub-packages
package com.example;

@SpringBootApplication
@RuleScan
public class MyApp { }

How Scanning Works

Under the hood, @RuleScan triggers a RuleRegistrar (an ImportBeanDefinitionRegistrar). Here's the flow:

  1. RuleRegistrar reads the scanBasePackages attribute from @RuleScan
  2. A RuleBeanDefinitionScanner (extending ClassPathBeanDefinitionScanner) scans those packages for classes annotated with @Rule
  3. Each discovered class is wrapped in a BeanDefinition that uses RuleBeanBuilder.build() as its factory method
  4. The bean is registered under the rule's name (derived from the class by ClassBasedRuleBuilder.getRuleName())
  5. A RuleRegistrarMetaInfo record is stored, tracking the scanned packages and rule count

Automatic Fallback Scanning

If you don't use @RuleScan, rulii-spring still tries to find your rules. The auto-configured RuleBeanDefinitionRegistryPostProcessor kicks in and uses Spring Boot's AutoConfigurationPackages to determine base packages.

This works, but you'll see a log message recommending explicit @RuleScan usage. The fallback exists for convenience; explicit scanning gives you full control over which packages are included.

Tip

Always prefer explicit @RuleScan in production applications. It's faster (scans only what you specify) and makes your configuration self-documenting.

What Gets Scanned

The scanner looks exclusively for classes annotated with rulii's @Rule annotation. A typical rule class looks like this:

package com.example.rules;

@Rule
public class AgeVerificationRule {

    @Given
    public boolean isAdult(Integer age) {
        return age != null && age >= 18;
    }

    @Then
    public void allow() {
        // approved
    }

    @Otherwise
    public void deny() {
        // rejected
    }
}

After scanning, this rule is available as a Spring bean named "AgeVerificationRule" (the name is derived from the class). You can look it up through the RuleRegistry or inject it directly.

Multiple @RuleScan Locations

You can specify multiple packages in a single @RuleScan annotation. All packages and their sub-packages are scanned recursively.

@RuleScan(scanBasePackages = {
    "com.example.rules.eligibility",
    "com.example.rules.pricing",
    "com.example.rules.compliance"
})