Home | FAQ | Contact me

Properties

I have notes on resource bundles using properties files.

One day, I'm thinking that I should demonstrate how to consume properties files for application configuration and other tasks. There's no notion of locale involved. Now, we can argue about whether configuration is a good thing, or best practice, how best to do it, etc., but let's not do that since I'm just going to demonstrate using Properties loaded from a file.

At the same time, I'm demonstrating a sort of Singleton here.

Let's pretend you're in need of specifying a different host and port than the colleague you work with. You decide that both of you will have something like /etc/configuration/application.properties and when it's missing, defaults will apply.

Practically speaking, in my /etc/configuration subdirectory, I have:

application.properties -> /home/russ/projects/ourwebapp/extras/private/russ/application.properties

...and my colleague's host has a similar symbolic link, but to his private place in our web application's extras area.

ApplicationProperties.java:
package com.etretatlogiciels.samples.properties;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.MissingResourceException;
import java.util.Properties;

import org.apache.log4j.Logger;

/**
 * Uh, well, I find I need this because Levi uses 8080 while I use 8000 for my port.
 * So, whenever /etc/configuration/applications.properties is missing or something
 * else is wrong when an attempt to read it is made, defaults will apply.
 *
 * @author Russell Bateman
 */
public class ApplicationProperties
{
    public static Logger log = Logger.getLogger( ApplicationProperties.class );

    private static final String APPLICATION_PROPERTIES = "/etc/configuration/application.properties/";
    private static final String HOSTNAME               = "hostname";
    private static final String PORT                   = "port";

    // all values will need to carry defaults in case application.properties is missing...
    private int     port     = 8080;
    private String  hostname = "localhost";

    public final void reloadProperties()
    {
        log.debug( "Reloading properties by request at " + lastUpdate );
        internalReloadProperties();
    }

    public int    getPort()     { return this.port; }
    public String getHostname() { return this.hostname; }



    /* Singleton stuff -------------------------------------------------------- */
    private static ApplicationProperties instance = null;

    public static ApplicationProperties getInstance()
    {
        if( instance == null )
            instance = new ApplicationProperties();

        return instance;
    }

    private static Long lastUpdate;

    protected ApplicationProperties()
    {
        lastUpdate = System.currentTimeMillis();
        log.debug( "Lazy instantiation of properties at " + lastUpdate );
        internalReloadProperties();
    }

    private final void internalReloadProperties()
    {
        Properties properties = new Properties();
        String     error      = null;

        try
        {
            properties.load( new FileInputStream( APPLICATION_PROPERTIES ) );
        }
        catch( MissingResourceException e )
        {
            error = "Missing " + APPLICATION_PROPERTIES;
        }
        catch( FileNotFoundException e )
        {
            error = "Missing " + APPLICATION_PROPERTIES;
        }
        catch( IOException e )
        {
            error = "Unspecified IOException loading " + APPLICATION_PROPERTIES;
        }

        if( error != null )
        {
            log.warn( error + " (defaults will continue to apply)" );
            return;
        }

        String  portString = properties.getProperty( PORT );

        if( portString != null )
            this.port = Integer.parseInt( portString );

        String  hostname = properties.getProperty( HOSTNAME );

        if( hostname != null )
            this.hostname = hostname;
    }

    public static void main( String[] args )
    {
        ApplicationProperties properties = new ApplicationProperties();

        System.out.println( "hostname = " + properties.getHostname() );
        System.out.println( "    port = " + properties.getPort() );

        properties.reloadProperties();

        System.out.println( "hostname = " + properties.getHostname() );
        System.out.println( "    port = " + properties.getPort() );
    }
}

Console output

Assuming /etc/configuration/application.properties contains:

hostname = goble-dee-goop
port = 8000

The following output will appear:

    hostname = goble-dee-goop
        port = 8000
    hostname = goble-dee-goop
        port = 8000

If not (no application.properties file), then it's

    hostname = localhost
        port = 8080
    hostname = localhost
        port = 8080

You can trace through in the debugger to watch the Singleton work if you like.