MicroProfile Config for injecting configuration properties

Last Updated:  October 11, 2020 | Published: August 17, 2019

Injecting configuration properties like JDBC URLs, passwords, usernames, or hostnames from external sources is a common requirement for every application. Inspired by the twelve-factor app principles you should store configuration in the environment (e.g. OS environment variables or config maps in Kubernetes). These external configuration properties can then be replaced for your different stages (dev/prod/test) with ease. Using MicroProfile Config you can achieve this in a simple and extensible way.

Learn more about the MicroProfile Config specification and how to use it in this blog post.

Specification profile: MicroProfile Config

  • Current version: 1.4
  • GitHub repository
  • Latest specification document
  • Basic use case: Inject configuration properties from external sources (like property files, environment, or system variables)

Injecting configuration properties

At several parts of your application, you might want to inject configuration properties to configure for example the base URL of a JAX-RS Client. With MicroProfile Config you can inject a Config object using CDI and fetch a specific property by its key:

In addition, you can inject a property value to a member variable with the @ConfigProperty annotation and also specify a default value:

If you don't specify a defaultValue, and the application can't find a property value in the configured ConfigSources, your application will throw an error during startup:

For a more resilient behavior, or if the config property is optional, you can wrap the value with Java's Optional<T> class and check its existence during runtime:

Furthermore, you can wrap the property with a Provider<T>  for a more dynamic injection. This ensures that each invocation of Provider.get() resolves the latest value from the underlying Config and you are able to change it during runtime.

For the key of the configuration property you might use the dot notation to prevent conflicts and separate domains: my.app.passwords.twitter.

Configuration sources

The default ConfigSources are the following:

  • System property (default ordinal: 400): passed with -Dmessage=Hello to the application
  • Environment variables (default ordinal: 300): OS variables like export MESSAGE=Hello
  • Property file (default ordinal: 100): file META-INF/microprofile-config.properties

Once the MicroProfile Config runtime finds a property in two places (e.g. property file and environment variable), the value with the higher ordinal source is chosen.

These default configuration sources should cover most of the use cases and support writing cloud-native applications. However, if you need any additional custom ConfigSource, you can plug-in your own (e.g. fetch configurations from a database or external service).

To provide you an example of a custom ConfigSource, I'm creating a static source that serves just two properties. Therefore you just need to implement the ConfigSource interface and its methods

To register this new ConfigSource you can either bootstrap a custom Config object with this source:

or add the fully-qualified name of the class of the configuration source to the org.eclipse.microprofile.config.spi.ConfigSource file in /src/main/resources/META-INF/services:

Using the file approach, the custom source is now part of the ConfigSources by default.

Configuration converters

Internally the mechanism for MicroProfile Config is purely Stringbased, typesafety is achieved with Converter classes. The specification provides default Converter for converting the configuration property into the known Java types: Integer, Long, Float, Boolean, Byte, Short, Character, Double and their primitive counterparts. Furthermore, you can also define a config value with the type java.lang.Class. All these built-in converters have the priority of 1.

In addition, there are built-in providers for converting properties into Arrays, Lists, Optional<T> and Provider<T>.

If the default Converter doesn't match your requirements and you want e.g. to convert a property into a domain object, you can plug-in a custom Converter<T>.

For example, I'll convert a config property into a Token instance:

The custom converter needs to implement the Converter<Token> interface. The converter method accepts a raw string value and returns the custom domain object, in this case, an instance of Token:

To register this converter you can either build your own Config instance and add the converter manually:

or you can add the fullyqualified name of the class of the converter to the org.eclipse.microprofile.config.spi.Converter file in /src/main/resources/META-INF/services:

Once your converter is registered, you can start using it:

YouTube video for using MicroProfile Config

Watch the following YouTube video of my Getting started with MicroProfile series to see MicroProfile Config in action:

You can find the source code for this blog post on GitHub.

Have fun using MicroProfile Config,

Phil

>