I've read up some questions by people having problems loading resources. I have followed the instructions they've got (though these instructions actually differ which means either were incorrect - I tried all).
I created enum
to load the resources for me when needed. It's long but I'll share it in case somebody came here from google and could make use of it:
package cz.autoclient.GUI;
/**
* Enum of resources used for GUI. These resources are packed in .jar and are for internal use.
* Provides lazy-loaded Image and ImageIcon for comfort.
* @author Jakub
*/
public enum ImageResources {
ICON("IconHighRes.png");
//So according to [this guy](https://stackoverflow.com/a/17007533/607407) I
// should enter classpath beginning with slash to make sure it's absolute path from
// the root of my .jar
public static final String basepath = "/cz/autoclient/resources/";
//Cache everything to have less letters to write
public static final ClassLoader loader = ImageResources.class.getClassLoader();
public static final Class leclass = ImageResources.class;
//String is immutable so it's ok to make it a public constant
public final String path;
//These will fill up on demand when needed
private ImageIcon icon;
private Image image = null;
//If image has failed, we'll not try to load it again and will return null straight away
private boolean image_failed = false;
//Constructor concatenates the individual path with the global path
ImageResources(String path) {
this.path = basepath+path;
}
/** Loads, or just retrieves from cache, the image.
* @return Image (not necesarily a BufferedImage) or null on failure
*/
public Image getImage() {
//Lazy load...
if(image==null) {
//Since the .jar is constant (it's packed) we can
//Remember the image is unavailable
if(image_failed)
return null;
//Use whatever is stored in Icon if we have it
if(icon!=null) {
image = icon.getImage();
}
//Load from .jar
else {
try {
image = ImageIO.read(leclass.getResourceAsStream("/images/grass.png"));
}
//While only IOException is reported it also can throw InvalidArgumentException
// when read() argument is null
catch(Exception e) {
image_failed = true;
}
}
}
return image;
}
}
Full version on GitHub. Can be subject to change.
Since this code doesn't work (due to invalid base path) I want to know a general way to find why are the resources not loading and where is the ClassLoader
looking.
For example when I had problems loading normal file from filesystem, I could do this:
File relativePath = new File("../my_test_image.png");
System.out.println(relativePath.getAbsolutePath());
And I could immediately see where's Java looking and what should I change. If I as well as others know a simple way to do this with resources, all these questions wouldn't need to be asked:
So is there a way to print what does my resource path translate to?
What I tried:
So it seems you can always get the current path by this statement:
System.out.println(" Path: \""+loader.getResource(".")+"\"");
For me, this gives:
Path: "file:/C:/... path to project .../PROJECT_NAME/target/test-classes/"
This is a path of the test class running the test, not the actual class loader
it has been created for. I do not think this is a bug.