Home > Back-end >  Inclusion of slf4j in classpath not being picked up when program is run
Inclusion of slf4j in classpath not being picked up when program is run

Time:09-17

I have been unsuccessfully trying to include slf4j in a project. I've added slf4j-api-1.7.32.jar and slf4j-jdk14-1.7.32.jar into the classpath but no matter what I've tried I end up with a java.lang.ClassNotFoundException: org.slf4j.LoggerFactory.

The initial part of the error is

Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at com.google.gwt.dev.shell.jetty.JettyLauncher$WebAppContextWithReload$WebAppClassLoaderExtension.findClass(JettyLauncher.java:354)
    at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:366)
    at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337)
    ...

(happy to include more if it would be helpful but the compiler cuts it off at that point)

The project is in Eclipse and I've tried

  • putting the libraries at the beginning of the class path
  • putting them at the end
  • turning Eclipse off and on
  • rebuilding the project
  • using different versions

Nothing seems to work.

However, oddly, with the exact same collection of libraries it works fine in JUnit tests I've written.

This morning a coworker found that adding the pair of slf4j libraries to war/WEB-INF/lib got things working, but this isn't a workable long term solution.

I'm hoping someone out there has some bright ideas!

Edit: Made some more progress. From here needed to add

<Set name="systemClasses">
    <Array type="java.lang.String">
        <!-- we from jetty WebAppContext source code ...-->
        <Item>java.</Item>
        <Item>javax.servlet.</Item>
        <Item>javax.xml.</Item>
        <Item>org.mortbay.</Item>
        <Item>org.xml.</Item>
        <Item>org.w3c.</Item>
        <Item>org.apache.commons.logging.</Item>
        <Item>org.apache.log4j.</Item>
        <!-- and ... added slf4j -->
        <Item>org.slf4j.</Item>
    </Array>
</Set>

to jetty-web.xml. Now need to find out what needs to change in deploy script.

CodePudding user response:

Solution:

Add the following 'systemClasses' set to the jetty-web.xml

<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
    ...
    <Set name="systemClasses">
         <Array type="java.lang.String">

             <!-- we copied these paths from jetty WebAppContext  source code ...-->
             <Item>java.</Item>
             <Item>javax.servlet.</Item>
             <Item>javax.xml.</Item>
             <Item>org.mortbay.</Item>
             <Item>org.xml.</Item>
             <Item>org.w3c.</Item>
             <Item>org.apache.commons.logging.</Item>
             <Item>org.apache.log4j.</Item>

             <!-- and ... added slf4j -->
             <Item>org.slf4j.</Item>

             <!-- we must promote slf4j to system classes, otherwise gwt
                  hosted mode will not allow loading them due to a policy
                  that don't allow server classes to be loaded from the
                  outside world (see gwt JettyLauncher source code). -->

         </Array>
    </Set>
</Configure>

As found in this message board from 2009: https://www.mail-archive.com/[email protected]/msg14754.html

How we found the solution:

While stepping through JettyLauncher.WebAppContextWithReload.WebAppClassLoaderExtension.findClass(String name) showed that on first load, most super.findClass(name) threw a ClassNotFoundException, then as they passed isServerPath they got down to using the systemClassLoader to load them from .jar files. Now the systemClassLoader has parent type URLClassLoader which has a field ucp (URLClassPath) that has a list (under path) of all the .jar files that it can load classes from. Taking a look in here, the slf4j jars indeed existed, but for some reason isServerPath was returning true. This is finally what led to finding the solution above.

  • Related