0

I have a small project which in my local IDE is running just fine, a screenshot will show the project structure:
enter image description here

I have highlighted the jewelcli jar because on that class i get the exception mentioned in the header. While running locally all goes fine, on a testing ubuntu server i get:
java -verbose -classpath "/correct/path/jarName.jar:lib/jars/*" correct.package.and.main.Class ***all bootstrapping class from RT.JAR*** java.lang.NoClassDefFoundError: uk/co/flamingpenguin/jewel/cli/ArgumentValidationException at correct.package.and.main.Class.main(Class.java:31) Caused by: java.lang.ClassNotFoundException: uk.co.flamingpenguin.jewel.cli.ArgumentValidationException at java.net.URLClassLoader$1.run(URLClassLoader.java:366) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:423) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:356) ... 1 more
I dont think this is actually related at all to that jewelcli jar in particular, because i double checked and its there: unzip -l jarname.jar | grep jewelcli 435937 11-20-11 01:22 lib/jars/jewelcli-0.7.6.jar

But it happens for that Jar because it is the very first jar that the program needs (after all the bootstrapping classes in rt.jar).
This is where i am basing my command line from But i also see:
Subdirectories are not searched recursively. For example, foo/* looks for JAR files only in foo, not in foo/bar, foo/baz, etc.
I thought that by specifying in the command line the jar file containing all the libraries, java would automaticaly, and recursively, scan all subdirectories, but it does not work:
java -verbose -classpath "/correct/path/jarName" correct.package.and.main.Class

Any tip on how can i get java to scan the whole jar i specify in the -classpath option?

JBoy
  • 5,398
  • 13
  • 61
  • 101
  • So if I understand correctly, you have a jar inside your jar that you want to add to your classpath? – Brian Mar 14 '18 at 13:39
  • Yes thats correct, – JBoy Mar 14 '18 at 13:45
  • Since you appear to be using Eclipse, I'd recommend looking at Eclipse's executable jar feature, as explained in the answer to [this question](https://stackoverflow.com/questions/11033603/how-to-create-a-jar-with-external-libraries-included-in-eclipse). If you're using (or plan to use) a more standardized build tool like Maven or Gradle, there are ways to do it with those too. – Brian Mar 14 '18 at 13:50

1 Answers1

0

I thought that by specifying in the command line the jar file containing all the libraries, java would automaticaly, and recursively, scan all subdirectories

It depends. The standard Java classloaders do not know how to load classes from JARs that embedded inside other JARs.

And that's what you appear to have done ... if I am reading your question correctly.

There are a few ways to address this:

  • Copy all of the dependent JARs to the server, put them into a directory, and add the directory to the classpath; e.g.

    java -classpath "/correct/path/jarName.jar:/correct/path/lib/*"  \
             correct.package.and.main.Class
    
  • Build an UberJAR or shaded JAR by unpacking the dependent JARs into a directory, adding your classes and producing a JAR from the tree. There are maven plugins for building such JAR files.

  • Use something like Spring Boot which uses a classloader that understands how to deal with JARs withing JARs.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216