Microprofile Config and Proxy based configuration?
Microprofile Configuration provides a way to handle configuration in CDI applications.
Concretely it allows to use a configuration abstraction - called Config - which is filled from ConfigSource, and therefore is extensible, to configure any part of your application but also CDI extensions. This sounds trivial but since an extension is executed before CDI is really active it is already a problem solved!
The API is inspired from mainstream configuration API like Spring Configuration or Apache DeltaSpike config. It looks like:
@ApplicationScoped
public class AppConfig {
@Inject
@ConfigProperty(name="app.port")
private Integer port;
@Inject
@ConfigProperty(name="app.host")
private String host;
}
This is not bad but has a few downsides:
- When you inject primitives you don't get them updated at any time
- It kind of encourage to put config anywhere and doesn't structure the configuration
- It doesn't allow to add features under the hood for free, for instance if you want to add some caching on the values and some hot reloading, then you need to scope your bean with an adapted scope (@Refreshed for instance)
An alternative programming model exists in the configuration ecosystem and is based on proxies. Long story short, the idea is to make an interface and each method a configuration entry:
public interface AppConfig {
@ConfigProperty(name="app.port")
Integer port();
@ConfigProperty(name="app.host")
String host();
}
It looks pretty close to previous solution but requires to inject the config to be used:
@ApplicationScoped
public class MyApp {
@Inject
private AppConfig config;
}
Not a big deal right? Now the implementation can do a lot for you:
- Reload the keys when needed and ensure the refreshing is consistent for all the keys (would be sad to have the old port but new host for instance)
- Make your configuration bean managed through JMX
- Have statistics on the configuration usage
- Route the configuration depending the current tenant
- ...
All that is possible because the implementation is decoupled from the usage and stay dynamic.
Apache Geronimo Config which is one of the Microprofile Config implementation is able to handle this kind of configuration. Microprofile is getting updates hooks to be able to refresh key/values when needed and consistently (the host/port example I talked about earlier) so it will be key for application to benefit from it for free.
As you can see the proxy API is only dependent on the standard API of Microprofile Config so with very few effort already usable. Of course, once it gets added to Microprofile Config itself, it will probably get a @Configuration annotation you can put on the interface to specify a global prefix but it is not a big deal to handle in practise.
Side note: @ConfigProperty can be put on the interface but it is weird to have a default value here, this is why another API can make more sense.
If you are interested in the implementation you can grab it on github and the required wiring is mainly just observing annotated types with @ConfigProperty annotation and if it is an interface bind a proxy created with previous handler in the CDI beans.
Last tip: with such interfaces it is very trivial to generate the documentation for your configuration: you grab you class, iterate over its method, extract @ConfigProperty and generate some nice asciidoctor file with the property name and its default. If you want to be fancy you can add a @Documentation(String) annotation to add a smart description but at least all keys will be easy to extract :).
From the same author:
In the same category: