I have a class in a Tomcat app which has a static initializer. An Error
is being thrown inside the static initializer.
The problem is that the error message shown by Tomcat does not include the "cause", i.e. the message and stack trace from that error are not shown.
I can reproduce the problem like this:
public class BadInitClass
{
static
{
if (System.currentTimeMillis() > 0)
throw new Error("I need to see this message");
}
public void doSomething()
{
System.out.println("functionality here");
}
}
Now, if I call this class from a unit test:
@Test
public void testStaticInit() throws Exception
{
new BadInitClass().doSomething();
}
Then the test prints out the stack trace and message:
java.lang.Error: I need to see this message
at mypackage.BadInitClass.<clinit>(BadInitClass.java:8)
at mypackage.BadInitClassTest.testStaticInit(UOneUtilitiesTest.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
However, if I add the same code to my Servlet, then Tomcat does not print the message, only the following:
exception
javax.servlet.ServletException: Servlet.init() for servlet MyServlet threw exception
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
java.lang.Thread.run(Thread.java:662)
root cause
java.lang.NoClassDefFoundError: Could not initialize class mypackage.BadInitClass
mypackage.[calling code here]
datcon.webmail.utils.DispatchedHttpServlet.init(DispatchedHttpServlet.java:77)
MyServlet.init(MyServlet.java:57)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
java.lang.Thread.run(Thread.java:662)
note The full stack trace of the root cause is available in the Apache Tomcat/6.0.37 logs.
I am running Tomcat 6.0.37.
Is this a bug in Tomcat? Is there any workaround?
I know that static initialisers are not generally a good idea, but I have some legacy code which uses them, and debugging these issues is very painful without the underlying error messages and stack traces.
I notice that the unit test does not have a NoClassDefFoundError
-- is the issue something to do with a custom ClassLoader used by tomcat?