Manage application config with Commons Configuration
TweetPosted on Wednesday Feb 26, 2014 at 01:53PM in Technology
Environment
- Commons Configuration 1.10
- WildFly 8.0.0.Final
- Oracle JDK7u51
Why go this way?
Various portable ways are available for manage configurations of the Java EE application. such as:
- Configuration table in DB
- I guess it's not bad, but I feel that is bit tedious work to coding.
- There's a way to use this mechanism via Commons Configuration, but I haven't tried it yet.
- Custom JNDI resources
- I thought that it's most efficient at first, but negative points here:
- Badness of lookup performance.
- Editing JNDI resources is very annoying.
- I thought that it's most efficient at first, but negative points here:
So sometimes I'm thinking of any better way, and I found Commons Configurations[1]. notable capabilities of Commons Configuration are:
- Simple API
- Auto-reloading and saving mechanism provided
- Support of various formats and placement styles
So I'd try it.
Prepare sample project and related resources
Create a system property
- Create a system property which specifies the path of configuration file.
- I'm using WildFly so go with jboss-cli:
[standalone@localhost:9990 /] /system-property=app.config:add(value=/Users/kyle/app.properties) {"outcome" => "success"} [standalone@localhost:9990 /]
Create the properties file
- Location is same as “app.config” system property.
hoge=fuge
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.nailedtothex</groupId> <artifactId>config</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <failOnMissingWebXml>false</failOnMissingWebXml> </properties> <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>commons-configuration</groupId> <artifactId>commons-configuration</artifactId> <version>1.10</version> </dependency> </dependencies> </project>
Create an application-scoped bean
package org.nailedtothex.config; import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; import javax.inject.Named; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; @Named @ApplicationScoped public class AppConfigBean { private Configuration config; @PostConstruct void init() throws ConfigurationException { String path = System.getProperty("app.config"); PropertiesConfiguration propConfig = new PropertiesConfiguration(path); propConfig.setReloadingStrategy(new FileChangedReloadingStrategy()); config = propConfig; } public Configuration getConfig(){ return config; } }
- If you want to read the config at startup of application, I recommend that use of @javax.ejb.Singleton and @javax.ejb.Startup[2].
Create a servlet
- Get a configuration variable from singleton bean.
package org.nailedtothex.config; import java.io.IOException; import java.io.PrintWriter; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(urlPatterns = "/*") public class HelloServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Inject private AppConfigBean bean; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try (PrintWriter pw = response.getWriter()) { pw.write(bean.getConfig().getString("hoge")); } } }
Access via browser
- It needs only very small and clean code.
Check runtime reloading
Edit app.properties:
kyle-no-MacBook:~ kyle$ echo hoge=FUGE > app.properties kyle-no-MacBook:~ kyle$
Reload browser:
- I just reloaded the browser and I didn't do any other operations, but config was updated immediately.
Collaboration with CDI
- There's a way to inject properties to CDI managed bean at [2]. that must be useful.
XMLConfiguration
- XMLConfiguration is good for hierarchical configuration.
- It depended on Commons Collection so don't forget to add the dependency.
pom.xml
<dependency> <groupId>commons-configuration</groupId> <artifactId>commons-configuration</artifactId> <version>1.10</version> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.1</version> </dependency>
XmlTest.java
package org.nailedtothex.config; import java.util.Iterator; import java.util.List; import org.apache.commons.configuration.XMLConfiguration; public class XmlTest { public static void main(String[] args) throws Exception { XMLConfiguration config = new XMLConfiguration(); config.load(XmlTest.class.getResourceAsStream("/config.xml")); String backColor = config.getString("colors.background"); String textColor = config.getString("colors.text"); String linkNormal = config.getString("colors.link[@normal]"); String defColor = config.getString("colors.default"); int rowsPerPage = config.getInt("rowsPerPage"); List<Object> buttons = config.getList("buttons.name"); System.out.println(backColor); System.out.println(textColor); System.out.println(linkNormal); System.out.println(defColor); System.out.println(rowsPerPage); System.out.println(buttons); System.out.println(); Object o; Iterator it = config.getKeys("colors."); while(it.hasNext()){ System.out.println(it.next()); } } }
config.xml
<?xml version="1.0" encoding="UTF-8"?> <gui-definition> <colors> <background>#808080</background> <text>#000000</text> <header>#008000</header> <link normal="#000080" visited="#800080"/> <default>${colors.header}</default> </colors> <rowsPerPage>15</rowsPerPage> <buttons> <name>OK,Cancel,Help</name> </buttons> <numberFormat pattern="###\,###.##"/> </gui-definition>
Log
#808080 #000000 #000080 #008000 15 [OK, Cancel, Help] colors.background colors.text colors.header colors.link[@normal] colors.link[@visited] colors.default
References
Tags: javaee