Config Source Factory#
Another way to create a ConfigSource
is via the ConfigSourceFactory
. The difference between the SmallRye Config
Factory and the standard way to make a ConfigSource
as specified in MicroProfile Config is the Factory’s ability to
provide a context with access to the available configuration. With the ConfigSourceFactory
it is possible to
bootstrap a ConfigSource
that configures itself with previously initialized ConfigSource's
.
By implementing
ConfigSourceFactory,
a list of ConfigSource's
may be provided via the Iterable<ConfigSource> getConfigSources(ConfigSourceContext context)
method. The ConfigSourceFactory
may also
assign a priority by overriding the default method OptionalInt getPriority()
. The priority only sorts the factories
during initialization. After initialization, the provided ConfigSources
will use their own ordinal and sorted with
all ConfigSources
available in the Config
instance.
When the Factory initializes, the provided ConfigSourceContext
may call the method
ConfigValue getValue(String name)
. This method looks up configuration names in all ConfigSource's
already
initialized by the Config
instance, including sources with lower ordinals than the ones defined in the
ConfigSourceFactory
. The ConfigSourceFactory
does not consider ConfigSources's
provided by other
ConfigSourceFactory's
(the priority does not matter).
Registration of a ConfigSourceFactory
is done via the ServiceLoader
mechanism by providing the
implementation classes in a META-INF/services/io.smallrye.config.ConfigSourceFactory
file. Alternatively, factories
may be registered via the Programmatic API in SmallRyeConfigBuilder#withSources
.
A ConfigSourceFactory
requires an implementation of io.smallrye.config.ConfigSourceFactory
. Each implementation
requires registration via the ServiceLoader
mechanism in the
META-INF/services/io.smallrye.config.ConfigSourceFactory
file. Alternatively, interceptors may be registered via the
Programmatic API in SmallRyeConfigBuilder#withSources
.
package org.acme.config
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import org.eclipse.microprofile.config.spi.ConfigSource;
import io.smallrye.config._private.ConfigMessages;
import io.smallrye.config.PropertiesConfigSource;
import io.smallrye.config.ConfigSourceContext;
import io.smallrye.config.ConfigSourceFactory;
import io.smallrye.config.ConfigValue;
public class FileSystemConfigSourceFactory implements ConfigSourceFactory {
@Override
public Iterable<ConfigSource> getConfigSources(final ConfigSourceContext context) {
final ConfigValue value = context.getValue("org.acme.config.file.locations");
if (value == null || value.getValue() == null) {
return Collections.emptyList();
}
try {
return List.of(new PropertiesConfigSource(toURL(value.getValue()), 250));
} catch (IOException e) {
return Collections.emptyList();
}
}
private URL toURL(final String value) {
try {
return new URI(value).toURL();
} catch (URISyntaxException | MalformedURLException e) {
throw ConfigMessages.msg.uriSyntaxInvalid(e, value);
}
}
}
And registration in:
org.acme.config.FileSystemConfigSourceFactory
The FileSystemConfigSourceFactory
look ups the configuration value for org.acme.config.file.locations
, and uses it
to set up an additional ConfigSource
.
Alternatively, a ConfigurableConfigSourceFactory
accepts a ConfigMapping
interface to configure the ConfigSource
:
@ConfigMapping(prefix = "org.acme.config.file")
interface FileSystemConfig {
List<URL> locations();
}
public class FileSystemConfigurableConfigSourceFactory implements ConfigurableConfigSourceFactory<FileSystemConfig> {
@Override
public Iterable<ConfigSource> getConfigSources(ConfigSourceContext context, FileSystemConfig config) {
}
}
With a ConfigurableConfigSourceFactory
it is not required to look up the configuration values with
ConfigSourceContext
. The values are automatically mapped with the defined @ConfigMapping
.