See below. On Tue, 12 Feb 2002, Michael Kintzer wrote:
> Date: Tue, 12 Feb 2002 18:56:38 -0800 > From: Michael Kintzer <[EMAIL PROTECTED]> > Reply-To: Tomcat Users List <[EMAIL PROTECTED]> > To: "Tomcat Users List (E-mail)" <[EMAIL PROTECTED]> > Subject: resource files not found in /WEB-INF/classes > > Tomcat 4.0.1: According to tomcat-docs/appdev/deployment.html, > webapps/mywebapp/WEB-INF/classes/ is the appropriate location for any > associated resource files required for an application "mywebapp". I have > placed a properties file "config.properties" in my /WEB-INF/classes/ > directory but when I try to access it using this code: > > package com.myco.myproj > > .. imports and other code... > > try > { > File f = new File("config.properties"); > FileInputStream fis = new FileInputStream(f); > Properties prop = new Properties(); > prop.load(fis); > } > catch (Exception e) > { > e.printStackTrace(); > } > > I continually get java.io.FileNotFoundException: config.properties (The > system cannot find the file specified). > > I even tried adding a context element in my conf/server.xml file for my web > app like so: > > <!-- myproj context --> > <Context path="/myproj" docBase="myproj" debug="0" reloadable="true" > /> > > but that had no effect. I've searched through all the documentation I > could find and it all seems to indicate that any resource files in > /WEB-INF/classes should be detectable. Any ideas on what I may be doing > incorrectly would be greatly appreciated. > > Thanks, > > > Michael Kintzer There are two issues here that I'd like to address: * How do I make File I/O work for this kind of thing? * What's a more portable way to do this? For the first answer, the thing you have to remember is that relative pathnames like "config.properties" are resolved, by the file i/o routines of Java or any other language, against the current working directory of the application you are running (Tomcat, in this case). You can't count on *anything* about where that really is, because it depends on how Tomcat is initially started (and which version you are running). BUT, you can do this right if you compute the path relative to the base directory of your webapp, like this: File docBase = new File(getServletContext().getRealPath()); File f = new File(docBase, "/WEB-INF/classes/config.properties"); FileInputStream fis = new FileInputStream(f); Will this work? Yes -- but only sometimes. What happens if you configure Tomcat to run your webapp directly from a WAR file (or you need to migrate to an application server that does not support running webapps from unpacked directories)? Then, you are in trouble, because getRealPath() will return null. There are two approaches that work just fine at this point: * Use ServletContext.getResourceAsStream(). This call is guaranteed to work on any servlet container, regardless of how it internally represents your webapp: String path = "/WEB-INF/classes/config.properties"; InputStream is = getServletContext().getResourceAsStream(path); This call works because the context-relative path is resolved by the container -- and it's required to work in all circumstances. Note that you can even use this approach to read things like the web.xml file at run time, if you wanted to: InputStream is = getServletContext().getResourceAsStream("/WEB-INF/web.xml"); Struts needs to do this (as an example use case) because it needs to know what servlet mappings you are using, and there is nothing in the Servlet API that makes this information available to a webapp. * The fact that you are willing to put this file into the /WEB-INF/classes subdirectory means that you can rely on a similarly-named method provided by the JDK: String path = "config.properties"; InputStream is = this.getClass().getClassLoader().getResourceAsStream(path); This call works because it uses the capability of JDK class loaders to find resources that are included in the class path of your web application -- even if they are inside a JAR file. It is particularly useful for configuring class libraries that might also be used outside of a web application environment, but it works here as well because the "/WEB-INF/classes" directory is always made visible to the class loader for your web application. Bottom line: *****PLEASE***** avoid the use of file I/O to access resources inside your web applications. This is only going to cause you portability grief later on. You should get in the habit, from the very beginning, of using the APIs that are made available to access inside-the-webapp resources in a portable way. Craig McClanahan -- To unsubscribe: <mailto:[EMAIL PROTECTED]> For additional commands: <mailto:[EMAIL PROTECTED]> Troubles with the list: <mailto:[EMAIL PROTECTED]>