views:

7054

answers:

8

We have been using System.getProperties("user.dir") to get the location of a properties file. Now that it has been deployed on Tomcat(via servlet), the System call is giving the location as tomcat and not at the location at where the properties file exist.

How can we call the the properties file dynamically?

Given:

  • Tomcat is not the only way the app will be deployed
  • We have no control on where the app may be placed.
  • Relative paths will not work as that Vista is being used and Vista breaks relative paths.
  • This must work on all OS, including(but not limited to) Linux, XP and Vista.
  • EDIT I implied this, but in case I was not clear enough, I have no way of knowing the path String.
+2  A: 

Take a look at ServletContext's getResource and getResourceAsStream methods.

John Topley
I kinda wish there was a way to get a ServletContext in a normal class file.
R. Bemrose
Thank you for your timely response, but the getResource methods require a path string. I cannot predict the path that will be used.
WolfmanDragon
@R.Bemrose, I have been trying to find a way to hack this.
WolfmanDragon
The requirement is that the file is "outside" the servlet, hence it is not in a classpath.
Thorbjørn Ravn Andersen
A: 

You can place your property files in your class path and read them as an input stream using something like:

ClassName.class.getResourceAsStream(filePath + fileName);

Where filePath is the relative path of the file from the class path root and fileName is the name of the file.

If you need to get the absolute path to a file you read as a resource, you can do some thing like this:

ClassName.class.getResource(filePath + fileName).getPath()

neesh
@neesh, if you do not know the filePath, how are you using it in the getResource() call? I am sure that I am simply misunderstanding what you are saying.
WolfmanDragon
So let's say you don't know the filePath and you want to know the absolute path of the directory your web-app is deployed. You can do this:ClassName.class.getResource("/").getPath();
neesh
Does not work on Vista. Would have been a good fix otherwise. +1
WolfmanDragon
really? What does the ..getResource("/").getPath() return in Windows Vista?
neesh
exception### I would have to go run it again to remember the exception . I will do that later and post the reply. out of time now
WolfmanDragon
A: 

Is it possible to put the config file within the classpath and reference it via something like springs ClassPathResource?

You should be able to use it like this:

ClassPathResource foo = new ClassPathResource("file.name");

Where file.name exists somewhere in the classpath at the lowest level such as:

  • /webapps/WEB-INF/classes/
  • the base of one of your jar files
Akrikos
Spring is not an option, this is a situation where it has to be agnostic to everything EXCEPT java(servlet being part of the java API) Thank you for your reply though.
WolfmanDragon
Sounds like your situation is difficult.
Akrikos
+1  A: 

I think ClassName.class.getResourceAsStream() will work for you. The comments on that method point you at ClassLoader.getResource(), which tells you how to specify a file in your classpath.

Something like this should work:

InputStream foo = ClassName.class.getResourceAsStream("file.name");

Where file.name is at the base of your classpath somewhere. If file.name is in the com.foo.bar package, you would use "/com/foo/bar/file.name"

Akrikos
On anything except Vista. Vista breaks it. but this is the closest anyone has got so far. +1
WolfmanDragon
OHNO! Man that sucks. If I had vista I'd be testing to see if I could find an answer. Good luck to you in figuring it out.
Akrikos
A: 

Another approach may be to pass the variable value to the JVM with -D parameter. That way you can tie your code to the same variable name and then pass different values at the time of start-up. I haven't tried this, but i'm thinking it should work for an app deployed in Tomcat as well, if you modify startCatalina script to pass -D parameter to JVM

Rocket Surgeon
+2  A: 

You must have a way of knowing the path of the property file which you can then wrap in a File and pass to the load() method of your properties object.

If you run inside a Tomcat service you are not running as the user you installed it as,so you cannot derive the home directory. You most likely need to hardcode SOMETHING then.


Edit: The property file is relative to the application. See http://www.exampledepot.com/egs/java.lang/ClassOrigin.html for an example of how to get to the file name for the bytecode for a given class. You should be able to continue from there.

Class cls = this.getClass();
ProtectionDomain pDomain = cls.getProtectionDomain();
CodeSource cSource = pDomain.getCodeSource();
URL loc = cSource.getLocation();  // file:/c:/almanac14/examples/

You should be aware that some security managers disallow this.

Thorbjørn Ravn Andersen
Works on Vista, passed it on to to be tested on Tomcat. thanks +1
WolfmanDragon
I never got an answer back from the tomcat side, as of now I am accepting your answer, as that it actually works on Vista. It only scares me what will happen with Windows 7. There might be another post. Thanks.
WolfmanDragon
A: 

You could store the location of your properties file in JNDI?

This should be portable across Tomcat, and for Java EE Application Servers.

toolkit
A: 

If I understood the question correclty, another alternative might be to call ServletContext.getRealPath() on a jsp or a static file in your app and derive the path from the result.

It implies webapp deployed as "expanded" - i.e. not as a compressed war file - but that is what most appservers do anyway.

david a.
That was one of the earliest tries at a fix. Does not work across the board. It goes to the Tomcat file, not the source file.
WolfmanDragon