Class loading in a web container is slightly more complex than a normal Java application. The normal configuration is that each web context (web application or WAR file) has its own classloader, which has the system classloader as its parent. Such a classloader hierarchy is normal in Java, however the servlet specification complicates the hierarchy because it requires the following:
java.lang.String are excluded from the webapp priority, and you may
not replace them with classes in WEB-INF/lib or WEB-INF/ classes. Unfortunately
the specification does not clearly state what classes are System classes, and it is unclear if
all javax classes should be treated as System classes.Jetty provides configuration options to control the three webapp class loading issues identified above.
You can configure webapp classloading by several methods on the WebAppContext. You can call these methods
directly if you are working with the Jetty API, or you can inject methods from a context XML file if you are using
the Context Provider (Using the Context Provider). You CANNOT set these methods from a
jetty-web.xml file, as it executes after the classloader configuration is set.
The method org.eclipse.jetty.webapp.WebAppContext.setParentLoaderPriority(boolean) allows control over the priority given to webapp classes over system classes. If you set it to false (the default), Jetty uses standard webapp classloading priority. However, if in this mode some classes that are dependencies of other classes are loaded from the parent classloader (due to settings of system classes below), ambiguities might arise as both the webapp and system classloader versions can end up being loaded.
If set to true, Jetty uses normal JavaSE classloading priority, and gives priority to the parent/system classloader. This avoids the issues of multiple versions of a class within a webapp, but the version the parent/system loader provides must be the right version for all webapps you configure in this way.
You can call the methods org.eclipse.jetty.webapp.WebAppContext.setSystemClasses(String Array) or org.eclipse.jetty.webapp.WebAppContext.addSystemClass(String) to allow fine control over which classes are considered System classes.
The default system classes are:
Table 24.1.
| System Classes | |
|---|---|
| java. | Java SE classes (per servlet spec v2.5 / SRV.9.7.2). |
| javax. | Java SE classes (per servlet spec v2.5 / SRV.9.7.2). |
| org.xml. | Needed by javax.xml. |
| org.w3c. | Needed by javax.xml. |
| org.apache.commons.logging. | Special case. |
| org.eclipse.jetty.continuation. | Webapp can see and not change continuation classes. |
| org.eclipse.jetty.jndi. | Webapp can see and not change naming classes. |
| org.eclipse.jetty.plus.jaas. | Webapp can see and not change JAAS classes. |
| org.eclipse.jetty.websocket. | WebSocket is a Jetty extension. |
| org.eclipse.jetty.servlet.DefaultServlet | Webapp can see and not change default servlet. |
Absolute classname can be passed, names ending with . are treated as packages names, and names starting with - are treated as negative matches and must be listed before any enclosing packages.
You can call the methods org.eclipse.jetty.webapp.WebAppContext.setServerClasses(String Array) or org.eclipse.jetty.webapp.WebAppContext.addServerClass(String) to allow fine control over which classes are considered Server classes.
The default server classes are:
Table 24.2.
| Server Classes | |
|---|---|
| -org.eclipse.jetty.continuation. | Don't hide continuation classes. |
| -org.eclipse.jetty.jndi. | Don't hide naming classes. |
| -org.eclipse.jetty.plus.jaas. | Don't hide jaas classes. |
| -org.eclipse.jetty.websocket. | Don't hide websocket extension. |
| -org.eclipse.jetty.servlet.DefaultServlet | Don't hide default servlet. |
| org.eclipse.jetty. | Hide all other Jetty classes. |
You can add extra classpaths to Jetty in several ways.
If you are using Start Features, at startup the jetty runtime automatically
loads option Jars from the top level $jetty.home/lib directory. The default settings
include:
$jetty.home/lib/ext to the system classpath. You can place
additional Jars here.$jetty.home/resources to the classpath (may contain classes
or other resources).You can add an additional classpath to a context classloader by calling org.eclipse.jetty.webapp.WebAppContext.setExtraClasspath(String) with a comma-separated list of paths. You can do so directly to the API via a context XML file such as the following:
<Configure class="org.eclipse.jetty.webapp.WebAppContext"> ... <Set name="extraClasspath>../my/classes,../my/jars/special.jar,../my/jars/other.jar> </Set> ...
If none of the alternatives already described meet your needs, you can always provide a custom classloader for your webapp. We recommend, but do not require, that your custom loader subclasses WebAppClassLoader. You configure the classloader for the webapp like so:
MyCleverClassLoader myCleverClassLoader = new MyCleverClassLoader();
...
WebAppContext webapp = new WebAppContext();
...
webapp.setClassLoader(myCleverClassLoader);
You can also accomplish this in a context xml file.
If you start a Jetty server using a custom class loader–consider the Jetty classes not being available to the system class loader, only your custom class loader–you may run into class loading issues when the WebAppClassLoader kicks in. By default the WebAppClassLoader uses the system class loader as its parent, hence the problem. This is easy to fix, like so:
context.setClassLoader(new WebAppClassLoader(this.getClass().getClassLoader(), context));
or
context.setClassLoader(new WebAppClassLoader(new MyCustomClassLoader(), context));