Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load a resource contained in a jar

Tags:

In my application I load resources in this manner:

WinProcessor.class.getResource("repository").toString(); 

and this gives me:

file:/root/app/repository   (and I replace "file:" with empty string) 

This works fine when I run my application from the IDE, but when I run the jar of my application:

java -jar app.jar 

The path becomes:

jar:/root/app.jar!/repository 

is there any way to solve this problem?

I'll use the "repository" dir name in order to create this:

ConfigurationContext ctx = (ConfigurationContext) ConfigurationContextFactory.createConfigurationContextFromFileSystem(repositoryString, null); 

In the same manner, I'll get one file name (instead of a dir) and I'll use it this way:

System.setProperty("javax.net.ssl.trustStore", fileNameString) 
like image 628
Giancarlo Avatar asked Feb 22 '09 12:02

Giancarlo


People also ask

How do I add a resource file to a JAR file?

1) click project -> properties -> Build Path -> Source -> Add Folder and select resources folder. 2) create your JAR!

Can jar contain resources?

jar ) contain your executable classes and resource files. A jar can also contain other jar files, which is useful when your program needs some library which is packaged in a jar.


2 Answers

It sounds like you're then trying to load the resource using a FileInputStream or something like that. Don't do that: instead of calling getResource, call getResourceAsStream and read the data from that.

(You could load the resources from the URL instead, but calling getResourceAsStream is a bit more convenient.)

EDIT: Having seen your updated answer, it seems other bits of code rely on the data being in a physical single file in the file system. The answer is therefore not to bundle it in a jar file in the first place. You could check whether it's in a separate file, and if not extract it to a temporary file, but that's pretty hacky IMO.

like image 149
Jon Skeet Avatar answered Oct 13 '22 09:10

Jon Skeet


When running code using java -jar app.jar, java uses ONLY the class path defined in the manifest of the JAR file (i.e. Class-Path attribute). If the class is in app.jar, or the class is in the class path set in the Class-Path attribute of the JAR's manifest, you can load that class using the following code snippet, where the className is the fully-qualified class name.

final String classAsPath = className.replace('.', '/') + ".class"; final InputStream input = ClassLoader.getSystemResourceAsStream( path/to/class ); 

Now if the class is not part of the JAR, and it isn't in the manifest's Class-Path, then the class loader won't find it. Instead, you can use the URLClassLoader, with some care to deal with differences between windows and Unix/Linux/MacOSX.

// the class to load final String classAsPath = className.replace('.', '/') + ".class";  // the URL to the `app.jar` file (Windows and Unix/Linux/MacOSX below) final URL url = new URL( "file", null, "///C:/Users/diffusive/app.jar" ); //final URL url = new URL( "file", null, "/Users/diffusive/app.jar" );  // create the class loader with the JAR file final URLClassLoader urlClassLoader = new URLClassLoader( new URL[] { url } );  // grab the resource, through, this time from the `URLClassLoader` object // rather than from the `ClassLoader` class final InputStream input = urlClassLoader.getResourceAsStream( classAsPath ); 

In both examples you'll need to deal with the exceptions, and the fact that the input stream is null if the resource can't be found. Also, if you need to get the InputStream into a byte[], you can use Apache's commons IOUtils.toByteArray(...). And, if you then want a Class, you can use the class loader's defineClass(...) method, which accepts the byte[].

You can find this code in a ClassLoaderUtils class in the Diffusive source code, which you can find on SourceForge at github.com/robphilipp/diffusive

And a method to create URL for Windows and Unix/Linux/MacOSX from relative and absolute paths in RestfulDiffuserManagerResource.createJarClassPath(...)

like image 43
Rob Philipp Avatar answered Oct 13 '22 10:10

Rob Philipp