IllegalArgumentException at Java Jar resource access - java

I have spent all last night (until 3am) and this morning researching, testing, refactoring, and attempting to debug this issue. I have a simple Java game in Netbeans and while it runs perfectly perfect within the IDE in either run or debug mode, once exported into a jar file it refuses to load any resources corrrectly. There are many similar questions to this such as this one regarding loading an ImageIcon and despite great effort none of these solutions work for my project. I am not using ImageIcons, only simple BufferedImages and wav sound files. I recently refactored to combine my BufferedImageLoader and Sound classes into one Resource class, which I then moved into the same package as all my resources even though it worked perfectly well in a separate code package before in the IDE, although it works in its new location as well, strictly within the IDE.
I'm rather irritated and flustered from this issue. The truly infuriating thing is that this project used to work with resources after being exported into a jar, and now it seems to have stopped working with no changes. The only real programmatic difference between back when it worked and now is that I didn't have or use sound files back then, but this error isn't related to the sound files, as it catches an exception (and generates an error dialog) just from first trying to load the art assets.
I've tried every possible solution I've found in my research to no avail. Hopefully a fresh set of eyes can reveal the error of my ways.
The offending line of code is
return ImageIO.read(Resource.class.getResource("/res/" + imageFileName));
whereas imageFileName is the parameter with values passed from method calls such as
blockSheet = Resource.loadImage("art_assets/platform.png");
The location of the Resource class seemed to have no bearing on this working within Netbeans. My res folder is inside src, next to the com class package beginning.
It throws an IllegalArgumentException: input == null! exception. After some testing it seems that Resource.class.getResource("/res/" + imageFileName) returns a null value, which makes no sense at all. Again, this works perfectly perfect within the IDE. I can change the jar file into a zip and look inside to see that all the resources are exactly where they should be with the correct names and the correct extensions.
Here is a zip file of my entire project. Any help is immensely appreciated. Thank you.
EDIT:
Some of the things I've already tried:
getResourceAsStream() instead of getResource()
classLoader() between Resource.class and getResource()
this.getClass() instead of Resource.class from a non-static context

I think this should help:
How to get the path of a running JAR file?
CodeSource codeSource = YourMainClass.class.getProtectionDomain().getCodeSource();
File jarFile = new File(codeSource.getLocation().toURI().getPath());
String jarDir = jarFile.getParentFile().getPath();
provided by Benny Neugebauer in the post.

Related

Interaction betewen Makefile, the Java RMI module and Java packages

To start, this project was developed in Eclipse and then all the source files were moved onto a Unix system to be tested. There are four different stages to my problem.
All files are in the default package : Project runs
Files are seperated into packages : Project no longer runs
Files are returned to the default package : Project still doesn't run
File contents are copied into another project : Project run
So, in the first stage we have 6 files, all in the default package. They are:
Main.java (This chooses which type of RMI object to make and execute ie. Server/Client)
RMIFunction.java {implements MapperInterface}
RemoteInterface.java {implemets Remote}
ConnectionInterface.java (This is to allow polymorphism in Main)
RMIClient.java {implements ConnectionInterface}
RMIServer.java {implements ConnectionInterface}
At this stage of my project everything runs fine, and all RMI Functions work.
In the second stage of my project, I decided to organize my files into packages.
Application: Main.java
Objects: Everything else
Makefile: executes javac package/file.java for all files
At this point, my program has stopped working and I spend a good three hours researching my problem on Google (a good portion of that time on here). The errors might have something to do with the makefile changing the compiled files in some way that I don't know of(PS. I know practically nothing of makefiles, I took the one I used off the internet to compile all of my java files). I got a Connection error and I fooled around with rmiregistry calls(none of these worked, since the port was supposedly already being used by an unnamed program...)
My next stage was out of frustration, where I just put everything back into default package. I was hoping that everything would go back to the way it was. Lo and behold, it was still broken, but this time I had a different error:
UnmarshalException: ... nested exception; ClassNotFoundException
So, here I thought that the RMIFunctions_stub was not being found by my Main file, where the exception was being thrown. I did a lot of research into classpaths, which came up dry. I was particularly confused because I could see the file that was not found in the same directory as Main.
So, the fourth stage that I was reduced to was to make a whole new project, copy and paste all the contents of the 6 original files into new files(all named the same) and now it magically works.
If anyone can share some insight on how this problem happened/was resolved that would be fabulous. My intuition now is that there's some metadata stored somewhere in eclipse when you make a package, and that's what messed up the files in stage 3.
PS. If someone wants to see some actual code where my explanation is lacking, I'll put it up. I just didn't want to throw up 7 different files and overwhelm people trying to figure out the problem.
EDIT 02/08/2015 -
#immibis: stopped working was explained in the short explanations of the different stages, that is which errors were thrown and such.
#EJP: thanks for the suggestion

Load files dynamically in multiple environments

so I am in the process of making a small application.
Right now, the project works fine. I am running it through an IDE. The problem comes about when trying to run the project as a jar - which is the end result. Right now, it fails to properly load the required files (classes and simple ASCII files).
The method I am using is one based off of:
final Enumeration<URL> paths = CLASS_LOADER.getResources("");
Where CLASS_LOADER is an instance of class.getClassLoader().
This works great when not inside a jar. Inside a jar though, it seems to fail horribly. For example, in the code above, paths would be empty.
I am assuming that the fault is that the files are all within a jar - the same jar to be precise.
The class path for the manifest file is blank at the moment.
If it helps, I have two tasks that require loading files.
I need to create a list of all files that are a subclass of
another class.
I need to load a list of language files (all of
which are in the same directory).
If you need anything else to help debug this problem or provide a solution - let me know. Thanks for reading this!
For ClassLoader.getResources() to work you need to feed a path relative to the jar root. If you want to search the jar then ClassLoader public API won't help you. You have to use custom code based on java.util.jar.JarFile, like the one here.

JAR won't work after adding images

I've written a game that uses PNGs, and when I exported it, the images wouldn't work. I added getClass().getClassLoader().getResource() to everywhere I import an image, but the JAR won't even launch anymore. It used to open, but none of the images worked. Now it won't even open the JAR.
This is how I get the image for the muffin:
muffin=new ImageIcon(getClass().getClassLoader().getResource("muffin.png")).getImage();
Actual path for it is: C:\Users\My User Name\Dropbox\FinalProjectWithoutApplet\muffin.png
What should I do to solve this issue?
Thanks!
getClass().getClassLoader().getResource("muffin.png") is looking for the image muffin.png in the same directory where your class is.
I means that if your class's name is com.mycompany.game.MyClass the image is expected to be in com/mycompany/game/muffin.png. If this is not the location write absolute path that starts with /, for example /img/muffin.png.
And in future if program does not work start from examining the stack trace.
I found the issue. Turns out my cases mismatched. The IDE didn't care that one was called "muffin.png" in code vs. "Muffin.png". Another case I found was "DoubleJumpIcon.png" vs. "DoubleJumpIcon.PNG". Every single case matters it turns out.

Get Android application lib directory

I need to specify the location of some native libraries in my Android application. I was accomplishing this with a hard-coded string:
public static final String DLL_DIR_STR = "/data/data/my.application.package/lib";
but wanted to get the path from Android instead. Following posts like this, I used getDir() to find the lib directory, changing
superCollider = new SCAudio(DLL_DIR_STR);
to
superCollider = new SCAudio(container.$context().getDir("lib", 0).getAbsolutePath());
Oddly, the initial libraries seem to load correctly
Trying to load lib /data/data/my.application.package/lib/libsndfile.so 0x42718d80
Added shared lib /data/data/my.application.package/lib/libsndfile.so 0x42718d80
No JNI_OnLoad found in /data/data/my.application.package/lib/libsndfile.so 0x42718d80, skipping init
Trying to load lib /data/data/my.application.package/lib/libscsynth.so 0x42718d80
Added shared lib /data/data/my.application.package/lib/libscsynth.so 0x42718d80
But when libscsynth tries to load some additional code, it's using the wrong path:
OK, listing opendir(/data/data/my.application.package/app_lib)
Any ideas where the "app_" comes from? I thought I must be using getDir() wrong, but the initial files load fine. Could it be something in the native code? Thanks for your help.
I found the answer, quite by accident, in this post. ApplicationInfo.dataDir holds the location of the data directory, and "lib" is easily navigated to from there:
superCollider = new SCAudio(container.$context().getApplicationInfo().dataDir + "/lib");
Alternatively, nativeLibraryDir takes you directly to the lib directory, but requires API level 9.
Thanks for your help!
getDir will always prepend app_ to the directory name so it is very odd that it is working the first time. I would either just expect the app_ to be there or try using getFilesDir, at least you always know what it will return. Does SuperCollider have a restriction on what the directory name is?
I found another SuperCollider Project that seems to be doing the same thing you did initially with the comment "// TODO: not very extensible,".. I found that funny :)

Java - .jar unexpected issue with Netbeans

First of all, I am aware of Stack Overflow (and any competent forum-like website) policy of "search first, ask last", and, doing my homework, I searched various sources to find a solution to my issue. That said, I, failing to find any suitable answers, was left no choice but to ask this problem personally.
I have somewhat moderate programming skills, especially regarding the Java language. I am working on this 2D game with the default Java SE JDK. More specifically JDK 7u4. In this project, we have a class that manages most I/O operations. One of its methods returns the path to a file:
public static URL load(String resource) {
return ZM.class.getResource(resource);
}
Now, this method works fine when running the project on Netbeans (version 7.1). However, when building and cleaning the project, the resulting .jar file does not seem to agree with its creator. When running the .jar on command line, the JVM caught a NullPointerException. It seemed that the file was not being able to be read inside the .jar. Following my programmers instinct, I started debugging the project. My first attempt was to check whether the load method was the faulty member. I ran some tests and obtained a couple of interesting results:
When running the application on Netbeans and with "ZM.class" as the methods argument, it returned:
/D:/Projects/GeometryZombiesMayhem/build/classes/geometryzombiesmayhem/ZM.class
But when running it from the .jar file, it returned:
file:/D:/Projects/GeometryZombiesMayhem/dist/GeometryZombiesMayhem.jar!/geometryzombiesmayhem/ZM.class
Naturally, I tried removing the initial file: string from it. No effect. Then I tried taking the exclamation mark from [...].jar![...]. Again, nothing. I tried removing all the possible permutations from the path. No luck.
Testing the method against the very own .jar file worked okay. Now, when I try to access the inside of the file, it doesn't let me. On earlier versions of this project it worked just fine. I am not really sure of what is going on. Any help is welcome.
Thank you in advance,
Renato
When loading resources from a jar file, I've always used a classLoader. Everything seems to work the same whether you run from within the IDE, launch the executable jar file or run the program from a web site using JNLP.
Try loading the resource this way instead:
try {
ClassLoader cl = ZM.getClass().getClassLoader();
ImageIcon img = new ImageIcon(cl.getResource("images/programIcon.jpg"));
// do stuff with img.
}
catch(Exception failed) {
System.out.println(failed);
}
One more suggestion - you should create a separate folder for resources. In my example above, images is a folder inside of my src folder. This way it will automatically become part of the jar when I build it, but I am keeping resources separate from source code.
I suppose your problem is in loading an image from your jar file.
Here is how i do it
URL imageurl = Myclassanme.class.getResource("/test/Ergophobia.jpg");
Image myPicture = Toolkit.getDefaultToolkit().getImage(imageurl);
JLabel piclabel = new JLabel(new ImageIcon( myPicture ));
piclabel.setBounds(0,0,myPicture.getWidth(null),myPicture.getHeight(null));
This way I can get the Ergophobia.jpg file inside 'test' package.

Categories

Resources