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 nine beans. 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).
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.