java.nio.file.NoSuchFileException : Uber Jar not able to locate src/main/resources folder files

1.8k Views Asked by At

I am building uber jar using gradle build and the plugin I have used is https://github.com/johnrengelman/shadow

I have a json file in my src/main/resources folder which i am using in the code in below way

   public Repository<Product> initializeData() {
        ClassLoader classLoader = getClass().getClassLoader();
        File file = new File(classLoader.getResource("product.json").getFile());
        System.out.println(file.getAbsolutePath());
        Repository<Product> productRepository = new ProductRepository();
        return productRepository;
    }

When I am running uber Jar, facing below issue

$$ java -cp libs/checkout-service-1.0-SNAPSHOT.jar com.noths.runner.Runner
java.nio.file.NoSuchFileException: /home/gradle/checkout-service/file:/home/gradle/checkout-service/libs/checkout-service-1.0-SNAPSHOT.jar!/product.json
        at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)
        at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
        at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
        at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:219)
        at java.base/java.nio.file.Files.newByteChannel(Files.java:371)
        at java.base/java.nio.file.Files.newByteChannel(Files.java:422)
        at java.base/java.nio.file.Files.readAllBytes(Files.java:3206)
        at java.base/java.nio.file.Files.readString(Files.java:3284)
        at java.base/java.nio.file.Files.readString(Files.java:3243)
        at com.noths.runner.Utils.initializeData(Utils.java:21)
        at com.noths.runner.Runner.main(Runner.java:21)
Exception in thread "main" java.lang.NullPointerException
        at com.noths.promotions.ProductPromotion.apply(ProductPromotion.java:26)
        at com.noths.promotions.DefaultPromotionsRunner.setPromotionsChain(DefaultPromotionsRunner.java:21)
        at com.noths.checkout.CheckoutServiceImpl.checkout(CheckoutServiceImpl.java:27)
        at com.noths.runner.Runner.main(Runner.java:25)

My build.gradle looks like this

// Shadow Plugin https://github.com/johnrengelman/shadow
plugins {
    id "com.github.johnrengelman.shadow" version "6.0.0"
    id 'java'
}

group 'com'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'

    compileOnly 'org.projectlombok:lombok:1.18.20'
    annotationProcessor 'org.projectlombok:lombok:1.18.20'

    testCompileOnly 'org.projectlombok:lombok:1.18.20'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'

    implementation 'com.google.code.gson:gson:2.8.8'

}

test {
    useJUnitPlatform()
}
1

There are 1 best solutions below

2
On

You cannot access the classpath via File unless you have classes in the filesystem. As soon as the files are inside a jar the access via File must fail.

So what you should do is a classloader.getResource(...) or a getClass().getResource(...). If they return null, the string you passed did not match to something on the classpath and you need to work out if the string or the jar file need to be fixed. If you get some resource then directly open the stream and read the data.

See also https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Class.html#getResource(java.lang.String) https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URL.html#openStream()

I hesitate to use getClass().getResourceAsStream(...) since you save one function call but cannot give a good error message in case the resource does not exist.