51

I have the following structure in a Java Web Application:

TheProject
  -- [Web Pages]
  -- -- [WEB-INF]
  -- -- -- abc.txt
  -- -- index.jsp
  -- [Source Packages]
  -- -- [wservices]
  -- -- -- WS.java

In WS.java, I am using the following code in a Web Method:

InputStream fstream = this.getClass().getResourceAsStream("abc.txt");

But it is always returning a null. I need to read from that file, and I read that if you put the files in WEB-INF, you can access them with getResourceAsStream, yet the method is always returning a null.

Any ideas of what I may be doing wrong?

Btw, the strange thing is that this was working, but after I performed a Clean and Build on the Project, it suddenly stopped working :/

Justin Johnson
  • 30,978
  • 7
  • 65
  • 89
Andreas Grech
  • 105,982
  • 98
  • 297
  • 360

7 Answers7

40

To my knowledge the file has to be right in the folder where the 'this' class resides, i.e. not in WEB-INF/classes but nested even deeper (unless you write in a default package):

net/domain/pkg1/MyClass.java  
net/domain/pkg1/abc.txt

Putting the file in to your java sources should work, compiler copies that file together with class files.

Esteban Herrera
  • 2,263
  • 2
  • 23
  • 32
Jaroslav Záruba
  • 4,694
  • 5
  • 39
  • 58
  • +1 Cheers mate, it worked. I moved the file to `wservices` and its working now – Andreas Grech May 09 '10 at 09:38
  • 4
    If you are using Eclipse, you also need to hit 'F5' (refresh) so that your 'abc.txt' appears in package explorer, otherwise getResource() always returns null. – Chris Huang-Leaver Jun 02 '14 at 12:28
  • I found Unit tests were more forgiving to the file's location in Eclipse/maven, but when packaged and deployed the file worked only when I moved it to match the class' location as this answer recommended. – Aaron Roller Jun 09 '14 at 19:45
31

A call to Class#getResourceAsStream(String) delegates to the class loader and the resource is searched in the class path. In other words, you current code won't work and you should put abc.txt in WEB-INF/classes, or in WEB-INF/lib if packaged in a jar file.

Or use ServletContext.getResourceAsStream(String) which allows servlet containers to make a resource available to a servlet from any location, without using a class loader. So use this from a Servlet:

this.getServletContext().getResourceAsStream("/WEB-INF/abc.txt") ;

But is there a way I can call getServletContext from my Web Service?

If you are using JAX-WS, then you can get a WebServiceContext injected:

@Resource
private WebServiceContext wsContext;

And then get the ServletContext from it:

ServletContext sContext= wsContext.getMessageContext()
                             .get(MessageContext.SERVLET_CONTEXT));
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
30

Instead of

InputStream fstream = this.getClass().getResourceAsStream("abc.txt"); 

use

InputStream fstream = this.getClass().getClassLoader().getResourceAsStream("abc.txt");

In this way it will look from the root, not from the path of the current invoking class

Derlin
  • 9,572
  • 2
  • 32
  • 53
Mike-Bell
  • 951
  • 1
  • 11
  • 25
11

I think this way you can get the file from "anywhere" (including server locations) and you do not need to care about where to put it.

It's usually a bad practice having to care about such things.

Thread.currentThread().getContextClassLoader().getResourceAsStream("abc.properties");
oberfreak
  • 1,799
  • 13
  • 20
jediz
  • 4,459
  • 5
  • 36
  • 41
  • 1
    so glad i came across this answer. many thanks! absolutely nothing else worked for me. – 90abyss Dec 15 '21 at 05:31
  • I'm with the commenter before me: nothing else worked! But your solution is godsend. First try, no problems. Thanks so much! – jaylawl Dec 20 '22 at 20:46
5

I don't know if this applies to JAX-WS, but for JAX-RS I was able to access a file by injecting a ServletContext and then calling getResourceAsStream() on it:

@Context ServletContext servletContext;
...
InputStream is = servletContext.getResourceAsStream("/WEB-INF/test_model.js");

Note that, at least in GlassFish 3.1, the path had to be absolute, i.e., start with slash. More here: How do I use a properties file with jax-rs?

Community
  • 1
  • 1
Matthew Cornell
  • 4,114
  • 3
  • 27
  • 40
1

I had the same problem when I changed from Websphere 8.5 to WebSphere Liberty.

I utilized FileInputStream instead of getResourceAsStream(), because for some reason WebSphere Liberty can't locate the file in the WEB-INF folder.

The script was :

FileInputStream fis = new FileInputStream(getServletContext().getRealPath("/") 
                        + "\WEBINF\properties\myProperties.properties")

Note: I used this script only for development.

CupawnTae
  • 14,192
  • 3
  • 29
  • 60
Ciro Hidalgo
  • 111
  • 1
  • 6
1

I had a similar problem and I searched for the solution for quite a while: It appears that the string parameter is case sensitive. So if your filename is abc.TXT but you search for abc.txt, eclipse will find it - the executable JAR file won't.