02 — Getting Started

Auto-Configuration

rulii-spring ships with a single @AutoConfiguration class — RuleConfig — that sets up everything you need. It's registered through Spring Boot's META-INF/spring/AutoConfiguration.imports file, so it activates automatically when the library is on the classpath.

How It Works

Every bean defined by RuleConfig is annotated with @ConditionalOnMissingBean. This means you can override any bean by declaring your own — Spring Boot will skip the default and use yours instead.

Auto-Configured Beans

RuleConfig creates the core beans below, plus four new beans in 2.0.0 (covered afterwards). Here's each one, what it does, and how to replace it.

1. BindingMatchingStrategy

Controls how rule parameters are matched to bindings at runtime. The default uses the standard matching strategy.

@Bean
@ConditionalOnMissingBean(BindingMatchingStrategy.class)
public BindingMatchingStrategy bindingMatchingStrategy() {
    return BindingMatchingStrategy.builder().build();
}

2. ParameterResolver

Resolves method parameters when invoking rule conditions and actions.

@Bean
@ConditionalOnMissingBean(ParameterResolver.class)
public ParameterResolver parameterResolver() {
    return ParameterResolver.builder().build();
}

3. MessageResolver

Resolves messages for rule violations from Spring's Environment. This is a Spring-specific implementation that reads message codes from application.properties.

@Bean
@ConditionalOnMissingBean(MessageResolver.class)
public MessageResolver messageResolver(Environment environment) {
    return new SpringEnvironmentMessageResolver(environment);
}

4. MessageFormatter

Formats resolved message strings, substituting placeholders with runtime values.

@Bean
@ConditionalOnMissingBean(MessageFormatter.class)
public MessageFormatter messageFormatter() {
    return MessageFormatter.builder().build();
}

5. ObjectFactory

Creates rule instances. When Spring's AutowireCapableBeanFactory is available, this uses SpringObjectFactory to enable constructor injection. Otherwise falls back to rulii's default factory.

@Bean(name = BeanNames.OBJECT_FACTORY_NAME)
@ConditionalOnMissingBean(ObjectFactory.class)
public ObjectFactory objectFactory(BeanFactory beanFactory) {
    if (beanFactory instanceof AutowireCapableBeanFactory ctx) {
        return new SpringObjectFactory(ctx);
    }
    return ObjectFactory.builder().build();
}

6. ConverterRegistry

Manages type converters for rule parameters. Automatically picks up any Spring Converter beans and wraps Spring's ConversionService with a SpringConverterAdapter.

@Bean(name = BeanNames.SPRING_CONVERTER_REGISTRY)
@ConditionalOnMissingBean(ConverterRegistry.class)
public ConverterRegistry converterRegistry(
        @Autowired(required = false) Set<Converter<?, ?>> converters,
        @Autowired(required = false) ConversionService conversionService,
        @Value("${rulii.converts.registerDefaults:true}") boolean registerDefaults) {
    // Registers defaults, custom converters, and Spring ConversionService
}

7. RuleRegistry

A Spring-backed registry that looks up rules directly from the application context. Uses SpringRuleRegistry when a ListableBeanFactory is available.

@Bean(BeanNames.RULE_REGISTRY)
@ConditionalOnMissingBean(RuleRegistry.class)
public RuleRegistry ruleRegistry(
        @Autowired(required = false) ListableBeanFactory ctx) {
    if (ctx != null) return new SpringRuleRegistry(ctx);
    return RuleRegistry.builder().build();
}

8. RuleContextOptions

Bundles all the above beans into a single options object for rule execution. Includes a fixed thread pool for async execution and the system clock.

@Bean
@ConditionalOnMissingBean(RuleContextOptions.class)
public RuleContextOptions ruleContextOptions(...) {
    return new SpringEnabledRuleContextOptions(
        matchingStrategy, parameterResolver, messageFormatter,
        converterRegistry, objectFactory, messageResolver,
        Executors.newFixedThreadPool(Math.max(2, Runtime.getRuntime().availableProcessors())),
        Clock.systemDefaultZone(), Locale.getDefault());
}

9. RuleBeanDefinitionRegistryPostProcessor

A fallback post-processor that automatically scans for rules when @RuleScan is not present. It uses AutoConfigurationPackages to determine the base packages. This bean is only created if no RuleRegistrarMetaInfo bean exists (which @RuleScan registers).

New Beans in 2.0.0

rulii.executorService

A bounded thread pool (work queue of 1000, caller-runs policy) used for async rule and RuleFlow execution, shut down with the application context. It is overridden by name: define your own bean named rulii.executorService to replace it — unrelated ExecutorService beans are deliberately ignored.

Tracer

Auto-configured with every RuliiListener, RuleListener, RuleSetListener, and RuleFlowListener bean found in the context. A bean that implements several listener interfaces is registered exactly once.

ScriptProcessorManager & ScriptTextResolverConfigurer

The script manager wires all discovered ScriptProcessorFactory beans (including SpEL). The resolver configurer enables ${property:default} environment placeholders inside script text; disable it with rulii.scripts.resolvePlaceholders=false.

Overriding a Bean

To replace any auto-configured bean, just define your own. For example, to provide a custom MessageResolver:

@Configuration
public class MyRuleConfig {

    @Bean
    public MessageResolver messageResolver() {
        return new MyCustomMessageResolver();
    }
}

Because RuleConfig uses @ConditionalOnMissingBean, your bean takes priority and the default is skipped entirely.