gradle run executes; compiled JAR crashes with ClassNotFoundException

Viewed 312

Why does the client JAR crash, java.lang.NoClassDefFoundError, caused by ClassNotFoundException, yet run from gradle works fine? There's a problem with how the client uses the library JAR?

thufir@mordor:~/NetBeansProjects/hello_client$ 
thufir@mordor:~/NetBeansProjects/hello_client$ gradle clean build
Starting a new Gradle Daemon for this build (subsequent builds will be faster).
Download https://jitpack.io/com/github/THUFIR/hello_api/dev/hello_api-dev.pom
Download https://repo1.maven.org/maven2/org/codehaus/groovy/groovy-all/2.4.1/groovy-all-2.4.1.pom
Download https://jitpack.io/com/github/THUFIR/hello_api/dev/hello_api-dev.jar
Download https://repo1.maven.org/maven2/org/codehaus/groovy/groovy-all/2.4.1/groovy-all-2.4.1.jar
Changed strategy of configuration ':compile' after it has been resolved. This behaviour has been deprecated and is scheduled to be removed in Gradle 3.0
:clean
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:startScripts
:distTar
:distZip
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 1 mins 11.959 secs
thufir@mordor:~/NetBeansProjects/hello_client$ 
thufir@mordor:~/NetBeansProjects/hello_client$ java -jar build/libs/hello_client.jar 
Exception in thread "main" java.lang.NoClassDefFoundError: net/bounceme/mordor/hello/library/HelloLibrary
    at net.bounceme.mordor.hello.client.Client.runLibrary(Client.java:13)
    at net.bounceme.mordor.hello.client.Client.main(Client.java:9)
Caused by: java.lang.ClassNotFoundException: net.bounceme.mordor.hello.library.HelloLibrary
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 2 more
thufir@mordor:~/NetBeansProjects/hello_client$ 
thufir@mordor:~/NetBeansProjects/hello_client$ gradle clean run
Changed strategy of configuration ':compile' after it has been resolved. This behaviour has been deprecated and is scheduled to be removed in Gradle 3.0
:clean
:compileJava
:processResources UP-TO-DATE
:classes
:run
hello [fred]

BUILD SUCCESSFUL

Total time: 4.66 secs
thufir@mordor:~/NetBeansProjects/hello_client$ 

As it should, above output is "hello [fred]", which is fine. The hello world client code:

package net.bounceme.mordor.hello.client;

import static java.lang.System.out;
import net.bounceme.mordor.hello.library.HelloLibrary;

public class Client {

    public static void main(String[] args) {
        new Client().runLibrary();
    }

    private void runLibrary() {
        HelloLibrary library = new HelloLibrary();
        out.println(library.hello("fred"));
    }

}

Netbeans complains about the import statement for net.bounceme.mordor.hello.library.HelloLibrary, which would seem to be correct:

thufir@mordor:~$ 
thufir@mordor:~$ cp .gradle/caches/modules-2/files-2.1/com.github.THUFIR/hello_api/dev/fa670823cfe9548b87c75f224a48a1089eab0b35/hello_api-dev.jar jar
thufir@mordor:~$ 
thufir@mordor:~$ cd jar
thufir@mordor:~/jar$ 
thufir@mordor:~/jar$ jar -xf hello_api-dev.jar 
thufir@mordor:~/jar$ 
thufir@mordor:~/jar$ cat META-INF/MANIFEST.MF 
Manifest-Version: 1.0

thufir@mordor:~/jar$           
thufir@mordor:~/jar$ ll net/bounceme/mordor/hello/library/HelloLibrary.class 
-rw-rw-r-- 1 thufir thufir 728 Mar 11  2016 net/bounceme/mordor/hello/library/HelloLibrary.class
thufir@mordor:~/jar$ 

Here is the client JAR:

thufir@mordor:~/NetBeansProjects/hello_client$              
thufir@mordor:~/NetBeansProjects/hello_client$ cd build/libs/
thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ 
thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ jar -xf hello_client.jar 
thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ 
thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ cat META-INF/MANIFEST.MF 
Manifest-Version: 1.0
Main-Class: net.bounceme.mordor.hello.client.Client
Class-Path: hello_api-dev.jar groovy-all-2.4.1.jar

thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ 
thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ ll net/bounceme/mordor/hello/client/Client.class 
-rw-rw-r-- 1 thufir thufir 912 Mar 11 02:28 net/bounceme/mordor/hello/client/Client.class
thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ 

and it seems, to me, that the classpath includes hello_api-dev.jar correctly.

This seems notable:

Where possible, avoid using dependencies in the manner of compile fileTree(dir: 'lib', include: ['*.jar']). Managed dependencies based on a repository such as Maven or JCenter are much easier to work with consistently than dependencies in a random directory. If these are internal libraries that you don't want to publish to an open-source artifact repository, then it may be worth setting up a local Nexus instance or similar.

https://stackoverflow.com/a/35304025/262852

However, I'm not quite sure whether that's the problem, as I seem to be using the correct JAR, with the correct packaging, from jitpack.

I even added the libary to a libs folder for the client:

thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ 
thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ jar -vft hello_client.jar 
     0 Fri Mar 11 02:50:28 PST 2016 META-INF/
   135 Fri Mar 11 02:50:28 PST 2016 META-INF/MANIFEST.MF
     0 Fri Mar 11 02:50:28 PST 2016 net/
     0 Fri Mar 11 02:50:28 PST 2016 net/bounceme/
     0 Fri Mar 11 02:50:28 PST 2016 net/bounceme/mordor/
     0 Fri Mar 11 02:50:28 PST 2016 net/bounceme/mordor/hello/
     0 Fri Mar 11 02:50:28 PST 2016 net/bounceme/mordor/hello/client/
   927 Fri Mar 11 02:50:28 PST 2016 net/bounceme/mordor/hello/client/HelloClient.class
thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ 
thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ jar -vft libs/hello_api-dev.jar 
     0 Fri Mar 11 01:59:38 PST 2016 META-INF/
    25 Fri Mar 11 01:59:38 PST 2016 META-INF/MANIFEST.MF
     0 Fri Mar 11 01:59:38 PST 2016 net/
     0 Fri Mar 11 01:59:38 PST 2016 net/bounceme/
     0 Fri Mar 11 01:59:38 PST 2016 net/bounceme/mordor/
     0 Fri Mar 11 01:59:38 PST 2016 net/bounceme/mordor/hello/
     0 Fri Mar 11 01:59:38 PST 2016 net/bounceme/mordor/hello/library/
   728 Fri Mar 11 01:59:38 PST 2016 net/bounceme/mordor/hello/library/HelloLibrary.class
thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ 
thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ java -jar hello_client.jar 
Exception in thread "main" java.lang.NoClassDefFoundError: net/bounceme/mordor/hello/library/HelloLibrary
    at net.bounceme.mordor.hello.client.HelloClient.runLibrary(HelloClient.java:13)
    at net.bounceme.mordor.hello.client.HelloClient.main(HelloClient.java:9)
Caused by: java.lang.ClassNotFoundException: net.bounceme.mordor.hello.library.HelloLibrary
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 2 more
thufir@mordor:~/NetBeansProjects/hello_client/build/libs$ 

which begs the question: why doesn't gradle copy the library over for the client?

1 Answers
Related