0

I have a testing Ubuntu server running tomcat7 and oracle jdk 8, I am trying to load a few jar files that will be needed for a variety of future programs. Both web and jvm programs. I realized that there is a problem when I did a test run of a jar that will be running as a server background process, but when it runs I get the following error:

Exception in thread "main" java.lang.NoClassDefFoundError: edu/illinois/sql/sqlConnection
    at server.edu.illinois.xmlConverter.convertXML.run(Converter.java:27)
    at server.edu.illinois.xmlConverter.Converter.main(Converter.java:13)
Caused by: java.lang.ClassNotFoundException: edu.illinois.sql.sqlConnection
    at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 2 more

I have added my jars with my classes to /shared/lib and catalina.properties knows to look there and there are symbolic links in $JAVA_HOME/jre/lib. Does anyone have any advice as to why my custom classes from my jars on the server are not being loaded properly? Also the jar that I ran to generate the error runs great in eclipse.

This is a different question than ClassNotFoundException/NoClassDefFoundError in my Java web application because I believe my jars are in the correct locations and I am trying to figure out what I have done wrong that is causing these classes not to load.

Community
  • 1
  • 1
nfeuerhelm
  • 21
  • 5
  • Why do you not make a selfcontained WAR instead containing these classes too? – Thorbjørn Ravn Andersen Jul 09 '14 at 17:29
  • Because there are classes that will be needed by both .WARs and .JARs. A self contained .WAR would solve the problem for the web apps but not the stand alone .JARs. – nfeuerhelm Jul 09 '14 at 17:44
  • 2
    The jars go in the war too. That said, I highly recommend _NOT_ messing with jre/lib - you are basically making a custom JVM where things work differently from elsewhere, giving you problems like this. – Thorbjørn Ravn Andersen Jul 09 '14 at 17:54
  • I know jars that need to be loaded go in the war as well. I am saying that I have other non-webapps that will need to use classes contained in these jars. I am trying to get them into the class path and loaded for both tomcat and java – nfeuerhelm Jul 09 '14 at 18:01
  • 1
    Doing it this way is a _very_ bad idea. You will discover this when your software comes of age and you need to support multiple versions. Enclose a copy in each deployment. – Thorbjørn Ravn Andersen Jul 09 '14 at 19:30
  • Reopened as the question is about adding jars to the JRE installation to avoid including them in the individual deployments! – Thorbjørn Ravn Andersen Jul 09 '14 at 20:00
  • Thanks for reopening @ThorbjørnRavnAndersen. I suppose I still need to work on my question asking. I am not concerned about supporting multiple versions as this is all one-off software to admin a hardware install at a institutional level. – nfeuerhelm Jul 10 '14 at 00:18

2 Answers2

0

Do not modify your JVM installation, it's not worth it. There are well-known ways to bundle JARs with your program:

  • for standalone programs as executable JARs, see this answer
  • for web applications, place them in WEB-INF/lib. Maven will even do it for you.

Yes, the same JAR will be duplicated. No, it really is OK. Yes, there is some overhead. Yes, the benefits vs a modified JVM are really worth it (cue myself wasting ~5 hours trying to find why suddenly my development machine did not find my classes after java got auto-updated...).

Community
  • 1
  • 1
Tassos Bassoukos
  • 16,017
  • 2
  • 36
  • 40
0

I might not have explained this well enough I still new to java and am self taught. I did however figure out my answer. Tassos and Thorbjørn make good point that I will keep in mind, particularly not messing with /jre/lib or /jre/lib/etx. However since I do not want to bundle the external jars in with the runnable jar, I have found my solution that will work for me as I am both running the server and creating the jars.

I am going to add create a custom MANIFEST.MF which will contain a Class-path: statement pointing to the directory where I am putting the common jars.

For example:

Manifest-Version: 1.0
Main-Class: server.edu.illinois.Main
Class-Path: /shared/lib/guava-17.0.jar /shared/lib/jcifs-1.3.17.jar /shared/lib/mysql-connector-java-3.1.14-bin.jar

This way I can include the external jars I need only once and update anything I need to in Eclipse when I update the manifest's jar. I can still leave tomcat to pickup those jars in that library when it does the common classload. When I get back to my dev machine tomorrow I am going to pull the symbolic links out of /jre/lib/ext.

Overall, my jars were not being loaded properly to begin with because they were not actually in the path that the class loader was looking at. To solve this problem without adding overhead and since these will be one off programs, adding directories to the common class loader for catalina and the jar paths to the manifest of my stand alone programs.

nfeuerhelm
  • 21
  • 5