You are on page 1of 6

Chapter 4 – Logging and Configuration, Part II

Common Property File


Often, it is nice to use an external property file (aka, declarative approach) for your web
application. It is more flexible over coding start-up parameters inside you application
(programmatic approach). I list some of those benefits below.
1. Allowing application reconfiguration without recompilation.
2. Easy to visually inspect what are the initialization parameters for your application.
3. Allowing you to set up test instances of your application.

There are several different ways to load a common property files. I list the pros & cons below.

Method Pros Cons


1. Portal VarPacks 1. Easy to use 1. Tightly coupled with the
2. No dependency on external portal. (Not vendor
libraries neutral)
3. Native to the portal 2. Lack of hierarchy, only
goes two levels deep.
3. Application cannot live
outside of the portal
context.
2. Jakarta Commons 1. Easy to use 1. Depends on several
Configuration 2. Proven technology & well external libraries (Jakarta
Framework (Java) accepted Commons Configuration,
3. Supports a variety of file Jakarta Commons
formats, e.g. property file, XML Collection, and Jakarta
file, JNDI, etc. Commons Lang).
4. Has a clear documentation
5. Has a defined strategy for
loading and setting properties.
3. Custom Property 1. Moderate effort to write. 1. Requires custom coding
File Loader 2. No need for external library. 2. Need post-production
3. You know your code support
4. AMS Profile 1. Easy to use 1. Depends on an external
Configurator (.Net) 2. Support a variety of library.
configuration files, INI, XML, 2. No cross platform support,
registry, … only .Net.
3. Automatic reload upon file
modification.

We will discuss 2 – 4 because BEA EDocs provides a pretty good coverage on how to use Portal
Varpacks.1

1
BEA EDocs on how to use VarPacks.
http://edocs.bea.com/alui/devdoc/docs60/Customizing_the_Portal_UI/Using_Varpacks/PlumtreeDevDoc_Customizi
ng_VarPack_SampleUses.htm
1
1 A Custom Property File Loader (Java)
If you read the previous chapter on Logging, you remember that you can add application
environment variables in a web application’s configuration files. For Java platform, it is the
web.xml file. For .Net platform, it is the web.config file.
See my example “logging_and_common_property”.

<?xml version="1.0" encoding="UTF-8"?>


<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<description>InitServlet</description>
<servlet-name>InitServlet</servlet-name>
<servlet-class>InitServlet</servlet-class>
<init-param>
<description>globalconfig file</description>
<param-name>global_config_file</param-name>
<param-value>\\WEB-INF\\globalconfig.properties</param-value>
</init-param>
</servlet>
(other stuff)
</web-app>
Web.xml

//Add following lines to our InitServlet class.


//reading global configuration file
try {
System.out.println("Loading global configuration file.");
String gcf = config.getInitParameter("global_config_file");
String gcf2 = config.getServletContext().getRealPath(gcf);
Konfig.getInstance().initialize(gcf2);
} catch (Exception ex) {
logger.info("A problem with reading global property file has
occured.");
logger.info(ex.getStackTrace());
}
Modified InitServlet Class

/*
* Konfig.java
*/

package logging;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.Enumeration;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.FileWatchdog;

/**
*
* @author rgao

2
*/
public class Konfig extends Properties {
private static boolean initialized = false;
private static Konfig instance;
private static Logger logger = Logger.getLogger(Konfig.class);
private KonfigWatchdog kdog;

/** Creates a new instance of Konfig */


private Konfig() {
}

public void initialize(String konfigfile) throws Exception {


//Dynamic reloading the property file without restarting application.
kdog = new KonfigWatchdog(konfigfile);
kdog.setDelay(KonfigWatchdog.DEFAULT_DELAY);
kdog.start();
}

private void doInitialize(String konf) throws Exception {


if (initialized == false) {
if(konf == null || konf.length() == 0 || !(new
File(konf)).isFile()) {
logger.info(
"ERROR: Invalid configuration file. Please check the
init param in web.xml");
throw new Exception("The global config file is not valid.");
}
//clears existing property index.
clear();
BufferedInputStream bis = new BufferedInputStream(new
FileInputStream(new File(konf)));
load(bis);
bis.close();
logger.info("---The list of global properties----");
Enumeration e = propertyNames();
while (e.hasMoreElements()) {
String name = e.nextElement().toString();
String val = getProperty(name);
logger.info(name + " = " + val);
}
logger.info("------------------------------------");
//list(System.out);
//konfig.loadFromXML(new InputStream) for jdk 1.5 in the future.
initialized = true;
}
//otherwise do nothing.
}

public static Konfig getInstance() throws Exception {


//singleton
if (instance == null) {
logger.info("Creating a new instance of the global configuraiton
properties.");
instance = new Konfig();
}
return instance;
}

class KonfigWatchdog extends FileWatchdog {


private int i;

3
KonfigWatchdog(String filename) {
super(filename);
}

public void doOnChange() {


logger.info("Reloading the global configuration file: " +
filename);
initialized = false;
try {
Konfig kk = Konfig.getInstance();
kk.doInitialize(filename);
} catch (Exception ex) {
logger.warn("Cannot reload the global configuration file.
");
ex.printStackTrace();
}
}
}
}
Konfig.java

In my example, the InitServlet class loads a specified global configuration file from the
web.xml. A singleton Konfig (subclass of java.util.Properties) is then constructed. The Konfig
class takes advantage of the FileWatchDog from the Log4J packages and automatically
refreshes itself when the property file is updated.

To access values of the configure file, use the following code snippets.
Konfig k = Konfig.getInstance();
Enumeration e = k.propertyNames();
while (e.hasMoreElements()) {
String name = e.nextElement().toString();
String val = k.getProperty(name);
out.println("<p>" + name + " = " + val + "</p>");
}

//or you can access indvidual properties by.


String prop1 = k.getProperty("Mykey");
Code Snippet2
and
#The global config file for
MyKey=cde
zzz=zzz
DDDD=DDDD
xyz=xyz
ttt=msprule
bbbbbb=blah
globalconfig.properties

2 AMS Profile Loader (.Net)


The AMS Profile loader is written by Alvaro Mendez. You can download it from
http://www.codeproject.com/csharp/readwritexmlini.asp . That download includes a demo
2
If you feel that Konfig class should not directly throw a generic Exception, you can easy
subclass it and override the getInstance() method and wrap around your specific exception.
4
application showing you how to read/write a variety of property files using that library. The GUI
clipping is displayed below.

In a DotNet web application, it quite simple. You specify environment variables in the
web.config file within the <appSettings> node. When, your page-behind C# code retrieves the
name of the property file, you can create a wrapper class to represent your property file. That
way you can manipulate an object instead of individual name-value pairs of strings. In my
example, I uses a DataSet and a Xml configuration file.

<configuration>
<appSettings>
<add key="MyConfigFile" value="myconfig.xml" />
</appSettings>
<system.web>

</system.web>
</configuration>
Web.config

//Reading the global configue file.


String configFileName = ConfigurationSettings.AppSettings["MyConfigFile"];
//using relative path.
MyGlobalConfig gs = new MyGlobalConfig(Page.MapPath(configFileName));
Response.Write("<br>Below is the content of my global config
file.<br><hr>");
Response.Write(gs.getMyConf().GetXml());
ASP C# Code Behind Page

using System;
using System.Collections;
using AMS.Profile;
using System.Data;
using System.IO;

namespace logging

5
{
/// <summary>
/// MyGlobalConfig contains a DataSet for the configuration file.
/// </summary>
public class MyGlobalConfig
{
DataSet myconf;
public MyGlobalConfig(String PropertyFileName)
{
if (!File.Exists(PropertyFileName))
{
Console.WriteLine(PropertyFileName + " is not a valid
file.");
throw new Exception(PropertyFileName + " is not a
valid file error.");
}
Console.WriteLine("PropertyFileName is: " +
PropertyFileName);
Xml profile = new Xml (PropertyFileName);
this.myconf = profile.GetDataSet();
}

public DataSet getMyConf()


{
return myconf;
}

}
}
MyGlobalConfig.cs file

3 Jakarta Commons Configurations (Java)


Jakarta Commons Configurati3on framework depends on:
1. Jakarta Commons Lang4 library.
2. Jakarta Commons Collection5 library.

See my example “config_with_jakarta_commons”.

3
Jakarta Commons Configuration - http://jakarta.apache.org/commons/configuration/index.html
4
Jakarta Commons Lang - http://jakarta.apache.org/commons/lang/
5
Jakarta Commons Collection - http://jakarta.apache.org/commons/collections/
6

You might also like