DeltaSpike: new Configuration API!
DeltaSpike configuration is a de facto standard for "EE"/CDI configuration API. It provides a nice "source" abstraction allowing to integrate the configuration loading from any kind of company or user specific storage.
Until the last release the API was looking like:
@Inject
@ConfigProperty(name = "my.url", defaultValue = "http://server.com")
private String url;
Or
URL url = ConfigResolver.resolve("my.url")
.as(URL.class, new URLConverter())
.cacheFor(TimeUnit.SECONDS, 30)
.getValue();
It works great but not always very smooth for end users: ConfigResolver is powerful but direct injection is smoother. However this last one didn't enable to use the caching feature (avoiding to read the configuration for each access but leep updating it from time to time) and the converter feature.
With 1.8.0 it got enhanced significantly!
ConfigProperty got converters!
Now it is valid to do:
?@Inject
@ConfigProperty(name = "my.url", converter = MyUrlConverter.class)
private URL url;
And the bonus is MyUrlConverter can be a normal scoped bean (often an @ApplicationScoped instance).
Interface based configuration
The other new configuration is to support to create on the fly configuration Bean based on interfaces:
@Configuration
public interface MyAppConfig {
@ConfigProperty(name = "my.app.url", converter = MyUrlConverter.class)
URL url();
@ConfigProperty(name = "my.app.retries", defaultValue = "2")
int retries();
}
Nice thing with this new API are:
- it supports primitives compared to direct injections which can't use primitive due to CDI limitations
- it fully reuses the standard @ConfigProperty features (including converters)
- it design the configuration as a bean which makes the maintenance and configuration extraction easier for end users (if you do some living documentation on your configuration you will enjoy it!)
- not visible in previous snippet but it supports prefixing of all keys (see next sample)
- it supports caching (see next snippet)
Completely configured you can do:
@Configuration(prefix = "my.app", cacheFor = 30, cacheUnit = TimeUnit.SECONDS)
public interface MyAppConfig {
@ConfigProperty(name = "url", converter = MyUrlConverter.class)
URL url();
@ConfigProperty(name = "retries", defaultValue = "2")
int retries();
}
And the usage? Simply:
@Inject
private MyAppConfig appConfig;
CDI sources and filters
Until recently ConfigSource (entries providers) and ConfigFilter (how to decrypt/tranform values) were not taken from CDI context and therefore were not CDI beans. Most of the time they were taken from the plain Java SE ServiceLoader and just plain java classes. Sometimes it is hard to use or enforce you to rely on BeanProvider (and some trick cause of boot lifecycle) to be able to bridge to your business code and a JPA repository for instance.
Now you can decorate a ConfigSource with @Source and a ConfigFilter with @Filter to automatically add the related normal scoped CDI beans once CDI is started (means they will not be active for Extension configuration but for the whole application configuration it will). This can look like a limitation but actually most of the time that's what we do and the Extension configuration is often just a kind of "hardcoded" configuration you can consider as an internal of the application so it is not that impacting to not rely on an advanced source to read it - at least it is acceptable.
Conclusion
Even if globally just syntax sugar, these new features makes DeltaSpike configuration far more efficient and smoother to use and the end user code is now easier to maintain. There are still a lot of potential enhancements like defaulting keys in the interface based configuration, defining the sources in this same interface, defining with java 8 an event to react on configuration reloading etc... but it already enables a lot of use cases for a cheap investment in term of API so don't hesitate to test it.
From the same author:
In the same category: