views:

74

answers:

4

Hi,

How can I define some properties dynamically in Java. For now, I'm using a properties file, but I need to change these properties before installation, so these properties should be set in a file outside the jar (or install) file.

These properties define my IBatis connection.

Thansk in advance, Victor

+2  A: 

Keep going with the .properties and load the file as a resource.

If it is in the classpath it would be found.

What I use, because it is much easier to me is a resource bundle instead.

edit

If the file is in your classpath you can loaded it either as a resource with: Some.class.loadResource(...) or what I do is use a ResourceBundle which does basically the same.

For instance if I have:

import java.util.ResourceBundle;

public class ResourceBundleTest {
    public static void main( String [] args ) {
        ResourceBundle bundle = ResourceBundle.getBundle("connection");
        for( String key: bundle.keySet() ){
            System.out.printf("bundle[%s]=%s%n",key, bundle.getString(key));
        }
    }
}

I can load that file if is in the class path. The property is outside, in "some/nested/dir"

$ls -l some/nested/dir/
total 8
-rw-r--r--  1 oscarreyes  staff  35 Jun 25 12:06 connection.properties
$cat some/nested/dir/connection.properties 
name=Oscar
lastName=Reyes
age=0x1F

If I run it without adding that directory to my classpath it wont work:

$java ResourceBundleTest 
Exception in thread "main" java.util.MissingResourceException: Can't find bundle for base name connection, locale es_ES
    at java.ut...ceBundle.java:1427)
    at java.ut...urceBundle.java:1250)
    at java.ut...ceBundle.java:705)
    at Resourc...st.java:6)

But if I add the directory to my classpath, then the file will be found easily.

$java -cp some/nested/dir/:.  ResourceBundleTest 
bundle[lastName]=Reyes
bundle[age]=0x1F
bundle[name]=Oscar
$

In a similar fashion, you can have a .jar file, and put your .properties file wherever you want, you just have to include it in your classpath.

The equivalent using properties would be:

import java.util.Properties;

public class LoadProperties {
    public static void main( String [] args ) throws java.io.IOException {
        Properties properties = new Properties();
        properties.load( LoadProperties.class.getResourceAsStream("connection.properties"));
        properties.list( System.out );
    }
}

But for some reason I prefer the resource bundle.

OscarRyz
Hi, thanks for the help, but I believe you don't understand my question. I'm doing like you said. The problem is that the properties' values will change and this values couldn't be set inside the jar file. They need to be easily changed. Is that clear now?
Victor
Most likely you didn't understand what I said :P If it is in the classpath ( which could be outside of you class ) it will be loaded. Let me update the answer with a sample
OscarRyz
@Victor: I believe that you don't understand the phenomenon "classpath" :) All you basically need to do is to put the file in one of the paths covered by the runtime classpath, or to add the file's path to the runtime classpath. This way the Java code can continue accessing it as classpath resource.
BalusC
@Vic I have updated my sample, probably wasn't clear enough the first time. Let me know if the update its better.
OscarRyz
Ok, you are right. I believe that will works. :)
Victor
A: 

A properties file is fine, you just have to include it in the classpath and it can live outside the jar.

If you want to get fancier, you have the Preferences API, but while that will keep things more to the standard of your operating system, it can make deployment complicated as you will have different locations for your configuration depending on your platform, and will require a platform dependent install.

Yishai
I don't think iBatis supports `Preferences`.
BalusC
A: 

Yes, Using a properties file is common practice. In addition the general practice is to have separate properties file for each environment and the build process will pick the right one depending on the target. All you need to do is keep the file in classpath and use classloader to find it.

Teja Kantamneni
A: 

Just put the file in one of the paths covered by the runtime classpath, or to add the file's path to the (default) runtime classpath. This way the Java code can continue accessing it as classpath resource.

When you execute JAR files using java -jar command or by doubleclicking the file, the -cp or -classpath arguments and even the %CLASSPATH% environment variable will be ignored. You can define the JAR file's default classpath as Class-Path entry in META-INF/MANIFEST.MF file.

E.g.

Class-Path: .

The dot . means that the path where the JAR file is currently sitting is included in the runtime classpath. So if you put the properties file in the same folder as the JAR file, it'll work.

You can also specify an absolute disk file system path:

Class-Path: /var/foo

This way the folder /var/foo is taken in the runtime classpath. So if you put the properties file in that folder, it'll work.

BalusC