07 — Advanced

Message Resolution

Rule violations carry messages that describe what went wrong. With rulii-spring, those messages can be externalized to application.properties or application.yml, making them easy to manage and change without touching code.

SpringEnvironmentMessageResolver

This is the default MessageResolver auto-configured by rulii-spring. It reads message codes from Spring's Environment, which means any property source works — properties files, YAML, environment variables, or Spring Cloud Config.

public class SpringEnvironmentMessageResolver implements MessageResolver {

    public String resolve(Locale locale, String code, String defaultMessage) {
        return environment.getProperty(code, defaultMessage);
    }
}

The locale parameter is accepted but not used for resolution — Spring's Environment resolves properties by key only. If you need locale-aware resolution, you can override the MessageResolver bean with one backed by Spring's MessageSource.

Externalizing Messages

Define message codes in your properties file:

# application.properties
rule.age.tooYoung=Must be at least {0} years old
rule.credit.insufficient=Insufficient credit for amount {0}
rule.email.invalid=Please provide a valid email address

Or in YAML:

# application.yml
rule:
  age:
    tooYoung: "Must be at least {0} years old"
  credit:
    insufficient: "Insufficient credit for amount {0}"

Using Messages in Rules

When you reference a message code in a rule violation, the resolver looks it up from the environment. If the code isn't found, the default message is used instead.

// The message code "rule.age.tooYoung" is resolved from properties
// If not found, the default message is used
messageResolver.resolve(
    Locale.getDefault(),
    "rule.age.tooYoung",
    "Age requirement not met"
);
// Returns: "Must be at least {0} years old"

Profile-Specific Messages

Since resolution uses Spring's Environment, you can leverage Spring profiles to provide different messages per environment. Messages in application-prod.properties override those in application.properties when the prod profile is active.

Custom MessageResolver

To replace the default resolver (for example, to use Spring's MessageSource for i18n), declare your own bean:

@Bean
public MessageResolver messageResolver(MessageSource messageSource) {
    return (locale, code, defaultMessage) ->
        messageSource.getMessage(code, null, defaultMessage, locale);
}

This overrides the auto-configured SpringEnvironmentMessageResolver and enables full locale-aware message resolution.