Sunday, November 4, 2012

Parse XML and Properties config files

       .xml(Extensible Markup Language) and .properties is a file extension for files mainly used in Java related technologies to store the configurable parameters of an application.(.properties files can also be used for storing strings for Internationalization and localization - these are known as Property Resource Bundles.)

       Let's first start with XML config files. There are many XML parser technologies, but I will show how u can use Apache Commons Configuration library to parse and use XML config files.

       The Commons Configuration software library provides a generic configuration interface which enables a Java application to read configuration data from a variety of sources:


  • Properties files
  • XML documents
  • Windows INI files
  • Property list files (plist)
  • JNDI
  • JDBC Datasource
  • System properties
  • Applet parameters
  • Servlet parameters
For example we have databases.xml file in our "com.handysofts.xml.parsing" package and we want parse and use this data.
<?xml version="1.0" encoding="UTF-8"?>

<databases>
 <database name="dev">
     <type>test</type> 
     <url>127.0.0.1</url>
     <port>3306</port>
     <user>juve</user>
     <pass>123</pass>
 </database>
 <database name="production">
     <type>main</type>
     <url>31.170.162.34</url>
     <port>3306</port>
     <user>admin</user>
     <pass>7bHU*]nJdj</pass>
 </database>
</databases>

Create new class file and get config file object:
XMLConfiguration config = new XMLConfiguration(DatabaseConfig.class.getClassLoader().getResource("com/handysofts/xml/parsing/databases.xml"));
Now if we want get develeopment db's url we must write following code part:
// 127.0.0.1
config.getString("databases.database(0).url"); 
As you can see to fetch consecutive values we used zero-based index inside parantheses, i.e. databases.database(1).url maps to the second node inside the databases parent.
Dot notation is nice, but works only in simple cases. For complex, real-life situations a better solution may be to use the XPath expression language. The main advantage here is that you can write advanced queries against XML, while still being concise. Here is how you could rewrite the previous snippet:
config.setExpressionEngine(new XPathExpressionEngine());
// 127.0.0.1
config.getString("database[@name='dev']/url")
/* or we can find db by child node value like following:
 * 127.0.0.1
*/
config.getString("database[type='test']/url")
Let me show db connection string builder :)
HierarchicalConfiguration dbProdConfs = config.configurationAt("database[type='main']");
StringBuilder sb = new StringBuilder();
sb.append("jdbc:mysql://"+dbProdConfs.getString("url")+":");
sb.append(dbProdConfs.getInt("port")+"/");
sb.append(dbProdConfs.getString("@name")+"?useUnicode=true&characterEncoding=UTF-8");
sb.append("&user="+dbProdConfs.getString("user"));
sb.append("&password="+dbProdConfs.getString("pass"));

/* Connection String 4 production server: jdbc:mysql://31.170.162.34:3306/production?useUnicode=true&characterEncoding=UTF-8&user=admin&password=7bHU*]nJdj */
System.out.println("Connection String 4 production server: "+sb.toString());
But properties config reader so simple:
// mail.properties file data: mail.host=http://mail.handysofts.com
Configuration config = new PropertiesConfiguration("com/handysofts/prop/parsing/mail.properties");

String mailHost = config.getString("mail.host");
// http://mail.handysofts.com
System.out.println(mailHost);
Apache Commons is my personal choice for the configuration-related code. I hope this article convinced you, that this framework may provide a very useful interface to your static data. What needs to be mentioned at the end is that not all features were covered in this article. Among many interesting are the abilities of the framework to:

  • load your configuration from different sources like properties files, ini files, a database, etc.
  • add new values to the configuration and save it back to the source it came from
  • listen for the configuration change event
  • automatically resolve the actual path to the configuration files (it does not matter whether you put them inside a jar or in the application folder)
I hope you enjoyed reading my text. Please, feel free to leave a comment.

No comments:

Post a Comment