Search code examples
jettyosgijetty-8

Getting ClassNotFoundException: org.eclipse.jetty.server.Server


I'm using the class "org.eclipse.jetty.server.Server" in XML file to intialize it with various parameters(Please note this is an OSGi environment). However my bundle which is using the class "org.eclipse.jetty.server.Server" is not starting and throwing the following exception:

java.lang.ClassNotFoundException: org.eclipse.jetty.server.Server
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at org.eclipse.core.runtime.internal.adaptor.ContextFinder.loadClass(ContextFinder.java:129)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at org.eclipse.jetty.util.Loader.loadClass(Loader.java:92)
        at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.nodeClass(XmlConfiguration.java:349)
        at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.configure(XmlConfiguration.java:327)

I've made sure that the jetty server bundle is up and running and also I've made sure that I've given proper version in the "Imported-Packages" section of my manifest file. Please help.


Solution

  • If you want to use Jetty in the way that

    • Jetty is initialized based on XML configuration
    • It is used within an OSGi environment

    I recommend that you should use jetty-osgi-boot bundle. You can find more information about its usage in the documentation of Jetty.

    In case you want to develop a custom solution based on jetty-xml, you should check how jetty-boot does it.

    Some tips:

    • The configuration is read from the XML file in the end of ServerInstanceWrapper.configure() function.
    • That is called from DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(...)
    • There you will find the trick that the Thread Context Classloader is overridden until the Server is configured from the XML.

      ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
      try
      {
          Thread.currentThread().setContextClassLoader(JettyBootstrapActivator.class.getClassLoader());
      
          ...
      
          Server server = ServerInstanceWrapper.configure(null, configURLs, properties);
      
          ...
      
          return server;
      }
      ...
      finally
      {
          Thread.currentThread().setContextClassLoader(contextCl);
      }
      

    Please note that the links and example is from Jetty 9.2.9 as the code is a bit nicer there, but you can find the same or similar logic in the jetty-osgi-boot of your Jetty version.

    It is not a good thing to play around with the Thread Context ClassLoader, but sometimes it is necessary, when code is called that use TCL. The best would be if the XMLConfiguration class of Jetty accepted a ClassLoader as a parameter.