Charlie Mulic
Charlie Mulic

Reputation: 199

Exporting jars with resources

I'm trying to build a large Java project by building many small, modular projects. I want each small project to be entirely self contained, holding all of its resources (such as images).

I am using Eclipse. If I configure the build path to add one of the modular projects, the resource references don't work. The system cannot find the file specified. The same thing occurs if I export a jar and include that in the libraries tab of configure build path.

I've done some experimenting, and haven't been able to figure out a way to get it to work. I've tried using source folders for resources and using:

// this works if resource is located in package alongside class file, 
// not where I want it
getClass().getResourceAsStream("resource.abc")

or

new FileInputStream("path/to/resource.abc")

Maybe I'm missing something about how projects are structured. I've always been able to get resources to work from a single project within the IDE without any trouble. What is different when you start linking multiple projects or including them as jars?

My ideal structure would be to have another folder, at the same level as the src folder in the root of my project, that would contain all of my resources, separate from source code. This is how it was set up before all the trouble trying to link projects/jars.

Upvotes: 3

Views: 2130

Answers (3)

Cratylus
Cratylus

Reputation: 54074

You have multiple projects comprising a single application? So if you run this via Eclipse all works?
If yes, then just in your main project do Export as Runnable Jar. This should work as well

Upvotes: 0

David Kroukamp
David Kroukamp

Reputation: 36423

This solution worked for me:

/**
 *
 * @author David
 */
public class JavaApplication60 {
/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    //http://img.viralpatel.net/java-cup-logo.png

    //located in a package not in the current one
    URL url = new JavaApplication60().getResource("/javaapplication60/newpackage/java-cup-logo.png");
    System.out.println(url.getPath());
    //located in same package
    url = new JavaApplication60().getResource("/javaapplication60/java-cup-logo.png");
    System.out.println(url.getPath());
}

public InputStream getResourceAsStream(String name) {
    name = resolveName(name, this.getClass());
    ClassLoader cl = getClass().getClassLoader();
    if (cl == null) {
        return ClassLoader.getSystemResourceAsStream(name); // A system class.
    }
    return cl.getResourceAsStream(name);
}

public java.net.URL getResource(String name) {
    name = resolveName(name, this.getClass());
    ClassLoader cl = getClass().getClassLoader();
    if (cl == null) {
        return ClassLoader.getSystemResource(name);  // A system class.
    }
    return cl.getResource(name);
}


/*
 * The resolveName method adds a package name prefix if the name is not
 * absolute, and removes any leading "/" if the name is absolute. It is
 * possible, though uncommon, to have classes in diffent packages sharing
 * the same resource.
 */
private String resolveName(String name, Object clazz) {
    if (name == null) {
        return name;
    }
    if (!name.startsWith("/")) {
        Class c = clazz.getClass();
        while (c.isArray()) {
            c = c.getComponentType();
        }
        String baseName = c.getName();
        int index = baseName.lastIndexOf('.');
        if (index != -1) {
            name = baseName.substring(0, index).replace('.', '/') + "/" + name;
        }
    } else {
        name = name.substring(1);
    }
    return name;
}
}

My package structure looked like this:

My package structure for above code

References:

Upvotes: 1

Chris Gerken
Chris Gerken

Reputation: 16392

To add another source folder for your resources first create the folder. In a java perspective, select the project and from the context menu choose "configure build path". In the source folder tab you can make that newly created folder a source folder for your project. From then on, all resources under that folder can be exported to a jar with the project classes.

By the way, the path you specify for getResourceAsStream is either just the resource file name if the resource is in the same package as the class or is the relative path name (starting with a slash) for the resource from the source folder you're using.

Upvotes: 0

Related Questions