2

I'm building my jar-file with maven, they include all dependencies, so i can run the jars via

java -jar

Inside the jar I have a config.json which is the the app-configuration. I verified that config.json is really inside the jar:

/> jar tf cloudimport-0.1-jar-with-dependencies.jar | grep config.json
config.json

But when I run the application it won't find the config.json:

ClassLoader classLoader = getClass().getClassLoader();
System.out.println(classLoader.getResource("config.json"));
File configFile =  new File(classLoader.getResource(fileName).getFile());
(Exception thrown here ->) FileReader fileReader = new FileReader(configFile);
BufferedReader br = new BufferedReader(fileReader);

produces:

java -jar cloudimport-0.1-jar-with-dependencies.jar
jar:file:/home/ubuntu/cloudimport-0.1-jar-with-dependencies.jar!/config.json
java.io.FileNotFoundException: file:/home/ubuntu/cloudimport-0.1-jar-with-dependencies.jar!/config.json (No such file or directory)

The Class that runs the above code is located in the jar at:

com.test.cloudsync.config.AppConfig.class

If I run the app from intelliJ in windows, it works properly, but execution from intelliJ means that the Main Class is executed not the jar.

I have already searched for this but answers like: What is the difference between Class.getResource() and ClassLoader.getResource()?

didn't help...

jar-contents

// EDIT The suggestion was that the Excpetion wasn't throwed by the ClassLoader - this is true. I removed some stuff so I could limit the scope, now it seems like the problem is that I try to open a FileINputStream but this is not possible I guess if the file is withing a jar?

The Full Stack Trace:

/> java -jar java_cloudsync/com/tsg/cloudimport/cloudimport/0.1/cloudimport-0.1-jar-with-dependencies.jar   
jar:file:/home/ubuntu/java_cloudsync/com/tsg/cloudimport/cloudimport/0.1/cloudimport-0.1-jar-with-dependencies.jar!/config.json
    java.io.FileNotFoundException: file:/home/ubuntu/java_cloudsync/com/tsg/cloudimport/cloudimport/0.1/cloudimport-0.1-jar-with-dependencies.jar!/config.json (No such file or directory)
            at java.io.FileInputStream.open0(Native Method)
            at java.io.FileInputStream.open(FileInputStream.java:195)
            at java.io.FileInputStream.<init>(FileInputStream.java:138)
            at java.io.FileReader.<init>(FileReader.java:72)
            at com.tsg.cloudsync.config.AppConfig.readConfigFile(AppConfig.java:33)
            at com.tsg.cloudsync.config.AppConfig.<init>(AppConfig.java:23)
            at com.tsg.cloudsync.awsutils.SQSSocket.<init>(SQSSocket.java:34)
            at com.tsg.cloudsync.awsutils.SQSSocket.<clinit>(SQSSocket.java:19)
            at com.tsg.cloudsync.NewFileWatchDog.main(NewFileWatchDog.java:24)
    Exception in thread "main" java.lang.ExceptionInInitializerError
            at com.tsg.cloudsync.NewFileWatchDog.main(NewFileWatchDog.java:24)
    Caused by: java.lang.NullPointerException
            at com.tsg.cloudsync.config.AppConfig.getAWSCredentials(AppConfig.java:50)
            at com.tsg.cloudsync.awsutils.SQSSocket.<init>(SQSSocket.java:35)
            at com.tsg.cloudsync.awsutils.SQSSocket.<clinit>(SQSSocket.java:19)
            ... 1 more
Community
  • 1
  • 1
G-M
  • 296
  • 1
  • 6
  • 15
  • 1
    try with `getResource("/config.json")` -> note the `/` before the resource name – Svetlin Zarev Oct 13 '16 at 09:41
  • Could you post the code which failed with `java.io.FileNotFoundException`. Based on the line `jar:file:/home/ubuntu/cloudimport-0.1-jar-with-dependencies.jar!/config.json` printed by `System.out.println(classLoader.getResource("config.json"))`you have proofed yourself that the file can be found. – SubOptimal Oct 13 '16 at 10:06
  • I removed some stuff and could limit the Exception, see my Edit for details. It seems like the input stream can't be read, because the file is inside the jar I guess? – G-M Oct 13 '16 at 12:33

2 Answers2

1

So it turned out that I was trying to define a

ClassLoader classLoader = getClass().getClassLoader();
File f = new File(classLoader.getResource(fileName).getFile())
FileReader fileReader = new FileReader(configFile);
BufferedReader br = new BufferedReader(fileReader);

Which is not possible, since the jar itself is a File. So instead to get the Contents of a file do:

ClassLoader classLoader = getClass().getClassLoader();
InputStream in = classLoader.getResourceAsStream(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(in));

Also refer to here: Reading a resource file from within jar

Notice the difference getResourceAsStream(fileName) and getResource(fileName).getFile()

Thanks for pointing me to the right direction!

Community
  • 1
  • 1
G-M
  • 296
  • 1
  • 6
  • 15
0

Assume following simple structure

bin/
src/AppConfig.java
src/config.json
src/manifest.mf

AppConfig.java

package com.test.cloudsync;
public class AppConfig {
    void check() {
        ClassLoader classLoader = getClass().getClassLoader();
        System.out.println(classLoader.getResource("config.json"));
    }
    public static void main(String[] args) {
        new AppConfig().check();
    }
}

manifest.mf

Main-Class: com.test.cloudsync.AppConfig

compile and build the Jar file

javac -d bin/ src/*.java
cp src/config.json bin/config.json
jar cfm test.jar src/manifest.mf -C bin/ .

run the Jar

java -jar test.jar

output

jar:file:/tmp/foobar/test.jar!/config.json

This demonstrates that the exception is not raised by the line ClassLoader classLoader = getClass().getClassLoader()

SubOptimal
  • 22,518
  • 3
  • 53
  • 69
  • Thanks for your answer, it seems like the problems is that I try to open a FileInputStream based on that path, which is appearently not possible because the file is inside a Jar. – G-M Oct 13 '16 at 12:34
  • That's because the URL is using the `jar` protocol. The simplest way to get a input stream from `URL` is just to call `URL.openConnection().getInputStream()` – Svetlin Zarev Oct 13 '16 at 12:49
  • What is the difference between your method and getResourceAsStream(fileName); Thanks – G-M Oct 13 '16 at 12:55