Interceptors

SmallRye Config provides an interceptor chain that hooks into the Configuration Value resolution. This is useful to implement features like Property Substitution, Configuration Profiles, or just Logging to find out where the Config was loaded from.

Usage

An interceptor can be created by implementing the ConfigSourceInterceptor interface.

The ConfigSourceInterceptor is able to intercept the resolution of a configuration name with the method ConfigValue getValue(ConfigSourceInterceptorContext context, String name). The ConfigSourceInterceptorContext is used to proceed with the interceptor chain. The chain can be short-circuited by returning an instance of ConfigValue.

The ConfigValue objects hold information about the key name, value, config source origin and ordinal.

Additionally, the ConfigSourceInterceptor may also intercept resolution of configuration names of configuration ConfigValue values with the methods Iterator<String> iterateNames(ConfigSourceInterceptorContext context) and Iterator<ConfigValue> iterateValues(ConfigSourceInterceptorContext context).

The Interceptor Chain is applied before any Conversion is performed on the Configuration.

Registration

Registration of an interceptor in the interceptor chain is done via the ServiceLoader mechanism and provide the implementation classes in a META-INF/services/io.smallrye.config.ConfigSourceInterceptor file.

Registration can also be done with a ConfigSourceInterceptorFactory, via the`ServiceLoader` mechanism and provide the implementation class in a META-INF/services/io.smallrye.config.ConfigSourceInterceptorFactory file. The ConfigSourceInterceptorFactory may initialize the interceptor with access to the current chain (so it can be used to configure the interceptor and retrieve configuration values) and set the priority.

Alternatively, interceptors may be registered via the Programmatic API in SmallRyeConfigBuilder#withInterceptors or SmallRyeConfigBuilder#withInterceptorFactories.

Priority

A ConfigSourceInterceptor implementation class can specify a priority by way of the standard javax.annotation.Priority annotation. If no priority is explicitly assigned, the default priority value of io.smallrye.config.Priorities.APPLICATION is assumed. If multiple interceptors are registered with the same priority, then their execution order may be non-deterministic.

A collection of built-in priority constants can be found in io.smallrye.config.Priorities. It is recommended to use io.smallrye.config.Priorities.APPLICATION has a baseline for user defined interceptors.

Built-In Interceptors

SmallRye Config provides the following built-in Interceptors (ordered by priority):

The ExpressionConfigSourceInterceptor, the ProfileConfigSourceInterceptor and the SecretKeysConfigSourceInterceptor are registered by default with each new instance of Config. Other interceptors require registration via the ServiceLoader mechanism or via the Programmatic API io.smallrye.config.SmallRyeConfigBuilder#withInterceptors.

RelocateConfigSourceInterceptor

The RelocateConfigSourceInterceptor allows relocating a configuration name to another name, by providing a transformation function or just a simple key value map.

Consider when a configuration key is renamed, lookup needs to happen on the new name, but also on the old name if the ConfigSources are not updated yet. The relocation function gives priority to the new resolved configuration name or resolves to the old name if no value is found under the new relocation name.

The following RelocateConfigSourceInterceptor can relocate configuration names in the smallrye.config namespace to the microprofile.config namespace:

new RelocateConfigSourceInterceptor(
    name -> name.startsWith("smallrye.config") ?
    name.replaceAll("smallrye\\.config", "microprofile.config") :
    name));

Relocation can also be done with Expression expansion.

ExpressionConfigSourceInterceptor

The ExpressionConfigSourceInterceptor provides expression expansion on Configuration Values. An expression string is a mix of plain strings and expression segments, which are wrapped by the sequence ${ …​ }.

For instance, the following configuration properties file:

my.prop=1234
expression=${my.prop}

Then the expression configuration will be resolved and expanded to the value 1234.

Additionally, the Expression Expansion engine supports the following segments:

  • ${expression:value} - Provides a default value after the : if the expansion doesn’t find a value.

  • ${my.prop${compose}} - Composed expressions. Inner expressions are resolved first.

  • ${my.prop}${my.prop} - Multiple expressions.

If an expression cannot be expanded and no default is supplied a NoSuchElementException is thrown.

Expression expansion may be selectively disabled with the API io.smallrye.config.Expressions#withoutExpansion(java.lang.Runnable).

Config Priority over Profiles

A ConfigSource with the highest priority, that defines my.prop will take priority over another low priority ConfigSource that defines %dev.my.prop. This allows overriding profiles properties regardless of the active profile.

ProfileConfigSourceInterceptor

The ProfileConfigSourceInterceptor supports the Profiles feature.

FallbackConfigSourceInterceptor

The FallbackConfigSourceInterceptor allows to fallback to another configuration name, by providing a transformation function or just a simple key value map.

Consider when a configuration name does not exist, but there might be another configuration name that the config can fallback to provide the same expected behavior. The fallback function is only applied if the original resolved configuration name is not found and resolved to the fallback name.

The following FallbackConfigSourceInterceptor can fallback configuration names in the microprofile.config namespace to the smallrye.config namespace:

new FallbackConfigSourceInterceptor(
    name -> name.startsWith("microprofile.config") ?
    name.replaceAll("microprofile\\.config", "smallrye.config") :
    name));

LoggingConfigSourceInterceptor

The LoggingConfigSourceInterceptor logs lookups of configuration names in the provided logging platform. The log information includes config name and value, the config source origing and location if exists.

The log is done as debug, so the debug threshold must be set to debug for the io.smallrye.config appender to display the logs.

SecretKeysConfigSourceInterceptor

The SecretKeysConfigSourceInterceptor supports the Secret Keys feature.