class.getResource() always return null

What I’m trying to do is to create a runnable .jar file from java. What I do is I fill the .jar file with resources, then I copy my .class files and the manifest file from another .jar file.
However, when I start the newly created .jar file, it starts up as normal. However, all calls to MyClass.class.getResource() always return null.
I have opened the .jar file with winrar and confirmed that the resources exist (they do indeed exist).

So my problem is basically that MyClass.class.getResource() can’t find any resources even though they exist.

Here is the code I use to create the .jar file.

//This function build to the project to the specified file
    public void buildProject(File file) {
        if (file == null)return;

        try {
            JarOutputStream out = new JarOutputStream(new FileOutputStream(file), new JarFile(GenericMethods.getHome()).getManifest());

            //First copy all src-files
            insert(new File("src/"), out);

            //Now copy the class files from this jar
            File jarfile = new File(GenericMethods.getHome());
            if(!jarfile.isDirectory()) insertFromJAR(out, jarfile);

            out.close();
            
        } catch (IOException ex) {
            Logger.getLogger(ProjectBuilder.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    //@input File f is the file that will be inserted
    //@input JarOutputStream out is the ouputstream connected to a jar file.
    public void insert(File f, JarOutputStream out) {
        if(f.isDirectory()) {
            File[] files = f.listFiles();
            for(File file:files)insert(file, out);
        }else {
            byte[] buf = new byte[1024];
            try {
                InputStream in = new BufferedInputStream(new FileInputStream(f));

                String path = f.getPath();
                if(path.startsWith("src"))path = path.replaceFirst("src", "").substring(1);
                out.putNextEntry(new JarEntry(path));

                int len;
                while((len=in.read(buf)) > 0) {
                    out.write(buf, 0, len);
                }

                out.closeEntry();
                in.close();
            } catch (IOException ex) {
                Logger.getLogger(ProjectBuilder.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public void insertFromJAR(JarOutputStream out, File jarFile) {
        try {
            JarFile jf = new JarFile(jarFile);
            
            //Get the enumerations from the zipfile
            Enumeration enums = jf.entries();

            byte[] buf = new byte[1024];

            //Loop until the enumeration has no more elements
            while(enums.hasMoreElements()) {

                //Get the next entry
                JarEntry entry = (JarEntry) enums.nextElement();

                //Check if the entryname starts with the folder name
                if(entry.getName().startsWith("Game")) {
                    InputStream in = jf.getInputStream(entry);

                    String path = entry.getName();
                    out.putNextEntry(new JarEntry(path));

                    int len;
                    while((len=in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }

                    out.closeEntry();
                    in.close();
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(ProjectBuilder.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

I’m not even seeing getResource in that class.
system out print the path getResource gives you.

I’m using the following to get the resource:

Main.class.getResource("/System/entities.xml")

That however returns null. Here is a screenshot that shows that entities.xml does exist.

http://www.trololol.se/error.png

Drop the first slash.

Didn’t work :frowning:

Guess I have to write my own classloader to force java to find my resources :stuck_out_tongue:

The following is known to work, always, everywhere:


InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("System/entities.xml");

If it doesn’t work, you might not have the JAR in your classpath.

Have a read of the javadoc; it explains how the path is resolved.

To summarize:

If the resource name begins with ‘/’, then the path is absolute - taken from the root of the class path. (i.e. it will find resources that reside in what would be otherwise called the default package)
Otherwise, the resource is relative to the package folder of the Class you are invoking the method upon.

So:

somePackage.SomeClass.class.getResourceAsStream("data/some.file");

will give the same results as:

AnyClass.class.getResourceAsStream("/somePackage/data/some.file");

I’m not sure why your initial example doesn’t work; you might need to show a little more of your code structure. What package is Main.class in? is it in the same archive as “/System/entities.xml”?

That unfortunately returned null aswell :s
Also I’m not sure how to add the jar to the classpath since all I do is copy some resources and compiled class files from another jar.

http://www.trololol.se/error2.png

That image shows the root-folder in my jar file. Main.class is located in the Game folder while my entities.xml file is located in the System folder.

I’m going to write my own class loader and see if that works. Thanks for your help guys, I really appreciate it :slight_smile:

Problem is solved now. Apparently there is difference between adding the entries to a jarfile as \System\entities.xml and as /System/entities.xml :stuck_out_tongue:

Why aren’t you using Ant or Maven to create your jar file?