jeev
jeev

Reputation: 193

gradle generate jar has resource file but running jar causes Invalid resource

I have a rest server written in java and using gradle as it build system.

In one my class I am using the file src/main/resources/myresource.config as below

public static void main(String[] args) {
  String resourcePath = Myapplication.class.getClassLoader().getResource("myresource.config").toURI().getPath();
LOGGER.info(String.format("Loading data from config %s", resourcePath));
BufferedReader br = new BufferedReader(new FileReader(resourcePath));
}

The program works fine when running the class directly from command line or ide.

I am build a jar for my application as below

jar {
    manifest {
        attributes 'Main-Class': 'com.example.Myapplication',
                'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' ')
    }

    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
    exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
}

The jar gets build successfully inside build/libs when I try running the jar java -jar myapplication.jar I fails to find the myresource.config resource.

I unzipped the build jar and found that the myresource.config file is present but the jar fails to run.

Things I have tried so far

ClassLoader.getSystemClassLoader().getResource("myresource.config");
Thread.currentThread().getContextClassLoader().getResource("myresource.config")

Can anyone point out what I am doing incorrect?

Stacktrace

INFO: Loading data from config null
Invalid resource: myresource.config
java.lang.NullPointerException
    at java.io.FileInputStream.<init>(FileInputStream.java:130)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at java.io.FileReader.<init>(FileReader.java:58)
    at com.example.Myapplication.<main>(Myapplication.java:26)

Upvotes: 1

Views: 337

Answers (2)

dpr
dpr

Reputation: 10972

The problem is that, when running the application from the IDE myresource.config is read directly from the file system. That is you get a regular file URL:

URL configUrl = Myapplication.class.getClassLoader().getResource("myresource.config");
// returns "file:/C:/path/to/project/bin/main/myresource.config"

But when you execute the application from the jar file, the config file is read from the jar and you get a jar based URL:

URL configUrl = Myapplication.class.getClassLoader().getResource("myresource.config");
// returns "jar:file:/C:/path/to/project/build/libs/myapplication.jar!/myresource.config"

This second jar-based URL cannot be converted to a filesystem path and that is why you get null.

To get the config in both scenarios, you should do something like this

try (final InputStream configInputStream = Myapplication.class.getClassLoader().getResourceAsStream("myresource.config");
     final BufferedReader br = new BufferedReader(new InputStreamReader(configInputStream));) {
   // do something with br
}

Upvotes: 2

Alexandr Ivanov
Alexandr Ivanov

Reputation: 399

I think you must use getResourceAsStream instead.
Myapplication.class.getResourceAsStream("myresource.config")

Upvotes: 0

Related Questions