0

I'm having the following problem. I have a Java EE application (which I didn't develop) and when I try to run it I'm getting a NoClassDefFoundError while executing a specific functionality.

[30/12/14 11:02:40:026 CET] 00000060 ServletWrappe E com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0068E: Uncaught exception created in one of the service methods of the servlet HttpCrisServiceServlet2 in application cris-ear. Exception created : java.lang.NoClassDefFoundError: org.slf4j.MDC (initialization failure)
    at java.lang.J9VMInternals.initialize(J9VMInternals.java:141)
    at com.foo.bar.castor.http.CastorServlet.putMDCCorrelationInfo(CastorServlet.java:214)
    at com.foo.bar.castor.http.CastorServlet.service(CastorServlet.java:126)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1661)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1602)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:149)
    at com.foo.baz.server.Log4jTimingServletFilter.doFilter(Log4jTimingServletFilter.java:50)
    at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:125)
    at be.bene.common.castor.http.CompressionFilter.doFilter(CompressionFilter.java:100)
    at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:125)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:80)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:908)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:939)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:507)
    at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:181)
    at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3954)
    at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:276)
    at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:945)
    at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1592)
    at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:191)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:453)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:515)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:306)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:277)
    at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
    at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
    at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:175)
    at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
    at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
    at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
    at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
    at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
    at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1660)

The compiler can't find the class org.slf4j.MDC at runtime. Now I wanted to check if the class is on my classpath. I used two methods to check this:

First method and output:

System.out.println(loader.getResource(MDC.class.getName().replace('.', '/') + ".class"));
00000025 SystemOut     O bundleresource://352/org/slf4j/MDC.class

Second method and output:

try {
        Class.forName("org.slf4j.MDC", false, loader);
        System.out.println("org.slf4j.MDC does exist on the classpath (called from Log4jTiminingServletFilter)");
    } catch(ClassNotFoundException e) {
             System.out.println("org.slf4j.MDC does not exist on the classpath (called from Log4jTiminingServletFilter)");
    }

which gave me:

00000028 SystemOut O org.slf4j.MDC does exist on the classpath (called from Log4jTiminingServletFilter)

So I assume the class is on my classpath...

But as the stacktrace tells us the problem is:

at com.foo.bar.castor.http.CastorServlet.putMDCCorrelationInfo(CastorServlet.java:214)

Now this code is 'in-house' developed, and I have (read) access to it, but I can't change it. When I check line 214, MDC is indeed called:

MDC.put(MDC_KEY_MESSAGE_UUID, CorrelationHeaderContext.getCorrelationInfo().getMessageUUID());

Now I was wondering, how can I check that org.slf4j.MDC is also provided for the CastorServlet, and if not, how can I provide it?

Community
  • 1
  • 1
Tom Jonckheere
  • 1,630
  • 3
  • 20
  • 37

3 Answers3

0

This is a clue: bundleresource://352

It means that somewhere, there is OSGi involved. OSGi is great for certain problems, but it doesn't mix well with Java EE since Java EE specifies exactly how a web application discovers classes and this approach isn't compatible to OSGi's design with bundles and bundle classpaths.

The fix should be to put slf4j-api.jar to WEB-INF/lib/ in your WAR. If you deploy this war, then your application (and all JSPs in it) should be able to access the classes in the JAR.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • I added the slf4j-api.jar to WEB-INF/lib/ as you suggested. But I'm still getting the same error. The application is still referring to bundleresource://352/org/slf4j/MDC.class. Any other suggestions? – Tom Jonckheere Dec 30 '14 at 13:34
  • How do you get `loader`? – Aaron Digulla Dec 30 '14 at 13:36
  • ClassLoader loader = Log4jTimingServletFilter.class.getClassLoader(); – Tom Jonckheere Dec 30 '14 at 13:36
  • That means this class has been loaded by WebSphere and not by your application. That shouldn't happen. Please check that you have all logging JARs (and all the JARs which they need) in your `WEB-INF/lib/` – Aaron Digulla Dec 30 '14 at 13:39
0

If you added slf4j-api.jar to WEB-INF/lib/, then you have to change class loader to parent last, So the classes from your application are loaded before classes from WebSphere.

Gas
  • 17,601
  • 4
  • 46
  • 93
0

I just had the same problem and this is how I resolved it.

Websphere has a version of slf4j-api-1.5.6.jar in the following folders and they are probably older than the one you are using.

base_v7\feature_packs\aries\osgiappbundles\com.ibm.ws.osgi.applications base_v7\feature_packs\aries\osgiappbundles\com.ibm.ws.osgi.applications\aries

Either make sure your newer jar gets loaded or replace the slf4j-api-1.5.6.jar with the newer version.