Usually developers have to create and deploy different versions of their application: For local development, testing, training, production, …
Different third-party and system dependencies for those different versions will preferably be configured via the container, e.g. data sources, JMS, topics, mail server, etc. However, most applications also contain several custom application properties such as the current version, mail addresses, images, templates, etc. Most of them may be static, but there are cases where you want to change application properties dynamically, i.e. without rebuilding the artifact.
In this article we will describe some approaches how this goal can be approached using the JBoss WildFly/EAP7 application server.
Approach 1: Bundled versions
You may configure your build tool (usually Maven) to build different versions of your application by using different resource paths containing the variant properties. That is, you build one artifact for local development, one for production, etc., each containing different property files.
This is usually configured via Maven profiles. The application code will look like this:
The disadvantages are obvious: You do not have to maintain one artifact, but many. For every change you have to rebuild and redeploy the application.
Approach 2: System properties
You may also use JVM system properties and change them upon startup:
./standalone.sh ... -Dapp.version=1.2.5p3 ...
So your application code may read the given value at runtime like this
String version = System.getProperty("app.version");
However, out of the box this works for String based properties only. Otherwise you will have to use indirections, e.g. by setting a system property containing a file path.
Approach 3: JNDI properties
WildFly also offers the possibility to configure system properties via the CLI. But more interestingly it allows to bind variables in the JNDI naming subsystem at runtime which then may be looked up by the application.
or more elegantly
@Resource(lookup ="java:global/myapp/props/app.version") private String version;
Approach 4: Create a module
The last approach is to create custom module, which contains the version-specific property files, images, … It is thus a variant of the first approach without its disadvantages.
Module in JBOSS/modules/myapp/main/module.xml
<module xmlns="urn:jboss:module:1.1" name="com.mycompany.myapp"> <resources> <resource-root path="./properties"/> ... </resources> </module>
This allows you to place various resources in the module directory while the application can load them dynamically via the class path (see approach 1). The deployed artifact just needs an additional XML descriptor (in META-INF/WEB-INF) jboss-deployment-structure.xml:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2"> <deployment> <dependencies> <module name="com.mycompany.myapp" export="true"/> ... </dependencies> </deployment> </jboss-deployment-structure>