Search code examples
javanetbeansprojectembedded-resource

Jar Embedded Resources NullPointerException


I originally started with Chillax, after Encountering so many problems so near to deadline, I went back to the IDE I am more familiar with, NetBeans, and I changed my approach to a more basic "Asteroid"-type game:

In NetBeans I get:

Exception in thread "main" java.lang.NullPointerException
at javax.swing.ImageIcon.<init>(ImageIcon.java:205)
at gayme.Craft.<init>(Craft.java:27)
at gayme.Board.<init>(Board.java:54)
at gayme.Gayme.<init>(Gayme.java:9)
at gayme.Gayme.main(Gayme.java:19)
Java Result: 1

sources: (Craft 26 - 34)

    public Craft() {
    ImageIcon ii = new ImageIcon(this.getClass().getResource("craft.png"));
    image = ii.getImage();
    width = image.getWidth(null);
    height = image.getHeight(null);
    missiles = new ArrayList();
    visible = true;
    x = 40;
    y = 60;}

(Board 54)

    craft = new Craft();

(Gayme 9)

    add(new Board());

(Gayme 19)

   new Gayme();

I have issues that I really need resolved and my sleep deprived brain is coming up with a loss on each. Feel free to help out on whichever game you'd rather. Thanks so much guys!


Solution

  • There are 3 methods:

    A few things to remember about working with Jar files and resources located within:

    • JVM is case sensitive thus file and package names are case sensitive. i.e Main class is located within mypackage we cannot now extract it with a path like: myPackAge

    • Any period '.' located within the package name should be replaced by '/'

    • If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'. Resource names begin with / when executing class and the resources are in different packages.

    Lets put that to the test using my preferred method of getResource(..) which will return the URL of our resource:

    I create a project with 2 packages: org.test and my.resources:

    enter image description here

    As you can see my image is in my.resources while the Main class which hold main(..) is in org.test.

    Main.java:

    import java.awt.image.BufferedImage;
    import javax.imageio.ImageIO;
    
    public class Main {
    
        public static final String RES_PATH = "/my/resources";//as you can see we add / to the begining of the name and replace all periods with /
        public static final String FILENAME = "Test.jpg";//the case sensitive file name
    
        /*
         * This is our method which will use getResource to extarct a BufferedImage
         */
        public BufferedImage extractImageWithResource(String name) throws Exception {
    
            BufferedImage img = ImageIO.read(this.getClass().getResource(name));
    
            if (img == null) {
                throw new Exception("Input==null");
            } else {
                return img;
            }
        }
    
        public static void main(String[] args) {
            try {
                BufferedImage img = new Main().extractImageWithResource(RES_PATH + "/" + FILENAME);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    
        }
    }
    

    If you play around with the names of the RES_PATH or FILENAME without making appropriate changes to actual files you will get an exception (just shows yous how careful we must be with paths)

    UPDATE:

    For your specific issue you have:

    ImageIcon ii = new ImageIcon(this.getClass().getResource("craft.png"));
    

    it should be:

    ImageIcon ii = new ImageIcon(this.getClass().getResource("/resources/craft.png"));
    

    The Alien and other classes also need to be changed.