Thursday 15 April 2010

Accessing properties file using Java and Spring.

You can save crosscutting data in a properties file for your Java application. This approach has been adopted by several application and consequently not unconventional to see various post related to this subject. And so today, after scratching my chin for thoughts on what to post, I decided to highlight slightly on this rather conventional approach.

Typical crosscutting details includes username, password, connection urls, MIME types etc. For Java applications, saving these data in a properties file avoid having to dig through your codes to re-factor changes, re-compile and hence deploy.

So if you are a beginner looking for 'How to' or an advance looking for a quick refresh, this is how it is done. First create a properties file and save it in your classpath. Typical properties file looks as shown below:
#File name is 'yourfile.properties'
#This file holds crosscutting details.

database.username=your username
database.password=your password
database.url=jdbc:mysql//your url

lang=eng
lang=ger
Core Java option
Then to access values within this properties file, you build a simple handler util as shown below with various helper functions to aid access the elements within the properties file.
public class PropsUtil
{
  private static Logger logger = Logger.getLogger(PropsUtil.class);
  private final static String file = "yourfile.properties";//Properties file name
  private static Properties props = null;

  /**
   * Find the properties file in the class path and load it.
   * @throws IOException
   */
  private static void loadPropertiesFromClasspath() throws IOException
  {
    props = new Properties();
    InputStream inputStream = PropsUtil.class.getClassLoader().getResourceAsStream(file);

    if (inputStream == null)
    {
      throw new FileNotFoundException("Property file '" + file + "' not found in the classpath");
    }
    props.load(inputStream);
  }

  /**
   * Look up a property from the properties file.
   * @param key The name of the property to be found
   * @return The value of the property
   */
  public static String getProperty(String key)
  {
    if (props == null)
    {
      try
      {
        loadPropertiesFromClasspath();
      }
      catch (Exception IOException)
      {
        logger.warn("Unable to load properties file.");
        return null;
      }
    }
    return props.getProperty(key);
  }

  /**
   * Look up a property from the properties file.
   * @param key The name of the property to be found
   * @return The value of the property
   */
  public static String getProperty(String key, String defaultValue)
  {
    if (props == null)
    {
      try
      {
        loadPropertiesFromClasspath();
      }
      catch (Exception IOException)
      {
        logger.warn("Unable to load properties file.");
        return null;
      }
    }
    return props.getProperty(key, defaultValue);
  }

  /**
   * Looks up the value of a key from the properties file and converts it to an integer.
   * @param key
   * @return The value of that key
   */
  public static int getIntProperty(String key)
  {
    String property = getProperty(key);

    if (property == null)
    {
      logger.warn("Could not load integer property " + key);
      return -1;
    }
    try
    {
      return Integer.parseInt(property);
    }
    catch (NumberFormatException nfe)
    {
      logger.warn("Invalid format for a number in properties file: " + property, nfe);
      return -1;
    }
  }
}
Using above util we can access the value of database.username in our file simply like this:
 String dbUser=PropsUtil.getProperty("database.username");//access using property name
 String dbUser=PropsUtil.getProperty("lang", "ger");//fetch match value using both property name and default value
Spring based
Another option is Spring base properties injection. It is common this days to adapt a common framework to wrap your application, one typical framework which has grown with strength over the years is Spring. Like other frameworks Spring comes packed with wrappers for almost anything your application is deemed to support, and one that this post is concern is wrapper for properties file.

PropertyPlaceholderConfigurer wrapper is the most common and easy properties file injector bean supported and used mostly by Spring based application. A typical usage is as straight forward as shown below:

   
 

 
  ${database.username}
 

Note the setting classpath:yourfile.properties assumes yourfile.propertie is located at your project classpath location src/main/resources.

Annotations option
Spring also provides you another wrapper for injecting properties into your bean using annotations. This makes it handy for accessing values at application level. For example classes which are not defined in your-app-context.xml as beans can still access this properties using annotations. Achieving this is as simple as adding below definition:
 
This provides access to the properties via simple constucts as demostrated in below class:
 public class Example
 {
  @Value("#{myAppProps['database.username']}")
  private String dbUser;
 
  public void foo()
  {
   System.out.println(dbUser);
  }
 }
So far you have seen how to construct a simple util class using Core Java to handlle properties file. You have also seen how easy to use Spring based support wrappers to handle properties within your application. Please do let me know if you have any suggestion or enchancement or if this post has helped you in some way.