Version: 9.4.5.v20170502 |

Jetty Classloading
Previous | Chapter 30. Architecture Home | Next

##### Contact the core Jetty developers at www.webtide.com

private support for your internal/customer projects ... custom extensions and distributions ... versioned snapshots for indefinite support ... scalability guidance for your apps and Ajax/Comet projects ... development services for sponsored feature development

## Jetty Classloading

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:

- Classes contained within WEB-INF/lib or WEB-INF/classes have priority over classes on the parent classloader. This is the opposite of the normal behaviour of a Java 2 classloader.
- System classes such as `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.
- Server implementation classes like Server should be hidden from the web application and should not be available in any classloader. Unfortunately the specification does not state what classes are Server classes, and it is unclear if common libraries like the Xerces parser should be treated as Implementation classes.

### Configuring Webapp Classloading

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 (???). You CANNOT set these methods from a `jetty-web.xml` file, as it executes after the classloader configuration is set.

#### Controlling Webapp Classloader Priority

The method org.eclipse.jett .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.

#### Configuring Webapp Classloader Caching

Introduced in Jetty 9.3.6, the CachingWebAppClassLoader can be used to cache `getResource(String)` results. For webapps that search for classes and resources regularly, this can increase speed and performance. This is an optional feature and it should be noted that it can conflict with several other libraries such as JSP, JSTL, JSF and CDI. As such, this feature must be manually enabled for each webapp you want to use it in.

Below is an example of implementing this feature using Jetty IoC XML format:

    <Configure id="mywebapp" class="org.eclipse.jetty.webapp.WebAppContext">

    ...

      <Set name="classLoader">
        <New class="org.eclipse.jetty.webapp.CachingWebAppClassLoader">
          <Arg><Ref refid="mywebapp"/></Arg>
        </New>
      </Set>

    ...
    </Configure>

#### Setting System Classes

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.

- A web application can see a System class.
- A WEB-INF class cannot replace a System class.

The default system classes are:

Table 30.1. Default System Classes

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.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.jaas.
Webapp can see and not change JAAS classes. | org.eclipse.jetty.websocket.
WebSocket is a Jetty extension. | org.eclipse.jetty.servlet.DefaultServlet

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.

#### Setting Server Classes

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.

- A web application cannot see a Server class.
- A WEB-INF class can replace a Server class.

The default server classes are:

Table 30.2. Default Server Classes

Server Classes | -org.eclipse.jetty.continuation.
--- | ---
Don’t hide continuation classes. | -org.eclipse.jetty.jndi.
Don’t hide naming classes. | -org.eclipse.jetty.jaas.
Don’t hide jaas classes. | -org.eclipse.jetty.servlets.
Don’t hide utility servlet classes if provided. | -org.eclipse.jetty.servlet.DefaultServlet
Don’t hide default servlet. | -org.eclipse.jetty.servlet.listener.
Don’t hide utility listeners | -org.eclipse.jetty.websocket.
Don’t hide websocket extension. | org.eclipse.jetty.

### Adding Extra Classpaths to Jetty

You can add extra classpaths to Jetty in several ways.

#### Using `start.jar`

If you are using ???, at startup the jetty runtime automatically loads option Jars from the top level `$jetty.home/lib` directory. The default settings include:

- Adding Jars under `$jetty.home/lib/ext` to the system classpath. You can place additional Jars here.
- Adding the directory `$jetty.home/resources` to the classpath (may contain classes or other resources).
- Adding a single path defined by the command line parameter path.

#### Using the extraClasspath() method

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>
     ...

### Using a Custom WebAppClassLoader

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.

### Starting Jetty with a Custom ClassLoader

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));

[[1xx-responses]] === Managing 1xx Responses

The HTTP RFC allows for 1xx informational responses to be sent before a real content response. Unfortunately the servlet specification does not provide a way for these to be sent, so Jetty has had to provide non-standard handling of these headers.

[[100-continue]] ==== 100 Continue

The 100 Continue response should be sent by the server when a client sends a request with a Expect: 100-continue header, as the client will not send the body of the request until the 100 continue response has been sent.

The intent of this feature is to allow a server to inspect the headers and to tell the client to not send a request body that might be too large or insufficiently private or otherwise unable to be handled.

Jetty achieves this by waiting until the input stream or reader is obtained by the filter/servlet, before sending the 100 continues response. Thus a filter/servlet may inspect the headers of a request before getting the input stream and send an error response (or redirect etc.) rather than the 100 continues.

[[102-processing]] ==== 102 Processing

RFC 2518 defines the 102 processing response that can be sent "when the server has a reasonable expectation that the request will take significant time to complete. As guidance, if a method is taking longer than 20 seconds (a reasonable, but arbitrary value) to process the server SHOULD return a 102 (Processing) response".

So if a request is received with the Expect: 102-processing header, then a filter/servlet may send a 102 response (without terminating further processing) by calling `servletResponse.sendError(102);`.

Previous | Top | Next
Chapter 30. Architecture | Home | Creating a Custom Protocol

See an error or something missing? Contribute to this documentation at Github!(Generated: 2017-05-02)