Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should resources in a compiled jar be accessed?

First of all, I have read through many S.O. questions regarding this topic and I have tried the things suggested in them.

Here is my situation. I am writing a Java app using the Processing framework and I'm in the final stages where I need to begin thinking about packaging the app. A jar file that is executable from the command line is what I'm attempting to build using the Export feature in Eclipse.

The structure of my project looks like this:

src/
   multiple packages/
libs/
   jar files and natives
data/
   fonts and images
config/
   json files

When I export the jar file and uzip the jar to inspect it's contents, I find that the contents of these dirs have been dumped in the top level of the .jar.

Which looks like this:

.jar
    packages
    jar files
    fonts
    json files

So, when I attempt to load a config file with something like:

BufferedReader reader = new BufferedReader( new FileReader( path ) );

Everything works just file when I run the app in Eclipse. But the jar file throws a FileNotFoundException.

Many of the questions that I've seen on S.O. regarding problems like these recommend using using class.getClass().getResource() or class.getResourceAsStream(). I have tried both of these using relative paths and just the file name as in:

class.getResource( 'config.json' );
class.getResources( 'cfg/config.json' );
class.getResourceAsStream( '../../config.json' );

All of these methods return null, when run from either Eclipse or the jar using:

java -jar myjarfile.jar

I am also open to using an Ant file. In fact, I'm now using the Ant file generated by the export feature to build the jar. If there is something I can add to that to add the directories into the jar that would be great too.

like image 260
JeremyFromEarth Avatar asked Jul 15 '12 22:07

JeremyFromEarth


2 Answers

To reach resources in the root, prepend a / to the path. If not, you do it relative to the current package, which is usually only useful if the resource is physically next to the class in your sources too.

So use class.getResourceAsStream("/config.json"); to reach config.json in the root of the jar.

Also note that jars-inside-jars are not directly supported.

like image 72
Thorbjørn Ravn Andersen Avatar answered Oct 03 '22 22:10

Thorbjørn Ravn Andersen


Your .jar file should just include the directories related to the "package" for the compiled code. You might be referencing a .war structure with /lib /WEB-INF etc. and this is different.

If your package structure is:

 com.yourco.authentication

And your class in Login

Then your jar should be

/com/
  /yourco/
    /authentication/
        Login.class

you then need the .jar in your classpath for the env to run via command line.

I see you note it works in Eclipse which likely has environment settings and imported required libs, etc. so hard to tell exactly. If your packages/ folder includes the compiled java code, I'm unsure if that'll work when referenced externally, thus suggesting you start your packages in the root folder.

like image 36
Mike S. Avatar answered Oct 04 '22 00:10

Mike S.