YAML is a nice and readable format for configuration allowing to set your properties hierarchically making them organized and readable.
Let see how to use this format with Apache DeltaSpike @ConfigProperty
injections!
YAML is a nice and readable format for configuration allowing to set your properties hierarchically making them organized and readable.
Let see how to use this format with Apache DeltaSpike @ConfigProperty
injections!
When you develop an application relying on a container for its awesome features you often hit the fact you use several code bases to do the same thing. In the context of this post it will be the ciphering of the passwords in the configuration:
PasswordCipher
APIConfigFilter
APISo finally you end up having to maintain two ciphering solutions which makes hard to production teams to maintain the configuration without developpers.
DeltaSpike configuration is a very elegant configuration solution for CDI.
However to make it fitting your application you often need to integrate it:
There are generally three cases to add a custom configuration file:
In this post we will tackle the second one since mixing the last two solves generally the first one and the last one is mainly the same solution with some specific conversion logic I don’t want to enter in for this post.
So our goal will be to read the configuration from ${catalina.base}/conf/my-app.properties and add it in deltaspike properties.
To do so we just need deltaspike core:
<dependency> <groupId>org.apache.deltaspike.core</groupId> <artifactId>deltaspike-core-api</artifactId> <version>${deltaspike.version}</version> </dependency> <dependency> <groupId>org.apache.deltaspike.core</groupId> <artifactId>deltaspike-core-impl</artifactId> <version>${deltaspike.version}</version> </dependency>
Then we need to implement a custom org.apache.deltaspike.core.spi.config.ConfigSource
reading ${catalina.base} from the corresponding system properties (our implementation will have a fallback on openejb.base property for openejb embedded tests):
import org.apache.deltaspike.core.impl.config.PropertiesConfigSource; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; // uses ${base}/conf/my-app.properties as source public class MyConfigSource extends PropertiesConfigSource { public MyConfigSource() { super(loadProperties()); } public String getConfigName() { return "MyAppConfig"; } private static Properties loadProperties() { return new Properties() {{ final File config = new File( System.getProperty("catalina.base", System.getProperty("openejb.base", "")), "conf/my-app.properties"); if (config.isFile()) { try (final InputStream is = new BufferedInputStream(new FileInputStream(config))) { load(is); } catch (final IOException e) { throw new IllegalArgumentException(e); } } }}; } }
Then to “activate” it just create a META-INF/services/org.apache.deltaspike.core.spi.config.ConfigSource
containing our qualified class name.
To decrypt password DeltaSpike uses org.apache.deltaspike.core.spi.config.ConfigFilter
implementations. It has two methods:
For this post the decryption will just reverse the value but a real implementation can use any ciphering considered secured in your environment:
import org.apache.deltaspike.core.spi.config.ConfigFilter; public class MyConfigFilter implements ConfigFilter { @Override public String filterValue(final String key, final String value) { return isEncrypted(key) ? decrypt(value) : value; } @Override // filter passwords and secrets in logs public String filterValueForLog(final String key, final String value) { return isEncrypted(key) ? "xxxxxx" : value; } // for the sample just "reverse" the string but in real life use some encryption private String decrypt(final String value) { return new StringBuilder(value).reverse().toString(); } private boolean isEncrypted(final String key) { return key.contains("password") || key.contains("secret"); } }
As for ConfigSource and since this classes are used before CDI is started to configure DeltaSpike itself don’t forget to register the filter adding the fully qualified name in META-INF/services/org.apache.deltaspike.core.spi.config.ConfigFilter
.
Now if you set for instance in your configuration:
my.password = tset
And get my.password
injected:
@Inject @ConfigProperty(name = "my.password") private String pwd;
Then pwd
value will be test
:).
The code of this post can be found there: https://github.com/rmannibucau/deltaspike-config-example.
The interesting part is to understand deltaspike can be integrated with all kind of configuration and environment which is the main feature of a configuration API. Then you still get it integrated with CDI for free thanks to DeltaSpike @ConfigProperty
which makes your application simple and decoupled from your actual configuration system.
Having SCM information in the project is really interesting to dump them at startup for instance.
There are several ways to do it.
One easy is to use templating-maven-plugin and filter a .java with these information but it has several drawbacks:
DeltaSpike is now providing a Data module allowing to use interface or abstract classes as repositories for JPA (a bit like spring-data). It got recently a new feature aiming to support DTOs pattern.
I’ll just show how to use it on a simple “User” entity in this post.