1

we are struggling here with a java.lang.NoClassDefFoundError that makes no sense.

The same WAR file runs perfectly in the server B, but throws a java.lang.NoClassDefFoundError on server A.

Configurations are:

Server A (throws Exception):

OS: 
    NAME="SLES"
    VERSION="12-SP4"
    VERSION_ID="12.4"
    PRETTY_NAME="SUSE Linux Enterprise Server 12 SP4"
Apache Tomcat 8.5.49
Oracle Java dk1.8.0_231

Server B (works perfectly):

OS:
    NAME="Ubuntu"
    VERSION="16.04.6 LTS (Xenial Xerus)"
    ID=ubuntu
    ID_LIKE=debian
    VERSION_ID="16.04"
    PRETTY_NAME="Ubuntu 16.04.6 LTS"
Apache Tomcat 8.5.37
Oracle Java jdk 1.8.0_201-b09

The exception is:

2020-01-27 15:57:27.103 [http-nio-8081-exec-10] ERROR o.g.w.errors.GrailsExceptionResolver - NoClassDefFoundError occurred when processing request: [GET] /server-0.1/cenario/getCenarioJson
Could not initialize class clojure.java.api.Clojure. Stacktrace follows:
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class clojure.java.api.Clojure
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:982)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        ...
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class clojure.java.api.Clojure
        at com.nitryx.brkmopt.util.ClojureHandler.invoke(ClojureHandler.java:176)
        at com.nitryx.brkmopt.util.ClojureHandler.invoke(ClojureHandler.java:173)
        at com.nitryx.brkmopt.CenarioService.$tt__getCenarioJson(CenarioService.groovy:35)
        ...        

The WAR file runs perfectly on server B but throws the exception on server A.

We inspected the ~/WEB-INF/lib/ folder under tomcat, and the necessary dependency (clojure-1.9.0.jar) is there and is consistent. On a desperate action, we have even tried to replace the jar file for a newer one manually, and it did not work.

From Why am I getting a NoClassDefFoundError in Java? :

java.lang.NoClassDefFoundError This exception indicates that the JVM looked in its internal class definition data structure for the definition of a class and did not find it. This is different than saying that it could not be loaded from the classpath. Usually this indicates that we previously attempted to load a class from the classpath, but it failed for some reason

Please advise!

Edit: Full stacktrace: (many thanks to clojurians @jumar @alexmiller @ghadi @seancorfield)

2020-02-05 16:00:02.342 [http-nio-8081-exec-10] ERROR o.g.w.errors.GrailsExceptionResolver - NoClassDefFoundError occurred when processing request: [GET] /server-0.1/cenario/getCenarioJson
Could not initialize class clojure.java.api.Clojure. Stacktrace follows:
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class clojure.java.api.Clojure
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:982)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:239)
        at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:215)
        at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
        at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:239)
        at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:215)
        at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
        at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
        at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:130)
        at org.springframework.boot.web.support.ErrorPageFilter.access$000(ErrorPageFilter.java:66)
        at org.springframework.boot.web.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:105)
        at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:123)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class clojure.java.api.Clojure
        at com.nitryx.brkmopt.util.ClojureHandler.invoke(ClojureHandler.java:176)
        at com.nitryx.brkmopt.util.ClojureHandler.invoke(ClojureHandler.java:173)
        at com.nitryx.brkmopt.CenarioService.$tt__getCenarioJson(CenarioService.groovy:35)
        at grails.melody.plugin.MelodyInterceptorEnhancer$_enhance_closure1$_closure2.doCall(MelodyInterceptorEnhancer.groovy:77)
        at grails.gorm.transactions.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:94)
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
        at grails.gorm.transactions.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:91)
        at grails.melody.plugin.MelodyInterceptorEnhancer$_enhance_closure1$_closure2.doCall(MelodyInterceptorEnhancer.groovy:77)
        at com.nitryx.brkmopt.CenarioController.getCenarioJson(CenarioController.groovy:20)
        at org.grails.core.DefaultGrailsControllerClass$MethodHandleInvoker.invoke(DefaultGrailsControllerClass.java:223)
        at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
        at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
        ... 18 common frames omitted
Chocksmith
  • 1,188
  • 2
  • 12
  • 40
  • The files tomcat picks up and provides to all webapps is configured - so a simple copy may or may not be enough. Second, since clojure 1.9 the clojure.jar also depends on the spec-alpha and the core-specs-alpha jars. If that is the case, your stracktrace should be telling you, but i mention it just in case. In the long run you are way better off adding the clojure deps just to your grails project? – cfrick Jan 27 '20 at 20:06
  • Tks for the insights! We added all Clojure dependencies on our grails project. It runs beautifully in one server (B). Has been running for months. The new server (A) throws the exception when running the save WAR file. – Chocksmith Jan 27 '20 at 20:11
  • 1
    Other things to explore: check the CLASSPATH environment variable in both servers. It's possible that the WAR includes an invalid JAR and the Clojure classes are being found elsewhere (Tomcat's own JARs or extra JARs in the `lib` folder of the JDK itself). Also, try to reproduce in a NEW Ubuntu server to see if the difference can be attributed to differences in the setup of the operating systems or the setup of Tomcat in general. – Denis Fuenzalida Jan 28 '20 at 02:03
  • 1
    We had a _sort of_ similar issue but with a 3rd party library throwing NoSuchMethodError on a server while working happily on local machines. It turned out it was a _depency conflict_ - that is multiple versions of the same library were included on the classpath but different one was picked when running on the remote server compared to when running locally. Check your classpath for conflicts, possibly with `lein deps :tree`. – Juraj Martinka Jan 28 '20 at 06:36
  • Good call! We will check it ASAP! And will let you know. – Chocksmith Jan 28 '20 at 10:59

1 Answers1

1

It looks like Tomcat 8.5.50 contains a bunch of regression fixes in Catalina with resource loading which may be affecting the loading of Clojure source files. Suggest either downgrading to same as the working one or upgrading to 8.5.50.

https://tomcat.apache.org/tomcat-8.5-doc/changelog.html

Alex Miller
  • 69,183
  • 25
  • 122
  • 167