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]>

Reply via email to