SmallRye Config 1.8 Released
SmallRye Config version 1.8 was released a few days ago.
The latest version of SmallRye Config introduced a few experimental changes to enhance the API and to make SmallRye Config more extensible. One of the experimental changes is the new interceptor model, to intercept the lookup of a configuration value.
The ConfigSourceInterceptor
The ConfigSourceInterceptor
allows to intercept the resolution of a configuration name before the Config
resolves
the configuration value and before any conversion taking place. This is useful to implement features like
property expansion or configuration profiles.
Implementations of ConfigSourceInterceptor
are loaded via the java.util.ServiceLoader
mechanism and can be
registered by providing a resource named META-INF/services/io.smallrye.config.ConfigSourceInterceptor
, which
contains the fully qualified ConfigSourceInterceptor
implementation class name as its content.
A single method must be implemented, 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
.
public interface ConfigSourceInterceptor extends Serializable {
ConfigValue getValue(ConfigSourceInterceptorContext context, String name);
}
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 or configuration
values with the methods Iterator<String> iterateNames(ConfigSourceInterceptorContext context)
and
Iterator<ConfigValue> iterateValues(ConfigSourceInterceptorContext context)
.
The Interceptor chain applies before any conversion takes place.
Implementation
With the Interceptor API, it becomes trivial to implement a logging mechanism and to find out which ConfigSource
loaded the resolved config:
public class LoggingConfigSourceInterceptor implements ConfigSourceInterceptor {
private static final Logger LOG = Logger.getLogger("io.smallrye.config");
@Override
public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) {
final ConfigValue configValue = context.proceed(name);
final String key = configValue.getName();
final String value = configValue.getValue();
final String configSource = configValue.getConfigSourceName();
LOG.infov("The key {0} was loaded from {1} with the value {2}", key, configSource, value);
return configValue;
}
}
SmallRye Config does ship with its own logging interceptor, so you don’t need to implement one.
Built-In Interceptors
SmallRye Config provides the following built-in interceptors to expand its feature set:
-
RelocateConfigSourceInterceptor
-
ProfileConfigSourceInterceptor
-
ExpressionConfigSourceInterceptor
-
FallbackConfigSourceInterceptor
-
LoggingConfigSourceInterceptor
-
SecretKeyConfigSourceInterceptor
Not every interceptor is registered by default. Only the ProfileConfigSourceInterceptor
,
ExpressionConfigSourceInterceptor
and SecretKeyConfigSourceInterceptor
are added on new instances of Config
.
Other interceptors require manual registration via the ServiceLoader
mechanism.
To learn more about all the built-in interceptors, please refer to the documentation page.
Expression Expansion
The ExpressionConfigSourceInterceptor
provides expression expansion on configuration values. An expression string is
a mix of plain strings and expression segments, which are wrapped into ${ … }
.
For instance, consider 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.
Configuration Profiles
The ProfileConfigSourceInterceptor
allows multiple configurations with the same name and selects them via
a profile property.
To be able to set properties with the same name, each property needs to be prefixed with %
followed by the profile
name and a dot:
my.prop=1234
%dev.my.prop=5678
Lookup is always performed with the my.prop
property name. To use the profile dev
, the configuration
smallrye.config.profile=dev
has to be set in any valid ConfigSource
.
When looking up the property my.prop
with the dev
profile active, the value is 5678
.
Only one profile can be active at any given time.
API Enhancements
Aside from interceptors, a few additional API enhancements shipped with the latest version of SmallRye Config:
-
ConfigValue
- The ConfigValue is a metadata object that holds additional information after the lookup of a configuration. -
ConfigValueConfigSource
- Extends the originalConfigSource
to expose methods that return aConfigValue
. -
SmallRyeConfigBuilder#withSecretKeys
- Hide configuration properties that contain passwords or other kinds of secrets to prevent accidental exposure of such values.
Summary
All the new features detailed here are experimental. The team is happy with them, and they had careful consideration when designed. We cannot guarantee that they won’t suffer any changes in the next few releases, especially considering that the SmallRye team is also pushing to have these added to the MicroProfile Config specification, which may require some changes.
This shouldn’t discourage developers to use these new features. We believe these add a lot of utility and improve the developer experience regarding configuration of applications.
Please, feel free to drop us any feedback in the SmallRye Mailing List.