Friday, June 5, 2009

Reading Property Files Efficiently In Java and JSP files


Described below is an efficient way of reading configurations from property files in a web application. It uses a class called AppConfigMaster to read all property files available at a directory location specified as a JVM argument. All key value pairs read from the property files are fed into a HashMap object, which is defined as a data member of the AppConfigMaster class. A singleton of this AppConfigMaster is maintained in the JVM so that the properties are read from the file system only once in a JVMs lifecycle.

AppConfigMaster.java

public class AppConfigMaster {

      private static AppConfigMaster AppConfigMasterObj;
      private Map configPropertiesMap = new HashMap();
      public static String configurationFilesPath = null;

      AppConfigMaster() throws SystemException {
            try {
                  configurationFilesPath = System.getProperty("ApplicationConfigPath");
                  navigateConfigDirectory(configurationFilesPath);
            } catch (Exception ex) {
                   //Do Something
            }
      }

      public synchronized static AppConfigMaster getInstance() {
            if (AppConfigMasterObj == null) {
                  try {
                        AppConfigMasterObj = new AppConfigMaster();
                  } catch (SystemException e) {
                        e.printStackTrace();
                  }
            }
            return AppConfigMasterObj;
      }

      private void navigateConfigDirectory(String path) throws SystemException {

            File configurationDirectiory = new File(path);
            File[] subdirectories = null;

            if ((configurationDirectiory.isDirectory())
                        && (configurationDirectiory.exists())) {
                  subdirectories = configurationDirectiory.listFiles();
                  FilenameFilter propertiesFileFilter = new OnlyExt("properties");
                  int configDirLength = configurationDirectiory.listFiles(propertiesFileFilter).length;
                  for(int i=0;i
                propertiesFileProcessor(configurationDirectiory.listFiles(propertiesFileFilter)[i]);
                 
                  /*
                   * Assuming there are just 2 levels of nesting
                   */
                  for (int i = 0; i < subdirectories.length; i++) {
                        if (subdirectories[i].isDirectory()) {
                              for (int j = 0; j < subdirectories[i].list(propertiesFileFilter).length; j++) {
                                    propertiesFileProcessor(subdirectories[i].listFiles(propertiesFileFilter)[j]);
                              }
                        }
                  }
            }
      }

      class OnlyExt implements FilenameFilter {
            String ext;

            public OnlyExt(String ext) {
                  this.ext = "." + ext;
            }

            public boolean accept(File dir, String name) {
                  return name.endsWith(ext);
            }
      }

      private void propertiesFileProcessor(File file) throws SystemException {
            Properties configProprties = new Properties();
            FileInputStream inputstream;
            String key = null;
            String value = null;

            try {
                  inputstream = new FileInputStream(file.getAbsolutePath());
                  configProprties.load(inputstream);
                  Enumeration keys = configProprties.keys();

                  while (keys.hasMoreElements()) {
                        key = (String) keys.nextElement();
                        value = configProprties.getProperty(key.toString());
                        configPropertiesMap.put(key, value);
                  }
            } catch (FileNotFoundException e) {
                  //Do Something
            } catch (IOException e) {
                  //Do Something
            } catch (Exception e) {
                  //Do Something
            }
      }

      public String getPropertyforkey(String key) {
            try {
                  if (configPropertiesMap.containsKey(key))
                        return configPropertiesMap.get(key).toString();
                  else
                        //Do Something
            } catch (ClassCastException cex) {
                  //Do Something
            } catch (NullPointerException npex) {
                   //Do Something
            }
            return null;
      }

      public String reloadProperties() throws SystemException {
            String retMessage = null;
            try {
                  navigateConfigDirectory(configurationFilesPath);
                  retMessage = "Reload of properties Successful";
            } catch (SystemException ex) {
                  retMessage = "Reload of properties unsuccessful";
                  //Do Something
            }
            return retMessage;
      }
}

The class is then used in other class files that need to read key values from property file as below:

AppConfigMaster.getInstance().getPropertyforkey("artbody.html.imagespanclasss.right");

To use it in JSP files without using scriplets following additional wrapper class and tag file are used:

AppConfigUtil.java

public class AppconfigUtil {
     
      private String key;
      private String value;
     
      public void setKey(String key) {
            this.key = key;
      }
      public String getValue() {
            value = AppConfigMaster.getInstance().getPropertyforkey(key);
            value = (value == null)?"":value;
            return value;
      }
}

/WEB-INF/tags/getProperty.tag

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
<%@ tag import="com.util.AppconfigUtil"%>
<%@ attribute name="property" required="true"%>
<%@ attribute name="id" required="true"%>

<jsp:useBean id="appconfig" class="com.util.AppconfigUtil">
      <jsp:setProperty name="appconfig" property="key" value="${property}" />
jsp:useBean>
<bean:define id="value" name="appconfig" property="value" />
<%request.setAttribute(id,value);%>

Usage in a JSP file is illustrated below

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib tagdir="/WEB-INF/tags" prefix="appConfig"%>

<appConfig:getProperty property="publication.name" id="pub_name"/>
<appConfig:getProperty property="site.url" id="site_url"/>


<b><c:out value="${site_url}"/></b> 


NOTE
To prevent key name conflicts, all key names used in various property files should follow some agreed naming convention. Name space conflicts can cause logical errors otherwise.


Bookmark and Share

0 comments:

Post a Comment