wood burning stoves 2.0*
The moose likes Java in General and the fly likes Loading properties from a static class Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Loading properties from a static class" Watch "Loading properties from a static class" New topic
Author

Loading properties from a static class

Mike Curwen
Ranch Hand

Joined: Feb 20, 2001
Posts: 3695

So i'm running into trouble with my little property-file loading method.

It goes much like you've probably seen out there (since I think I 'borrowed' it originally from the net...)


But, as you might guess, I can't use this method from a static context because of Class.getResourceAsStream(fileName);

So what is the alternate, that still ensure my app will be able to find the file? And oh yes, it's actually a servlet and the whole thing might be inside a jar file (the whole point of using the getResourceAsStream()). There probably isn't something I can use with static contexts, that still *absolutely* guarantees the JVM will find the properties file, right?

I'm posting it here, as opposed to Servlets, because I'm curious in general... Why isn't there a static method on the java.lang.Class object to obtain a hmm... 'static class loader'. I'm sure something in that quoted bit should clue me in... Surely *something* has to "load" the static class.
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2833
    
  11

Using it from a static context is irrelevant. It's getResourceAsStream() that's not static on the Class class. The code you've posted wouldn't even compile. You need an instance of the Class class. That is, an object of type Class. (Yes, that's a bit confusing, but you'll get the hang of it.)
There are several ways to get such an object. For example, you could say:
Object.class.getResourceAsStream(...);
You could also say,
this.getClass().getResourceAsStream(...);
However, that will only work when "this" has meaning ... so not from a static method. The class you use is important, because its package will be used to find your file. For example, Object is in the java.lang package, so the loader will look for your file at java/lang/filename.file. If you want to look at the root level along the classpath, then just make sure your file name starts with a slash /.
Mike Curwen
Ranch Hand

Joined: Feb 20, 2001
Posts: 3695

I think I must have copy and pasted that when I was in the middle of trying something. Indeed, my actual code uses getClass().getResourceAsStream(). I *do* have the hang of at least that much.

And like you said.. it has no meaning in a static context.

So how *do* I load a properties file when it's a static context?
Mike Curwen
Ranch Hand

Joined: Feb 20, 2001
Posts: 3695

And further... because this is 'actually' a Servlet question in disguise, my property files are all here:

WEB-INF/classes

which is in the class loading path of the web application.

and all my file names that I send to this method do indeed start with a '/'. So I really don't care WHAT object I'm using.. I'd just like a reference to the classloader.. hard to get (apparently) from a static context.. and I guess that's kinda why I posted in this forum... I was more confused about why I couldn't get one, than why this particular code doesn't work. I know that I'll probably have to break down and use File I/O for my InputStream. But I'd really like it to be portable.
Mike Curwen
Ranch Hand

Joined: Feb 20, 2001
Posts: 3695

:roll:


This seems like such a cheat. hehe. But a pretty obvious solution when I thought of it! Like duh! What prevents you from making an object in the static context, and using that object?
Mike Curwen
Ranch Hand

Joined: Feb 20, 2001
Posts: 3695

Ok, small tweak.

The first compiled, but didn't load the file. Because "" is loaded by a different classloader.

So replace "" with an instance of the class in which I'm using this method and it's all happy.
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
Hmmm, here's how I loaded property files, but into PropertyResourceBundle class. Is there some reason you're not just using java.io classes? Like, something dumb about what I did? (This was in like my first week of using Java, BTW)


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Mike Curwen
Ranch Hand

Joined: Feb 20, 2001
Posts: 3695

There's nothing dumb with your approach at all. But what value is in the variable aFileId ?

The reason I have to use a classloader to get at this file is because my application is actually a web-application. So it might be running from a jar file. In which case an absolute filepath through JavaI/O won't work (or will it?). Anyone care to prove that wrong?
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2833
    
  11

Originally posted by Mike Curwen:

So replace "" with an instance of the class in which I'm using this method and it's all happy.

You actually don't need to create an instance of the class. You can use the special ".class" syntax. That was my point with:
Object.class.getResourceAsStream(...);
String.class.getResourceAsStream(...);
also works. However, as you point out, you need to work with a class with the right classloader, so something like:
MyServlet.class.getResourceAsStream(...);
would work for you.
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
Back a step or two ... aFileId is a string name of a properties file minus the ".properties" extension.
This thing reads one properties file which must be in a known location. That file contains a list of directories which contain more properties files. The program goes to each directory in order and reads all the properties files it can find. It keeps the bundles in a hashmap keyed by filename. If it finds the same name twice, the second one replaces the first one. A little like overriding inherited values.
The idea was to deploy an identical set of files to all servers - windows, unix, development, staging, qa, production, etc - except for that first one with the list of directories. The directories correspond to different environments, and have names like windows, unix, development, um, you get the idea.
A call like ResourceMgr.getString("partnerapp1","url") would get the URL for development, qa, staging, etc. depending on that first list of directories.
I thought it was cute at the time. As I recall it made the version control system happier to have exactly the same files on all machines - except the one file that we managed separately and rarely changed.
Mike Curwen
Ranch Hand

Joined: Feb 20, 2001
Posts: 3695

This has bit me in the butt again!



What am I doing wrong?
Ron Newman
Ranch Hand

Joined: Jun 06, 2002
Posts: 1056
From the documentation for Class.getClassLoader():
Some implementations may use null to represent the bootstrap class loader. This method will return null in such implementations if this class was loaded by the bootstrap class loader.


Ron Newman - SCJP 1.2 (100%, 7 August 2002)
Mike Curwen
Ranch Hand

Joined: Feb 20, 2001
Posts: 3695

Thanks Ron,

So I might resonably expect this to work fine in a servlet container, where each webapp is several steps removed from the bootstrap loader.

I'll just add a check for null, I guess.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Loading properties from a static class
 
Similar Threads
Multiple Drivers
ServletContext and properties file
Reading a properties file from within a JAR! (quite urgent)
Problem with Copying and Renaming FIle once it reaches its limit
location of a property file