ClassLoader loading the wrong instance of a file - java

So I see there has already been a post very similar to this issue, however I am in a situation where I have no power to specify the location of this file within my jar and so am hoping someone is aware of a solution to get around this.
So I currently use the following snippet to obtain a file as an input stream, the file 'plugin.xml' is located at the root of the jar and I cannot change this location as another piece of software (dynatrace) creates this file and determines its location.
the standard snippet:
InputStream is = JmxPlugin.class.getResourceAsStream("/plugin.xml");
Now I am aware that the issue is that the ClassLoader is picking up the first file which matches the name 'Plugin.xml' along the classpath (one which isn't in my jar, yay).
Can anyone think of a way to ensure I pick up the correct file without having to move it? The relative path of my class in the jar is com/something/jmx/JmxPlugin.class.
(Id rather not have to unpack the jar in memory).
Many thanks for any contributions,

I'm not absolutely sure, but seems like Thread.currentThread().getContextClassLoader().getResourceAsStream("/plugin.xml") may solve your issue. If not, you'll have to create your own ClassLoader and resolve the issue there.

The simplies way is to move your jar in classpath to be the first containing Plugin.xml,
Another approach is to use getResource() to locate your jar file:
URL myJar=JmxPlugin.class.getResource("/"+JmxPlugin.class.getName().replace(".","/")+".class");
then use this URL to open jar file and extract Plugin.xml.

Related

getting null pointer when reading the properties file

when reading the properties file, iam getting nullpointer exception.
faceConfig.load(ReadPropertyFile.class.getClassLoader().getResourceAsStream("/resources/faces.properties"));
below is the path of properties file facedetections/src/main/resources/faces.properties
i tried in different combinations as my class file that reads in below path /facedetections/src/main/java/com/facial/facedetection/utils/ReadPropertyFile.java
combinations are ../../../../../resource/faces.properties , /resource/faces.properties and
../../../resource/faces.properties
Please suggest what is the correct path i can provide for this.
Edit :
I extracted the war file and providing its path below.
looks your property file under class folder not in resource.
as your screen shot cant find resource folder under class folder.
So just use
ReadPropertyFile.class.getClassLoader().getResourceAsStream("faces.properties")
The path is relative to the point where the object (.class) files are located. Are you sure you have configured your build/test tool to copy the resource file into that structure? Exactly where? That's what counts, not the position of the sources.
Additionally, my understanding is that getResourceAsStream() of most ClassLoaders do not support .. notation.
The position where your resource file is currently located is out of reach of the ClassLoader. If you move your file to /facedetections/src/main/java/resources/faces.properties, then you will be able to use the current code
getResourceAsStream("resources/faces.properties")
I'm making assumptions about your environment. In particular, this is entirely dependent on classloaders. If this doesn't help, please provide object file location, not sources (unless it is the same, but state it).
Since it is unlikely that you get a NPE when the file is not found I assume that faceConfig is null when you execute that line.

Why does getResourceAsStream() work in the IDE but not the JAR?

I just want to read a file into my program. The file is located one directory above the working directory at "../f.fsh". So the following code runs correctly when I run it in the IDE
String name="../f.fsh";
InputStream is = getClass().getResourceAsStream(name);
InputStreamReader isreader=new InputStreamReader(is);//CRASHES HERE WITH NULL POINTER EXCEPTION
BufferedReader br = new BufferedReader(isreader);
but when I create a JAR file that has f.fsh zipped inside of it and run it, it crashes when creating the InputStreamReader, because the InputStream is null.
I've read a bunch of answers to questions about input streams and JAR files, and what I got out of it is that I should be using relative paths, but I am already doing that. From what I understand getResourceAsStream() can find files relative to the root of the project, that is what I want. Why does it not work in the JAR? What is going wrong, how can I fix it?
Does it have to do with the classpath? I thought that was only for including files external to the jar being run.
I have also tried, but still fail, when putting a slash in:
InputStream is = getClass().getResourceAsStream("\\"+name);
I looked at: How to get a path to a resource in a Java JAR file andfound that contents of a JAR may not necesarily be accesible as a file. So I tried it with copying the file relative to the jar (one directory up from the jar), and that still fails. In any case I'd like to leave my files in the jar and be able to read them there. I don't know what's going wrong.
You can't use .. with Class.getResourceAsStream().
To load a resource f.fsh in the same package as the class, use SomeClass.class.getResourceAsStream("f.fsh")
To load a resource f.fsh in a sub-package foo.bar of the package of the class, use SomeClass.class.getResourceAsStream("foo/bar/f.fsh")
To load a resource f.fsh in any package com.company.foo.bar, use SomeClass.class.getResourceAsStream("/com/company/foo/bar/f.fsh")
This is described in the javadoc of the getResource() method, although it lacks examples.
If .. works in Class.getResourceAsStream() while running from Eclipse, it's a bug in Eclipse. Eclipse and other IDEs implement custom class loaders to fetch resources from the project at runtime. It looks like the class loader implementation in Eclipse isn't performing all the necessary validations on input to getResourceAsStream() method. In this case the bug is in your favor, but you will still need to rethink how you structure your resources for your code to work in all cases.
it's mandatory that the name of the file is CASE SENSITIVE
it's mandatory to refresh (F5) the project explorer if the file is moved or copied outside Exclipse

How to use ClassLoader.getResources() in jar file

Problem statement:
I have a jar file with a set of configuration files in a package mycompany/configuration/file/.
I don't know the file names.
My intention is to load the file names at runtime from the jar file in which they are packaged and then use it in my application.
As far as I understood:
When I use the ClassLoader.getResources("mycompany/configuration/file/") I should be getting all the configuration files as URLs.
However, this is what is happening:
I get one URL object with URL like jar:file:/C:/myJarName.jar!mycompany/configuration/file/
Could you please let me know what I am doing wrong ?
For what you are trying to do I don't think it is possible.
getResource and getResources are about finding named resources within the classloader's classpath, not listing values beneath a directory or folder.
So for example ClassLoader.getResources("mycompany/configuration/file/Config.cfg") would return all the files named Config.cfg that existed in the mycompany/configuration/file path within the class loader's class path (I find this especially useful for loading version information personally).
In your case I think you might almost have half a solution. The URL you are getting back contains the source jar file (jar:file:/C:/myJarName.jar). You could use this information to crack open the jar file a read a listing of the entries, filtering those entries whose name starts with "mycompany/configuration/file/".
From there, you could then fall back on the getResource method to load a reference to each one (now that you have the name and path)

Images are not displaying in jar but displaying in compiler?

I know, I know, this has been asked before. But every resource I've looked at uses IconImages while I just have plain Images.
Is there a different solution? Please help as I've been stuck researching and trying to figure this out for days now with no progress.
Image Floor = Toolkit.getDefaultToolkit().getImage("Floor.PNG");
EDIT: If I was to make sure the jar wouldn't compress and I created a seperate directory in the jar for images and put the correct file path, would this code work?
Toolkit#getImage(String s) looks for a file and likely your image is in the Jar and is now a resource not a file. Look to using resources for this.
Note that ImageIO.read(...) can accept an InputStream parameter the Class class has a method, getResourceAsStream(...) which can put the resource into a Stream that ImageIO can read. Give that a try.
Also, are you getting any error messages when you try what you're doing?
Make sure you know what your current directory is, and how it relates to the position of the files in your jar.
Here's how I would handle it.
1) Require there to be a file called "images.txt" in the directory with your jar (or bundle it into the jar.)
2) Make a file called "images.txt" with a format like `FLOOR:C:\\images\\floor.png`
3) Load this file into memory on load.
4) Load your images based on the entries in the file
This will give you the advantage of changing your images without changing your code if it's defined outside the jar :)
It's not loading because you're not putting the path to the images in the declaration. It expects the images to be wherever the jar is (notice there's no directories there)
You need to offload the definition of the file names to a file, or at the very least guarantee the relative position of the files.
Another good option is to put the images in the jar itself, say in an img directory, and reference them there. But then changes to the images require a new jar, which may not be desired for development purposes.
The getImage call is looking in the file system working directory, not inside the Jar file. This is why the jar file loads the images successfully when they are placed in the same directory outside the jar file. If the images are bundled in the jar file, they are no longer file system files to be accessed, but rather Jar file resources. There is a different way to load these, but sorry, I don't know it off the top of my head.
Check the extension of files. I had this problem because the extension was "PNG", when I changed it to "png", everything was ok.
You can't expect a JAR file to magically know where your images are. If you put a JAR file alone on the desktop, it's going to look for the files on the desktop! The code
getImage("Floor.png")
searches the current directory of the JAR (or source project) by default and you'd expect that if the JAR was in the same directory, it would work. If the JAR is on the desktop how does it know where Floor.png is? Of course, you can specify a hard-coded path
getImage("C:\Some Folder Path\Floor.png")
but then Floor.png has to be in C:\Some Folder Path\ for the JAR to work properly.
It sounds like what you really want to do is keep the images in the JAR file (which acts like a ZIP file). The tutorial on doing that is here:
http://download.oracle.com/javase/tutorial/uiswing/components/icon.html#getresource
And I know for ImageIcon you use: new javax.swing.ImageIcon(getClass().getResource("myimage.jpeg") but I have not found anything similar for plain Image.
<head-desk /> You should really get into reading the JavaDocs. Otherwise you are 'coding by magic'. Which generally won't work.
URL urlToImage = getClass().getResource("myimage.jpeg");
// If you need to support Java 1.3
Image image = Toolkit.getDefaultToolKit().getImage(urlToImage);
// If your users have dragged their JRE into this millennium
BufferedImage bufferedImage = ImageIO.read(urlToImage);

Regarding Help File in JAVA

I'm new to help file creation in java. I have created a help file "sample.chm" with a 3rd party tool, added it to a java program with package name as "help" calling with runtime class and build the jar. When I run the jar file it is giving me an error that the "file cannot be found, null pointer Exception". I have given a relative path to identify the file like "../help/sample.chm" still it is not working and I tried with various classes to ientify the path. But still the same error.
Request you to please help me in fixing it.
The jar can be placed in different systems and should open this help file with out any issues.
I hope my explanation is sufficient you to identify the problem.
Regards,
Chandu
If you have a file inside a jar, you can't access it as you normally would. You can access it like this:
URL helpFile=Thread.currentThread().getContextClassLoader().getResource("help/sample.chm");
The method used above (getResource) will return a URL; if you want, you can get it as an InputStream as well by using getResourceAsStream instead.
At least a workaround unless a better solution pops up. Use the this.getClass().getClassLoader().getResource way to get an inputstream to the help file inside the jar.
Copy the bytes to a new help file in the target systems temp folder and use this extracted file with the external help file viewer.

Categories

Resources