How a servlet can get the absolute path to a file outside of the servlet?

35.2k views Asked by At

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.
9

There are 9 answers

2
Thorbjørn Ravn Andersen On BEST ANSWER

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.

2
Akrikos On

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"

0
Rocket Surgeon On

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

0
toolkit On

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

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

4
John Topley On

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

5
neesh On

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()

2
Akrikos On

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
1
david a. On

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.

0
JosefB On

We had the same requirements. The simplest thing that worked so far was to just store a basedir property in one of the property files we were already loading. Then define a method like getExternalDocPath(String path).

This allowed us to extend the docbase of Tomcat (which only Tomcat 7 supports?). Out on the web someone posted a class that actually extends Tomcat's docbase to allow multiple paths, i.e., "alpha;baker;charlie".