简体   繁体   中英

getResourceAsStream not loading resource in webapp

I have a web application that uses a library which resides in TOMCAT_HOME/common/lib. This library looks for a properties file at the root of the classpath (in a class called ApplicationConfig):

ApplicationConfig.class.getResourceAsStream("/hv-application.properties");

My Tomcat web application contains this properties file. It is in WEB-INF/classes, which is the root of the classpath right? However, at runtime, when it tries to load the properties file, it throws an exception because it can't find it (getResourceAsStream returns null).

Everything works fine if my application is a simple, standalone Java application. Does Tomcat cause the getResourceAsStream method to act differently? I know there's a lot of similar questions out there, but none of them have helped unfortunately. Thanks.

请尝试使用Thread.currentThread().getContextClassLoader().getResourceAsStream("/hv-application.properties")

This looks like it might be related to how Tomcat classloaders work. If you have something in one class loader (your config file in the webapp classloader) that's used by something in another (the jar in common/lib), the result could be a big headache.

This document explains how Tomcat delegates to class loaders. If possible, could you try one of the following:

  1. Move the jar file in common/lib into your web application (WEB-INF/lib). This is not always possible I know, but sometimes jars (eg log4j) can coexist peacefully across classloaders (*).
  2. Move your configuration file into common/classes. This is effectively the same thing (puts the configuration item into the same classloader as the jar that needs it). Again, this is not ideal, but if you have control over your environment, it would work.

Either way, having resources in different classloaders can be a pain. I hope this helps.

(*) log4j has the -log4j.ignoreTCL option which makes this possible though

The Tomcat security manager generally won't let you access webapp classes and resources from libraries in the Tomcat root libraries. This is meant to give separation between the web applications running in a container.

You should be able to get around this by updating the security policy, but it's generally better to not put your libs into the Tomcat container, which I assume you are doing.

I'm expanding Olivier comment as a response (thank you for the lead).

The problem seems to be the leading slash (/) in the resource path.

In Tomcat 8 the WebAppClassloader correctly resolves the path with and without the leading slash. Both .getResourceAsStream("/org/pakopa/app/config.properties"); and .getResourceAsStream("org/pakopa/app/config.properties"); returns an InputStream.

In Tomcat 7 (And I assume previous versions too) .getResourceAsStream("/org/pakopa/app/config.properties"); is not resolved and returns null but .getResourceAsStream("org/pakopa/app/config.properties"); is correctly resolved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM