Properties, canonical way of reading/writing configuration files.

A

Alex Polite

Here's another newbie question?

Is java.util.Properties the canonical way of reading and writing
configuration files?

alex
 
L

lyallex

Here's another newbie question?

Is java.util.Properties the canonical way of reading and writing
configuration files?

alex

Alex

I would say yes before J2SE 1.4 came out.
If you are using 1.4 or later check out java.util.prefs.Preferences.

Rgds
Lyall
 
L

Liz

lyallex said:
Alex

I would say yes before J2SE 1.4 came out.
If you are using 1.4 or later check out java.util.prefs.Preferences.

Rgds
Lyall

A nit, perhaps, but in Windows the preferences are stored in the registry
not in a file, so it can't be a configuration file ;-))
 
A

Alex Polite

Alex

I would say yes before J2SE 1.4 came out.
If you are using 1.4 or later check out java.util.prefs.Preferences.

OK I tried it out.

Storing preferences data in an XML file and the way that file is
interfaced with getInt et. al. feels soooo right.

But this ~/.java/.prefs thing isn't right for this project.

Can I tell the Preferences constructor to look at a specific path
rather then ~/.java/.prefs?

I need instances for different users to look at the same place. I
can't put it under system preferences cause I'm not root. This is for
an application running on a webhotel. So the user will be something
like nobody or www-data.


Maybe there's some other package that does persistance with XML,
better fitted for my needs?

alex
 
L

lyallex

Here's another newbie question?

Is java.util.Properties the canonical way of reading and writing
configuration files?

alex

Hi

It seems that the article I mentioned in an earlier post

http://www.javaworld.com/javaworld/jw-08-2001/jw-0831-preferences-p2.html

has some 'inconsistencies' with my current version of J2SE 1.4.2. The
article mentions getting a reference to a Preferences object by
passing an object reference but my API docs only show a
userNodeForPackage method that takes a Class as argument so I thought
I'd do a quick run through of getting and setting preferences and see
if anyone can point out problems with this approach.

First set up a properties node

package anon.pack.prefs;

import java.util.prefs.Preferences;
import java.io.FileOutputStream;

public class PropertiesTest {

private Preferences prefs;

public PropertiesTest() {
prefs = Preferences.userNodeForPackage(this.getClass());
String outfile = "C:/prefs/prefs.xml";
prefs.put("outfile", outfile);
try{
prefs.exportNode(new FileOutputStream(outfile));
}
catch(Exception ex){
}
}

public static void main(String[] args){
new PropertiesTest();
}
}

After running this once I have the following file in
C:/prefs/prefs.xml

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

<!DOCTYPE preferences SYSTEM
'http://java.sun.com/dtd/preferences.dtd'>

<preferences EXTERNAL_XML_VERSION="1.0">
<root type="user">
<map />
<node name="anon">
<map />
<node name="pack">
<map />
<node name="prefs">
<map>
<entry key="outfile" value="C:/prefs/prefs.xml" />
</map>
</node>
</node>
</node>
</root>
</preferences>

I can now modify my code to read the preferences file location thus

....

public PropertiesTest() {
prefs = Preferences.userNodeForPackage(this.getClass());
String prefsfile = prefs.get("outfile", "C:/temp/tempprefs.xml");
try{
prefs.importPreferences(new FileInputStream(prefsfile));
}
catch(Exception ex){
ex.printStackTrace();
}
}

So now I can change the location of my preference file at will which
is pretty cool I think.
Anyway say I now need to set a 'property' that returns the value of a
listenPort (crap example but it does the job). All I need to do is to
edit my preferences file and add in a new entry like this.

<preferences EXTERNAL_XML_VERSION="1.0">
<root type="user">
<map />
<node name="anon">
<map />
<node name="pack">
<map />
<node name="prefs">
<map>
<entry key="outfile" value="C:/prefs/prefs.xml" />
<!-- *********** new entry *********** -->
<entry key="listenPort" value="26358" />
</map>
</node>
</node>
</node>
</root>
</preferences>

Now I can access this preference/property in my code

....

public String getPref(String key){
return prefs.get(key, "someDefaultValue");
}

public static void main(String[] args){
System.out.println(new PropertiesTest().getPref("listenPort"));
}

The output is

26358


Which seems pretty cool to me, I couldn't give a monkeys where the
information is stored on the platform, as far as I'm concerned I have
a platform independent, location independent way of specifying
properties for my programs.

I'm not really sure where the author of the article above is coming
from when he uses objects to get preferences, perhaps this was an
earlier version (or a later one, I haven't looked yet). Whatever, much
of what he says seems to make sense (to me at least).

What, if anything, do people think is wrong with this approach ?

Rgds
Lyall
 
A

Alex Polite

OK I tried it out.

Storing preferences data in an XML file and the way that file is
interfaced with getInt et. al. feels soooo right.

But this ~/.java/.prefs thing isn't right for this project.

Can I tell the Preferences constructor to look at a specific path
rather then ~/.java/.prefs?

I need instances for different users to look at the same place. I
can't put it under system preferences cause I'm not root. This is for
an application running on a webhotel. So the user will be something
like nobody or www-data.


Turns out you can supply the userRoot and systemRoot variables as
arguments to the JVM.

java -Djava.util.prefs.systemRoot=<somepath> <someapp>

Then you have to give anyone using the app read/write permissions to
everything under <somepath>.

The problem is just that if a user creates a new node that file will
have write premissions for that user only. If you only have one
concurrent user and reset the premissions after the app is run you
should be alright.

A cleaner alternative would be to override
java.util.prefs.PreferencesFactory and use a SQL backend or something
like that. But 1.4.1 dosen't seem to provide that and I don't want to
stray from the standard library.

Besides my app will not be changing the preferences.

alex
 
R

Rogan Dawes

lyallex said:
First set up a properties node

package anon.pack.prefs;

import java.util.prefs.Preferences;
import java.io.FileOutputStream;

public class PropertiesTest {

private Preferences prefs;

public PropertiesTest() {
prefs = Preferences.userNodeForPackage(this.getClass());
String outfile = "C:/prefs/prefs.xml";
prefs.put("outfile", outfile);
try{
prefs.exportNode(new FileOutputStream(outfile));
}
catch(Exception ex){
}
}

public static void main(String[] args){
new PropertiesTest();
}
}

After running this once I have the following file in
C:/prefs/prefs.xml

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

<!DOCTYPE preferences SYSTEM
'http://java.sun.com/dtd/preferences.dtd'>

<preferences EXTERNAL_XML_VERSION="1.0">
<root type="user">
<map />
<node name="anon">
<map />
<node name="pack">
<map />
<node name="prefs">
<map>
<entry key="outfile" value="C:/prefs/prefs.xml" />
</map>
</node>
</node>
</node>
</root>
</preferences>

Yes, but you should ALSO have the same information in ~/.java/ whatever,
so there is no point in having exported it to a file, other than that
another user might be able to import those settings and configure their
app environment the same way.

Note that you read the location of the prefs outfile from prefs before
you have imported your (previously exported) file. Try skipping that
step, and seeing if your listenPort is still set ;-)
Which seems pretty cool to me, I couldn't give a monkeys where the
information is stored on the platform, as far as I'm concerned I have
a platform independent, location independent way of specifying
properties for my programs.

Sure. It looks like it is platform independent anyway, which is really
all you need, I think.
What, if anything, do people think is wrong with this approach ?

See above ;-)
Rgds
Lyall

Please don't take my comments to be knocking Preferences, I think it
looks great! I'm just pointing out some implementation mistakes that you
made.

Rogan
 
L

lyallex

....
Please don't take my comments to be knocking Preferences, I think it
looks great! I'm just pointing out some implementation mistakes that you
made.

Rogan

Ah, I see, well thanks for that Rogan

Actually the code does exactly what I want it to do.
All I know is that once I have set everything up I can do this

public PropertiesTest() {
prefs = Preferences.userNodeForPackage(this.getClass());
}

public String getPref(String key){
return prefs.get(key, "someDefaultValue");
}

public static void main(String[] args){
System.out.println(newPropertiesTest().getPref("listenPort"));
}

and still get the output

26358

That is all I wanted.

Rgds
Lyall
 
R

Rogan Dawes

lyallex said:
Actually the code does exactly what I want it to do.
All I know is that once I have set everything up I can do this

public PropertiesTest() {
prefs = Preferences.userNodeForPackage(this.getClass());
}

public String getPref(String key){
return prefs.get(key, "someDefaultValue");
}

public static void main(String[] args){
System.out.println(newPropertiesTest().getPref("listenPort"));
}

and still get the output

26358

That is all I wanted.

Rgds
Lyall

Sure. All I was saying was that your program was reading the value from
a tree structure under .java, rather than from the .xml file that you
were referring to. As you have shown, you can skip that import step
completely, and still get your values.

Regards,

Rogan
 
L

lyallex

Sure. All I was saying was that your program was reading the value from
a tree structure under .java, rather than from the .xml file that you
were referring to. As you have shown, you can skip that import step
completely, and still get your values.

Regards,

Rogan

Looks like we are in agreement then

Cool

Rgds
Lyall



"Process- How will the work and the team be organized?
The team needs to fit the culture in which it will operate,
but you should write software well rather than preserve the
irrationality of an enclosing culture" - Kent Beck
 
L

Liz

Guess you need to read the API docs Liz

http://java.sun.com/j2se/1.4.2/docs/api/index.html

Rgds
Lyall
Ya, you too, cuz you b wrong.

public abstract class Preferences
extends Object
A node in a hierarchical collection of preference data. This class allows
applications to store and retrieve user and system preference and
configuration data. This data is stored persistently in an
implementation-dependent backing store. Typical implementations include flat
files, OS-specific registries, directory servers and SQL databases. The user
of this class needn't be concerned with details of the backing store.
 
L

lyallex

You can't edit a file if there is no file.

Oh, that's odd, I've just done it...

Must've been dreaming.






"Process- How will the work and the team be organized?
The team needs to fit the culture in which it will operate,
but you should write software well rather than preserve the
irrationality of an enclosing culture" - Kent Beck
 
L

lyallex

Oh, that IS odd, you must be on one of those blue hat
or jack-in-tosh machines.

Even odder, it's Microsoft Windows XP, at least it was last time I
looked, hold on ....

yes, yes, it certainly looks like XP

Yep, I'm now really really sure it is XP.

And look at this ! here's the file !!!

<!DOCTYPE preferences SYSTEM
'http://java.sun.com/dtd/preferences.dtd'>

<preferences EXTERNAL_XML_VERSION="1.0">
<root type="user">
<map />
<node name="anon">
<map />
<node name="pack">
<map />
<node name="prefs">
<map>
<entry key="outfile" value="C:/prefs/prefs.xml" />
</map>
</node>
</node>
</node>
</root>
</preferences>

Hmm, I think what you are saying is that the preferences are stored
in the registry and that the registry is not a 'file' that you can
edit. I have no argument with that, never have done. However what I am
saying is that it is possible to export those preferences to a file,
modify the file by hand, in a text editor, just like editing a
properties file then re-import the modified preferences file and have
the changes reflected in the registry.

that's all I'm saying, that's all I ever intended to say.

Still, it's good to have these little chats, it really helps to
reinforce understanding. I'm much clearer on the whole 'implementation
dependant persistence' thing now. Nice one.

Rgds
Lyall





"Process- How will the work and the team be organized?
The team needs to fit the culture in which it will operate,
but you should write software well rather than preserve the
irrationality of an enclosing culture" - Kent Beck
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top