Foojay Today

MicroProfile Config for Java SE

October 13, 2022

The MicroProfile Config specification is one of those attempts to create a specification around application configuration for the Java Enterprise world. In the past, there were already some other attempts within Java EE to define this specification for Java EE, but they were never finalised.

Currently, another attempt is in progress with Jakarta EE Config but since MicroProfile is closely related to Jakarta EE, it is the best available solution today. That is the reason why almost all Jakarta EE runtimes also support MicroProfile Config and the other specifications of the MicroProfile umbrella.

Although the MicroProfile Config specification is based on the Context and Dependency Injection specific actions (Jakarta CDI) there is a large part that covers programmatic retrieval of configuration values.

It is namely also the idea to use this config specification for the configuration of the runtime itself. This means it must also work, at least large parts of it, on plain Java SE.

We look a bit more in detail in this article about this plain Java SE aspect of MicroProfile config and 2 libraries that implement recent versions of the specification.

Programmatic access

The programmatic access of the Config object allows you to get the configuration values from the sources that are available for your application.

Config config = ConfigProvider.getConfig();

This Config object has methods to retrieve and convert a value from the environment.

String value = config.getValue("key", Integer.class);
Boolean flag = config.getOptionalValue("otherKey", Boolean.class);

The class type on the method determines the Converter that is used to transform the String value obtained from the ConfigSource to the desired type.

There are many Converters available by default but also Implicit Converters can be used if the specified class has a static method with a certain method signature or constructor with a String parameter.

You can also define converters yourself and define the order in which they are tried. The order is determined by the value specified in the @Priority, or a default value is assumed when not specified. Depending on the version of the MicroProfile config that is supported by the implementation, this Priority is the javax or jakarta one. See further on for some examples.

Converters are picked up through the ServiceLoader mechanism or can also be defined programmatically when using the ConfigBuilder. Have a look at the specification if you want to learn more about this.

@Priority
public class MyConverter implements Converter {
}

Supported features

Some MicroProfile Config implementations have split up their project into 2 parts. A part that only contains those features that can be used in Java SE, and another artifact that adds the CDI integration on top of the first part.

What features are supported when using the pure Java SE version?

  • ConfigSources, the 3 default implementations with their default ordinal values, and the possibility to define custom ones through the ServiceLoader mechanism.
  • Custom ConfigSourceProvider‘s can be loaded through the ServiceLoader mechanism.
  • Converter, the implicitly defined one as specified in the specification, and the possibility to define custom converters using the ServiceLoader mechanism.
  • Support for optional values
  • Support for expressions where a value is a result of combining other configuration values and constant expressions.
  • Support for Config Profile defining the application phase (dev, test, …) on the property and ConfigSource level.
  • Support for ConfigBuilder and creating custom Config instances.

Other like the @ConfigProperty and @ConfigProperties which clearly required the CDI engine to function, are not included in those artifacts.

Testing

How can you test code that makes use of the ConfigProvider? Since the Config is created once, for each Classloader, you might think it is difficult to have several tests where various values or the absence of a value for a key can be tested.

But you can actually work around this relatively easily. You can create a custom ConfigSource for your tests (don't forget to define it in a service loader configuration file) that retrieves values from a ThreadLocal Map. Resetting that map after each test allows you to define test values for each test separately and works also when you run tests in parallel.

The gist of that solution can be found in this Github gist.

Use Case

What are typical use cases for MicroProfile Config on Java SE? Defining configuration values can be important for any kind of application, not only web applications. So all applications that you have, might benefit from a proven reusable framework to define the configuration, not only when running web applications on a runtime.

  • Command line programs that perform some tasks and need some configuration can be implemented using MicroProfile Config.
  • JavaFX or programs using another desktop UI technology can also make use of this configuration system.

The implementations that I will discuss next, also support native compilation with GraalVM, so also your native compiled programs can make use of it.

Implementations

I cover two implementations that have an artifact available that cover the MicroProfile Config functionality that can run on pure Java SE.

SmallRye Config

The Configuration framework that is used within Quarkus and OpenLiberty can use on Java SE only. It is based on version 2.0 of the specification which is still using the javax namespace. You can make use of it in your application by adding the following dependencies to your project.

 <dependency>
    <groupId>io.smallrye.config</groupId>
    <artifactId>smallrye-config-core</artifactId>
    <version>2.12.0</version>
</dependency>

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>1.3.5</version>
</dependency>

The jakarta annotation api one is needed since the order of the converters is defined through the @Priority annotation as mentioned above and is not included within the core SmallRye config dependency.

Atbash MP Config

The Atbash Runtime product, a playground for the new Jakarta core profile, also has configuration support and can also be used in pure Java SE. This library is already based on the Jakarta namespace as it is intended to be used with Jakarta EE 9.1 and Jakarta EE 10. It is based on the Microprofile Config 3.0 specification.

You only need to add the following dependency to your Java SE project to have it available.

<dependency>
    <groupId>be.atbash</groupId>
    <artifactId>mp-config-se</artifactId>
    <version>1.0.1</version>
</dependency>

Conclusion

Configuration is a very important aspect of any application, not only your web application.

So almost all frameworks and java enterprise runtimes have already a solution available, but there is still nothing defined for Java SE.

There were a few attempts in the past but today, using a library that implements MicroProfile config, can be used on pure Java SE as an option.

In this article, we looked at what is supported on Java SE, how you can configure your project to make use of it, and showed an example of writing tests when using MicroProfile Config on Java SE.

Related Articles

View All
  • Evolution of Microservices

    For some time now, there has been an undeniable growth in interest for Microservices. The core concept itself, however, is not that new.

    Microservices are an architectural type that builds on (mostly) RESTful web services. Where RESTful web services, in general, can be used for just about anything, for instance, to expose an API to external users, Microservices are specifically dedicated to be independent business services that together form a suite of such services that make up an application.

    Read More
    Jadon Ortlepp profile
    Oct 23, 2020
  • How To Bring Your Java Microservices To The Cloud

    All companies are software companies, and businesses will always experience the challenge of keeping integrations between users and applications scalable, productive, fast, and of high quality.

    To combat this, cloud, microservices, and other modern solutions come up more and more in architectural decisions.

    Here is the question: Is Java prepared to deal with these diverse concepts in a corporate environment?

    Read More
    Jadon Ortlepp profile
    Jan 08, 2021
  • MicroProfile Metrics with Prometheus and Grafana

    In a distributed microservices architecture, it is important to have an overview of your systems in terms of CPU, memory management and other important metrics.

    This is called Observability, measuring the internal state of a system, in this case, the micro-services instances.

    The goal of MicroProfile Metrics is to expose monitoring data from the implementation in a unified way. It also defines a Java API so that the developer can define and supply his own values.

    Read More
    Jadon Ortlepp profile
    Dec 02, 2020

Author(s)

  • Avatar photo
    Rudy De Busscher

    Rudy loves to create (web) applications with the Jakarta EE platform and MicroProfile implementations. Currently, he is a Developer Advocate for MicroStream. He has implemented various projects in a team ... Learn more

Comments (0)

Your email address will not be published.

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Save my name, email, and website in this browser for the next time I comment.

Subscribe to foojay updates:

https://foojay.io/feed/
Copied to the clipboard