Runnable Jar cannot find Resources and Other Libraries
Asked Answered
N

4

12

I created a desktop app and I have run into a problem with my generated runnable jar. Everything works fine in the Eclipse environment, but when I generate the jar it only shows theswtcomponents (menu, tabs, etc..). The other libraries location is a blank area (library to generate gallery). The same does not appearset ToolBar(containing buttons with images),GoogleMap.htmldoes not appear.

How can I correctly generate an executable jar that will include these external sources?

ToolBar image loading code :

folderSearchIcon = new Image(display, this.getClass().getResourceAsStream("images/search_folder.png"));

GoogleMap.html loading code :

File mapFile = new File("resources/GoogleMap.html");        
if(!mapFile.exists()) {
    System.out.println("File doesn't exist! " + mapFile.getAbsolutePath()); 
    return;
}

Generating runnable jar:

enter image description here

My app structure in Eclipse and generated jar structure:

enter image description here

Generated manifest :

Manifest-Version: 1.0
Rsrc-Class-Path: ./ swt.jar commons-imaging-1.0-SNAPSHOT.jar org.eclip
  se.nebula.widgets.gallery_0.5.3.201210262156.jar xmpcore.jar metadata
  -extractor-2.6.3.jar
Class-Path: .
Rsrc-Main-Class: geotagger.AppInit
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
Norge answered 21/12, 2012 at 12:0 Comment(15)
Do you have any exceptions in the background when you run your app through the runnable jar?Literality
Did you make sure that the resources are really contained in the jar? Just open it with an archiving software and check.Ailanthus
so lib folder is not included in the jar right? Just add them to Build Path using EclipseSkuld
@NikolayKuznetsov As you can see from the manifest and the second screenshot, the libraries are referenced in the jar.Ailanthus
On screen I showed unpacked jar content, I add lib folder to Eclipse project folder and next I choose Build Path -> Add to Build Path for each libraryNorge
@unixhead According to your screenshot, your jar doesn't contain a resources folder, but you use it to access the .html file.Ailanthus
Why is he having libraries inside lib folder and outside in Eclipse?Skuld
@NikolayKuznetsov Because that's the way Eclipse exports them...Ailanthus
@Baz, not in my case. Maybe mine is configured to hide those outside.Skuld
@NikolayKuznetsov Does your jar contain a lib folder or is the lib folder created outside the jar?Ailanthus
@Baz, jar contains lib folder, I mean hiding in Package Explorer.Skuld
@NikolayKuznetsov Then maybe you chose a different setting for "Library handling".Ailanthus
@unixhead Have you tried using: YourClass.class.getClassLoader.getResourceAsStream("images/search_folder.png"); instead?Ailanthus
The answer which works is provided https://mcmap.net/q/1009700/-getresources-for-imageicon-java by @ReimeusHieratic
@DarshanShah Thanks :DNorge
A
9

For the toolbar image you need to add a slash, i.e. instead of

this.getClass().getResourceAsStream("images/search_folder.png")

you need

this.getClass().getResourceAsStream("/images/search_folder.png")

This is because, as explained in the JavaDocs, Class.getResourceAsStream resolves relative paths against the package of the class in question, so if this is a com.example.Foo then getResourceAsStream("images/search_folder.png") would look for com/example/images/search_folder.png inside your JAR. Prepending the slash would make it look for images/search_folder.png instead, which is what your screenshot suggests you need.

You will need to use a similar trick for the GoogleMap.html - you can't load items from inside a JAR using java.io.File, but you could use this.getClass().getResource("/GoogleMap.html") to get a java.net.URL pointing to the HTML file inside your JAR.

Antimacassar answered 21/12, 2012 at 12:38 Comment(5)
Thanks it works! Runnable jar shows entire contents of the app but GoogleMap.html doesn't load in SWT Browser (in Eclipse works) but Browser has connection with network, GoogleMap.html loading code : try { URL mapFile = getClass().getResource("/GoogleMap.html"); browserMap = new Browser(compositeTabItemMap, SWT.NONE); browserMap.setUrl(mapFile.toString()); } catch(NullPointerException e) { e.printStackTrace(); }Norge
@unixhead In that case you may have to load the HTML into a string yourself and use setText instead of setUrl. The SWT Browser is a wrapper around a native browser and may not be able to load Java-specific URL schemes.Antimacassar
So there is no other way to execute *.html file in jar ? It is much easier and more clearly :(Norge
I tried this: InputStream getHtml = getClass().getResourceAsStream("/GoogleMaps.html"); Scanner htmlScanner = new Scanner(getHtml); StringBuffer htmlBuffer = new StringBuffer(); while(htmlScanner.hasNextLine()) { htmlBuffer.append(htmlScanner.nextLine()); } browserMap = new Browser(compositeTabItemMap, SWT.NONE); browserMap.setText(htmlBuffer.toString()); but google maps dosen't load in Eclipse .. I created simply html file and did the same .. Tn that case it works in Eclipse but in runnable jar still the same situtation as with GoogleMap.htmlNorge
simply solution :) : java can't load html file from jar file because it must be decompressed to temp file in file sys. location, so I changed .html to .txt also I added \n in append method to correctly validate javascript code and it works very niceNorge
H
3

As you can see here:

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getResourceAsStream(java.lang.String)

getResourceAsStream() looks for the file in the same package as the class from which it is called. Thus it will look for a file named "com/whatever/more/images/search_folder.png" inside the JAR, which of course won't exist, because the contents of the "resources" directory are directly put in the root of the JAR file by the JAR exporter.

Use http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#getResourceAsStream(java.lang.String) instead.

The second part: when you load the HTML will never work. You try to find a File named "resources/GoogleMap.html", but that will look outside of the JAR, in the working directory of your java program process. You should again use the previous function to load the HTML:

http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#getResourceAsStream(java.lang.String)

Heathcote answered 21/12, 2012 at 12:44 Comment(1)
So I ended up trying this after seeing the above solution that seems to work fine for me. Not sure why this has to be so obscure for Runnable Jars. I placed the resource in my resources directory which I had added as part of the class path for Eclipse ClassLoader.getSystemClassLoader().getResourceAsStream("file.txt");Dwelt
M
3

I lost many hours on this same issue. If you created your runnable jar using the options in the "Export" functionality in Eclipse, it just won't work. At least it didn't for me. No matter what number of options I tried, nothing worked. When trying to read the resources, the resourceUrl would return null. Finally, I decided to create the runnable jar using Maven, and leave the Eclipse kind help aside. I needed to have the dependent jars in a separate lib folder. I created the runnable jar as explained in http://www.mkyong.com/maven/how-to-create-a-manifest-file-with-maven/ and the solution worked for me. Somehow, when Eclipse creates the runnable jar package, the resources cannot be read, even though they are present in the jar file. Hope this will help others.

Mogador answered 12/11, 2013 at 16:19 Comment(1)
I couldn't get it to work either. However, I did notice that copying the resources folder in the same folder of the runnable jar worked... Maybe this helps someone elseMultilateral
E
0

Since exporting into a runnable jar essentially creates one file, the file/image/resource in your resources folder can no longer be found with FileReader because the file location is now non-existent..

Changing from using FileReader fr = new FileReader(resource_file_path) to loading with an InputStream, InputStream is = getClass().getResourceAsStream(resource_file_path) and then using an InputStreamReader to actually use the resource in other locations. Hope this helps.

Extravagate answered 22/10, 2017 at 16:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.