Recent Additions in MicroProfile Config 1.1

Photo of Ondro Mihályi by Ondro Mihályi

Configuration is an important aspect of programming. However, a standard approach to it has been missing in Java for a long time. A year ago, the MicroProfile project decided to change that. I'm glad I could be part of it and help design the new API. One year later, a common configuration API aiming to set a standard is a reality, with several released versions and multiple projects that provide it. Payara Server and Payara Micro have supported MicroProfile Config API since version 4.1.2.173. We added support for Config 1.1 in version 4.1.2.174 and completed the support for all Eclipse MicroProfile 1.2 features in version 4.1.2.181. So let's summarize what's new since Config 1.0.

 

First things first

MicroProfile Config is an API created collaboratively by multiple parties within the MicroProfile initiative in 2017. It's already provided by multiple implementations. But the API isn't set in stone. It's evolving at a steady pace while adding new and improving existing features.

 

The main goal is to allow developers consuming configuration values easily, both with plain Java code and injecting them into CDI beans. Therefore reading a value takes only a single line of code:

 

String defaultProperty = ConfigProvider.getConfig().getValue("property", String.class);

 

Injecting a configuration value is also as easy:

 

@Inject @ConfigProperty(name = "property")
String defaultProperty;

 

Some default values may be provided but it's completely optional. The power of MicroProfile Config is in its flexible mechanism of providing the configuration from the environment without changing the application. Configuration may be provided by system properties and environment variables. On top of that, Payara Server and Payara Micro provide additional configuration sources which enable sharing configuration among members of a cluster, reading the configuration from a directory compatible with Kubernetes (added in version 4.1.2.181) and a lot more. If that's not enough, an application can extend this by implementing the ConfigSource interface and provide its own configuration sources.

 

Default name in injection point

In MicroProfile Config 1.1, the ConfigProperty annotation has a new attribute defaultValue. It specifies a value to be used if no other value is provided at all:

 

@Inject
@ConfigProperty(name = "default.property", defaultValue = "Default Value")
String defaultProperty;

 

This will have 2 effects:

  • if no value for the key "default.property" is found then the value "Default value" will be injected after converting it to the appropriate Java type if needed
  • providing the value during deployment is optional and deployment will never complain about a missing configuration value for the key "default.property"

The second point is less obvious but important. MicroProfile Config requires that deployment should fail if a configuration value to be injected isn't specified. This is very useful to detect missing configuration and avoid runtime exceptions later. But it's sometimes undesirable. Adding a default value means that the value will always be defined and thus any other configuration is optional.

 

Setting a default value was possible even earlier by providing the value in the file microprofile-config.properties inside the application. But the new defaultValue attribute makes it much easier to set the default value right where it's used. And while values set in the properties file are global for the application, default values set in an annotation are used only for the particular injection point.

 

More default converters

Apart from the list of object types supported initially, also primitive types and java.net.URL can be directly used out of the box in version 1.1. Payara Server and Payara Micro also support java.net.InetAddress. All other types require a converter in the application, which is just a single class registered via a simple service file.

Here's an example of how using the newly supported types looks like:

 

// Example injection of a primitive type
    @Inject @ConfigProperty(name ="application.numberOfWorkers", defaultValue = "10")
    int numberOfWorkers;
 
// Example injection of a URL object automatically converted from String
    @Inject @ConfigProperty(name = "application.url", defaultValue = "http://localhost")
    URL url;
 
// Example injection of an InetAddress object supported by Payara on top of the MicroProfile Config specification
    @Inject
    @ConfigProperty(name = "application.address", defaultValue = "10.0.0.1")
    InetAddress inetAddress;

 

The same types can be retrieved with the programmatic API:

 

int numberOfWorkers = ConfigProvider.getConfig().getValue("application.numberOfWorkers", Integer.class)
 
URL url = ConfigProvider.getConfig().getValue("application.url", URL.class);
 
// supported by Payara on top of the MicroProfile Config specification
InetAddress inetAddress = ConfigProvider.getConfig().getValue("application.address", InetAddress.class);

 

Directory config source for Kubernetes

On top of what is specified by MicroProfile Config, Payara server and Payara Micro in version 4.1.2.181 provide a config source to support configuration stored as a file per configuration value in a directory. This is a very common format of  configuration available in containerized environments like Docker and Kubernetes. The content of each file in a directory represents a value and the name of the file is the key. Therefore a configuration for the key "application.numberOfWorkers" would be stored in a file with the same name and containing just the configuration value as text, such as "10".

 

Both Kubernetes Configmaps and Kubernetes Secrets provide values in this format and the new config source allows to consume them out of the box. This config source shows our desire to bring innovative and useful features into Payara Server and Payara Micro. As members of the MicroProfile project, we hope to bring this feature into the common MicroProfile API so that it can be used also when building portable applications.

 

Try it yourself

Though MicroProfile Config 1.1 isn't a big leap over the previous version it adds some nice features to make the life of a developer easier. To dive deeper, you may explore an example config-injection application and experiment with it in Payara Examples repository. The code provides examples for most of the features available in MicroProfile Config up to version 1.1 as well as features provided only by Payara Server and Payara Micro.

 

And if you like what you see, let us know. You may also provide feedback on the MicroProfile project mailing list or raise an issue on the MicroProfile Config issue tracker to help the next version be even better!

 

Comments