Use of java.lang.Class.getResources - java

I've seen some posts on using java.lang.Class.getResources() and java.lang.Class.getResourcesAsStream() on SO today. Somehow, I still have confusion.
I have a Jar file that contains this structure (resources/test.xml)
This jar file is on the classpath of my application, and when I call below piece of code, it returns null, i.e. value of mappingURL is null.
URL mappingURL = this.getClass().getResource("/resources/test.xml");
However when I store the XML file in exploded format on the classpath i.e. by creating a directory "resources" and storing mapping.xml inside, it works.
I'm using this URL for reading the content of the "test.xml" file later.
Does that mean, getResources() is not the appropriate method for reading the files from inside a Jar? I didn't understand why mappingURL is null when file (test.xml) is present in the Jar file?

The getResource() method will return null if it cannot find the resource. You are prefixing the resource with a / which means that it is trying to look in the folder. You should be able to remove the leading / and achieve your intended result.
Here is the getResource() method description from the documentation:
Finds the resource with the given name. A resource is some data (images, audio, text, etc) that can be accessed by class code in a way that is independent of the location of the code.
The name of a resource is a '/'-separated path name that identifies the resource.
This method will first search the parent class loader for the resource; if the parent is null the path of the class loader built-in to the virtual machine is searched. That failing, this method will invoke findResource(String) to find the resource.

this.getClass().getResource("/resources/test.xml");
That should work, provided that the class file you are starting with is also in the same JAR file.

Does that mean, getResources() is not the appropriate method for
reading the files from inside a Jar?
This is correct. If your resource will be bundled in a jar, you always want to use getResourceAsStream().
A single line later and you can start reading the file:
BufferedReader reader = new BufferReader(InputStreamReader(getResourceAsStream("/test.xml")));
reader.readLine();
//...

Related

GetResourceAsStream returning null, file exists

I know there are many topics out there for this but I have seem to have tried everything. I can put my file name in there and it finds it if there is a src folder,
InputStream is = context.class.getClassLoader().getResourceAsStream("file.props");
but when we put it on an apache server, a src folder is not automatically created, so it isn't finding it. I have tried placing it directly in the web-inf folder and
InputStream is = context.class.getClassLoader().getResourceAsStream("/WEB-INF" + File.separator + "file.props");
But this is always returned as null. What is the reason for this? The file exists there, why can't it find it?
You appear to be using the wrong ClassLoader. Invoking context.class.getClassLoader() provides the ClassLoader with which the ServletContext class (context.class) was loaded. What you want is the ClassLoader for the web application's classes, which would be context.getClassLoader().
Don't use the ClassLoader if you want to load your file from /WEB-INF. Instead, use the ServletContext's method for just that purpose:
// In your servlet e.g. doGet method
ServletContext app = super.getServletContext();
InputStream in = app.getResourceAsStream("/WEB-INF/file.props");
Note that using / is okay regardless of the OS, filesystem, etc.
If you really want to use the ClassLoader, take #rickz's advice and move your file.props into WEB-INF/classes.

Loading an image from the Resource Folder

The code I am using to load the image is:
ImageIO.read(SpriteSheet.class.getResource(path));
The path being the path to the resource. But it would error with IllegalArgumentException. I wondered what might be causing and came to the conclusion that the resource should be added into the same path as the class.
Is it possible to load the image from another folder, like a res folder outside of the bin folder? (folder holding compiled classes)
EDIT:
So i messed around with a few things, and came to a solution. But now I have another problem. Here is my code
File sheet = new File(SpriteSheet.class.getProtectionDomain().getCodeSource().getLocation().getPath());
URI uri = sheet.toURI();
BufferedImage image = ImageIO.read(uri.toURL());
When I try to run it, it gives me an IIOException: Can't read Input File
This means that I can never actually get it work. I tried debugging by prining the URL to the console and this is the URL.
C:\Users\Amma\Abhijeet\Eclipse%20Workspace1\Test%20Game\bin
The %20 comes in the middle. Meaning that the file is and never can be acceesed. Is there anyway I can fix this?
Thanks.
Class.getResource will return null if the resource could not be found or the invoker doesn't have adequate privileges to get the resource.
All variants of ImageIO.read will throw an IllegalArgumentException if they receive a null input.
Take a look at the documentation of the getResource to understand how an absolute resource name is constructed from the given resource named and what are the rules for searching resources.
You can read images from any location as long as you have permissions to do so, the ImageIO.read method accepts a File, URL or InputStream so you have many option to do it.

Determine if a resource from the ServletContext is a file or directory

Given that we use the code below
Set paths = servletCtxt.getResourcePaths("/app/themes");
How can we tell if the path in paths is directory or a actual file?
This would usually be in an zipped war.
What I did find is this, but I am betting it isn't reliable:
When it is a file
servletCtxt.getResource(dir).getContent()
returned (java.io.ByteArrayInputStream) java.io.ByteArrayInputStream#5a645a64
When it is a directory it returned:
(org.apache.naming.resources.FileDirContext) org.apache.naming.resources.FileDirContext#57155715
Is it safe to say that I could use a instanceof with InputStream on what is returned by getContent?
Thanks
Without testing I see the following in the JavaDoc of getResourcePaths():
Paths indicating subdirectory paths end with a /.
[...]
For example, for a web application containing:
/welcome.html
/catalog/index.html
/catalog/products.html
/catalog/offers/books.html
/catalog/offers/music.html
/customer/login.jsp
/WEB-INF/web.xml
/WEB-INF/classes/com.example.OrderServlet.class
/WEB-INF/lib/catalog.jar!/META-INF/resources/catalog/moreOffers/books.html
getResourcePaths("/") would return {"/welcome.html", "/catalog/", "/customer/", "/WEB-INF/"}, and getResourcePaths("/catalog/") would return {"/catalog/index.html", "/catalog/products.html", "/catalog/offers/", "/catalog/moreOffers/"}.
Seems like you can simply rely on the last character of the path.

getResource with parent directory reference

I have a java app where I'm trying to load a text file that will be included in the jar.
When I do getClass().getResource("/a/b/c/"), it's able to create the URL for that path and I can print it out and everything looks fine.
However, if I try getClass().getResource(/a/b/../"), then I get a null URL back.
It seems to not like the .. in the path. Anyone see what I'm doing wrong? I can post more code if it would be helpful.
The normalize() methods (there are four of them) in the FilenameUtils class could help you. It's in the Apache Commons IO library.
final String name = "/a/b/../";
final String normalizedName = FilenameUtils.normalize(name, true); // "/a/"
getClass().getResource(normalizedName);
The path you specify in getResource() is not a file system path and can not be resolved canonically in the same way as paths are resolved by File object (and its ilk). Can I take it that you are trying to read a resource relative to another path?

classloader.getSystemResourceAsStream returns null

I'm trying to load a properties file without using the actual path of the file. I've already done that on some other simple apps using:
InputStream inputStream = ClassLoader.getSystemResourceAsStream(PROPERTIES_FILE);
props.load(inputStream);
But this time it doesn't work. The inputStream is null for some reason. PROPERTIES_FILE is a constant defined as "app.properties". I tried to remove the .properties extension and got the same results.
Any ideas?
Thanks.
The PROPERTIES_FILE constant should include the package as well as the properties file (e.g. "com/some/library/file.properties".
final static String PROPS_FILE = "/com/some/library/file.props";
//The preceding "/" is dependendant on wheterh
//you are going to be giving a relative or absolute location
InputStream is = YourCurrentClass.class.getResourceAsStream(PROPS_FILE);
Got the same problem.
Reason: I renamed DAO package to dao. While exploding the artifact, directory DAO not get overwritten.
So I got dao in project internals and DAO in filesystem :facepalm:
When getSystemResourceAsStream returns null, it means the resource was not found. Make sure the requested resource really is on the classpath at the specified location.

Categories

Resources