views:

130

answers:

8

I have a series of application properties which all have different types.

The types could include, booleans, dates, timestamps, or strings.

I need to be able to provide the ability for administrative users to change these properties and have the system to remember / persist them to a file.

I am looking for a best practice way to store these application properties and be able to persist them on change and load them on start up.

A: 

You can store them in your Database, however due to the difference in data types of your properties you'll have to store them in their String representation. You could use another column to specify maybe the data type.

That form of application parametrization is something you've used successfully at my work. That's the general idea, I hope you could arrive to your solution with this.

StudiousJoseph
A: 

Assuming you are using Java, take a look at apache commons DatabaseConfiguration (http://commons.apache.org/configuration/apidocs/org/apache/commons/configuration/DatabaseConfiguration.html).
Basically, what it does is pretty simple. It scans a table that has key-value pairs and exposes that table as a java.util.Properties. You can use this to load your application properties from the database.
Once loaded, you can cache these properties in your application. Remember to invalidate this cache whenever you make changes to the application properties.

Sasi
A: 

You can use SQLite Firefox uses it to persist properties

Enrique
+3  A: 

Java has a facility built specifically for this purpose - Properties. Here is very good article about it

http://download-llnw.oracle.com/javase/tutorial/essential/environment/properties.html

eugener
What i ended up doing was copying some code from java.util.prefs.Preferences and using it in my own Properties backed class because the Preferences class is really for system and user preferences and does not really allow me to easily save it in a location i specify.
JavaRocky
+1  A: 

java.util.Properties is the easiest way. A Properties object can be created from a properties file (a file containing properties in the format name=value) or even a simple XML file. You can modify the object in memory and then write it back to a properties or XML file.

If you need more flexibility in structuring the properties, you can consider designing your own XML configuration file, although it will be a bit more work to read and write. You can however use a marshalling/unmarshalling API like JAXB, XStream etc to make that task easier.

These files can easily be modified manually as well.

Samit G.
+1  A: 

I use this code and it works quite good for me (only partial code, coding from memory..): (This is used in conjunction with the Properties class of java, but it makes it easier to add properties and keep your property file template in sync.)

to use:
Date date = Conf.value(Prop.SOME_DATE,Date.class);

and

enum Prop {
    SOME_DATE(Date.class, "2009-10-28", "Some date"){
        Object parse(String value){
            return new Date(value);
        }};
    private final Class<?> type;
    private final String description;
    private final Object default;
    Properties(Class<?> type, String defaultValue, String desc){
       this.type = type;
       this.description = desc;
       this.default = this.parse(defaultValue);
    }
    abstract Object parse(String value);
}

and

class Conf {
    private static final String PROP_FILE_NAME = "some.properties";
    private volatile Map<Prop,Object> store;

    public void load(){
        //Read from property file and use default if not given.
        //I code it in a way that it will not permit null as value, so 
        //if default is null the user is forced to provide setting.
    }

    public <T> T value(Prop prop, Class<T> clazz){
        return (T)this.store.get(prop);
    }
    public static void main(String[] args){
        //code to autogenerate property file
        //Something like:
        //#Default : 2009-10-28 Description : Some date. Type:Date
        //#SOME_DATE=2009-10-28
    }
}

The class argument makes the method a little verbose, but sometimes it is irritating if you can only let java infer the type, like this:

CountDownLatch latch = Conf.value(Prop.SOME_INTEGER);
//Compilation error! Since it expects int and won't unbox.

CountDownLatch latch = Conf.value(Prop.SOME_ITEGER,Integer.class);
//Verbose, but works everytime. Of course you could get a 
//ClassCastException, but you should notice that early 
//in the development...    
Enno Shioji
You memorize those in your memory?
Rosdi
Ah, it's a snippet I use all the time so I roughly remember. It's too small to package it in a jar though :)
Enno Shioji
+4  A: 

Since you have a requirement of storing and reading various properties of different types like boolean, integers, etc. I think the java.util.prefs API is a good choice for you. It allows you to store and read various data types.

Here's the API documentation

naikus
+1 Preferences API is weird and don't give much control of how the data is stored, but it is a much newer API that Properties and is a better choice.
tulskiy
Are there any solid libraries for file based implementations for java.util.prefs.Preferences?
JavaRocky
The sun's jdk implementation stores them in the filesystem, for user preferences (Preferences.geUserRoot()), in the user's home directory, in XML files. The Preferences class API documentation defines a DTD of such files
naikus
Thanks for the reply. I'd like to take control on where the file gets stored. The user's home directory is not appropriate for my application. I would like to store it with the other file data in my application. Does the sun's jdk's implementation allow this? Or any other implementations?
JavaRocky
Yes you can to that. You need to have a class implementing java.util.prefs.PreferencesFactory that returns a class that is a subclass of AbstractPreferences. All the abstract methods take are quite straight forward and should not be hard to implement. Infact your Preferences implementation can be backed by a java.util.Properties (file)
naikus
A: 

Even though you should use Preferences API or Properties, here is a hack that might also work:

Create a HashMap<String, Object> and use XMLEncoder/XMLDecoder for saving/loading. Most of the standard java classes can be serialized this way as java beans. You can make a simple wrapper class for getting various properties, handling default values etc. This way you can also store nested collections which is handy sometimes. It's really easy to implement.

tulskiy