Version: 9.4.30.v20200611 |

Embedding Jetty
Previous | Chapter 21. Embedding 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

## Embedding Jetty

Jetty has a slogan, "Don’t deploy your application in Jetty, deploy Jetty in your application!" What this means is that as an alternative to bundling your application as a standard WAR to be deployed in Jetty, Jetty is designed to be a software component that can be instantiated and used in a Java program just like any POJO. Put another way, running Jetty in embedded mode means putting an HTTP module into your application, rather than putting your application into an HTTP server.

This tutorial takes you step-by-step from the simplest Jetty server instantiation to running multiple web applications with standards-based deployment descriptors. The source for most of these examples is part of the standard Jetty project.

### Overview

To embed a Jetty server the following steps are typical and are illustrated by the examples in this tutorial:

1. Create a Server instance.
2. Add/Configure Connectors.
3. Add/Configure Handlers and/or Contexts and/or Servlets.
4. Start the Server.
5. Wait on the server or do something else with your thread.

### Creating the Server

The following code from SimplestServer.java instantiates and runs the simplest possible Jetty server:

    //
    //  ========================================================================
    //  Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //

    package org.eclipse.jetty.embedded;

    import org.eclipse.jetty.server.Server;

    /**
     * The simplest possible Jetty server.
     */
    public class SimplestServer
    {
        public static Server createServer(int port)
        {
            Server server = new Server(port);
            // This has a connector listening on port specified
            // and no handlers, meaning all requests will result
            // in a 404 response
            return server;
        }

        public static void main(String[] args) throws Exception
        {
            int port = ExampleUtil.getPort(args, "jetty.http.port", 8080);
            Server server = createServer(port);
            server.start();
            server.join();
        }
    }

This runs an HTTP server on port 8080. It is not a very useful server as it has no handlers, and thus returns a 404 error for every request.

### Using Handlers

To produce a response to a request, Jetty requires that you set a Handler on the server. A handler may:

- Examine/modify the HTTP request.
- Generate the complete HTTP response.
- Call another Handler (see `HandlerWrapper`).
- Select one or many Handlers to call (see `HandlerCollection`).

#### HelloWorld Handler

The following code based on HelloHandler.java shows a simple hello world handler:

    //
    //  ========================================================================
    //  Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //

    package org.eclipse.jetty.embedded;

    import java.io.IOException;
    import java.io.PrintWriter;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.eclipse.jetty.server.Request;
    import org.eclipse.jetty.server.handler.AbstractHandler;

    public class HelloHandler extends AbstractHandler
    {
        final String greeting;
        final String body;

        public HelloHandler()
        {
            this("Hello World");
        }

        public HelloHandler(String greeting)
        {
            this(greeting, null);
        }

        public HelloHandler(String greeting, String body)
        {
            this.greeting = greeting;
            this.body = body;
        }

        @Override
        public void handle(String target,
                           Request baseRequest,
                           HttpServletRequest request,
                           HttpServletResponse response) throws IOException,
            ServletException
        {
            response.setContentType("text/html; charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);

            PrintWriter out = response.getWriter();

            out.println("<h1>" + greeting + "</h1>");
            if (body != null)
            {
                out.println(body);
            }

            baseRequest.setHandled(true);
        }
    }

The parameters passed to the handle method are:

- `target` – the target of the request, which is either a URI or a name from a named dispatcher.
- `baseRequest` – the Jetty mutable request object, which is always unwrapped.
- `request` – the immutable request object, which may have been wrapped by a filter or servlet.
- `response` – the response, which may have been wrapped by a filter or servlet.

The handler sets the response status, content-type, and marks the request as handled before it generates the body of the response using a writer.

#### Running HelloWorldHandler

To allow a Handler to handle HTTP requests, you must add it to a Server instance. The following code from OneHandler.java shows how a Jetty server can use the HelloWorld handler:

    //
    //  ========================================================================
    //  Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //

    package org.eclipse.jetty.embedded;

    import org.eclipse.jetty.server.Server;

    public class OneHandler
    {
        public static Server createServer(int port)
        {
            Server server = new Server(port);
            server.setHandler(new HelloHandler());
            return server;
        }

        public static void main(String[] args) throws Exception
        {
            int port = ExampleUtil.getPort(args, "jetty.http.port", 8080);
            Server server = createServer(port);
            server.start();
            server.join();
        }
    }

One or more handlers do all request handling in Jetty. Some handlers select other specific handlers (for example, a `ContextHandlerCollection` uses the context path to select a `ContextHandler`); others use application logic to generate a response (for example, the `ServletHandler` passes the request to an application Servlet), while others do tasks unrelated to generating the response (for example, `RequestLogHandler` or `StatisticsHandler`).

Later sections describe how you can combine handlers like aspects. You can see some of the handlers available in Jetty in the org.eclipse.jetty.server.handler package.

#### Handler Collections and Wrappers

Complex request handling is typically built from multiple Handlers that you can combine in various ways. Jetty has several implementations of the `HandlerContainer` interface:

`HandlerCollection`
  Holds a collection of other handlers and calls each handler in order. This is useful for combining statistics and logging handlers with the handler that generates the response.
`HandlerList`
  A Handler Collection that calls each handler in turn until either an exception is thrown, the response is committed or the `request.isHandled()` returns true. You can use it to combine handlers that conditionally handle a request, such as calling multiple contexts until one matches a virtual host.
`HandlerWrapper`
  A Handler base class that you can use to daisy chain handlers together in the style of aspect-oriented programming. For example, a standard web application is implemented by a chain of a context, session, security and servlet handlers.
`ContextHandlerCollection`
  A specialized `HandlerCollection` that uses the longest prefix of the request URI (the `contextPath`) to select a contained `ContextHandler` to handle the request.

#### Scoped Handlers

Much of the standard Servlet container in Jetty is implemented with `HandlerWrappers` that daisy chain handlers together: `ContextHandler` to `SessionHandler` to `SecurityHandler` to `ServletHandler`. However, because of the nature of the servlet specification, this chaining cannot be a pure nesting of handlers as the outer handlers sometimes need information that the inner handlers process. For example, when a `ContextHandler` calls some application listeners to inform them of a request entering the context, it must already know which servlet the `ServletHandler` will dispatch the request to so that the `servletPath` method returns the correct value.

The `HandlerWrapper` is specialized to the `ScopedHandler` abstract class, which supports a daisy chain of scopes. For example if a `ServletHandler` is nested within a `ContextHandler`, the order and nesting of execution of methods is:

    Server.handle(...)
      ContextHandler.doScope(...)
        ServletHandler.doScope(...)
          ContextHandler.doHandle(...)
            ServletHandler.doHandle(...)
              SomeServlet.service(...)

Thus when the `ContextHandler` handles the request, it does so within the scope the `ServletHandler` has established.

#### Resource Handler

The FileServer example shows how you can use a `ResourceHandler` to serve static content from the current working directory:

    //
    //  ========================================================================
    //  Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //

    package org.eclipse.jetty.embedded;

    import java.nio.file.Path;
    import java.nio.file.Paths;

    import org.eclipse.jetty.server.Handler;
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.handler.DefaultHandler;
    import org.eclipse.jetty.server.handler.HandlerList;
    import org.eclipse.jetty.server.handler.ResourceHandler;
    import org.eclipse.jetty.util.resource.PathResource;
    import org.eclipse.jetty.util.resource.Resource;

    /**
     * Simple Jetty FileServer.
     * This is a simple example of Jetty configured as a FileServer.
     */
    public class FileServer
    {
        public static Server createServer(int port, Resource baseResource) throws Exception
        {
            // Create a basic Jetty server object that will listen on port 8080.  Note that if you set this to port 0
            // then a randomly available port will be assigned that you can either look in the logs for the port,
            // or programmatically obtain it for use in test cases.
            Server server = new Server(port);

            // Create the ResourceHandler. It is the object that will actually handle the request for a given file. It is
            // a Jetty Handler object so it is suitable for chaining with other handlers as you will see in other examples.
            ResourceHandler resourceHandler = new ResourceHandler();

            // Configure the ResourceHandler. Setting the resource base indicates where the files should be served out of.
            // In this example it is the current directory but it can be configured to anything that the jvm has access to.
            resourceHandler.setDirectoriesListed(true);
            resourceHandler.setWelcomeFiles(new String[]{"index.html"});
            resourceHandler.setBaseResource(baseResource);

            // Add the ResourceHandler to the server.
            HandlerList handlers = new HandlerList();
            handlers.setHandlers(new Handler[]{resourceHandler, new DefaultHandler()});
            server.setHandler(handlers);

            return server;
        }

        public static void main(String[] args) throws Exception
        {
            int port = ExampleUtil.getPort(args, "jetty.http.port", 8080);
            Path userDir = Paths.get(System.getProperty("user.dir"));
            PathResource pathResource = new PathResource(userDir);

            Server server = createServer(port, pathResource);

            // Start things up! By using the server.join() the server thread will join with the current thread.
            // See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details.
            server.start();
            server.join();
        }
    }

Notice that a `HandlerList` is used with the `ResourceHandler` and a `DefaultHandler`, so that the `DefaultHandler` generates a good 404 response for any requests that do not match a static resource.

### Embedding Connectors

In the previous examples, the Server instance is passed a port number and it internally creates a default instance of a Connector that listens for requests on that port. However, often when embedding Jetty it is desirable to explicitly instantiate and configure one or more Connectors for a Server instance.

#### One Connector

The following example, OneConnector.java, instantiates, configures, and adds a single HTTP connector instance to the server:

    //
    //  ========================================================================
    //  Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //

    package org.eclipse.jetty.embedded;

    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.ServerConnector;

    /**
     * A Jetty server with one connectors.
     */
    public class OneConnector
    {
        public static Server createServer(int port) throws Exception
        {
            // The Server
            Server server = new Server();

            // HTTP connector
            ServerConnector http = new ServerConnector(server);
            http.setHost("localhost");
            http.setPort(port);
            http.setIdleTimeout(30000);

            // Set the connector
            server.addConnector(http);

            // Set a handler
            server.setHandler(new HelloHandler());
            return server;
        }

        public static void main(String[] args) throws Exception
        {
            int port = ExampleUtil.getPort(args, "jetty.http.port", 8080);
            Server server = createServer(port);

            // Start the server
            server.start();
            server.join();
        }
    }

In this example the connector handles the HTTP protocol, as that is the default for the `ServerConnector` class.

#### Many Connectors

When configuring multiple connectors (for example, HTTP and HTTPS), it may be desirable to share configuration of common parameters for HTTP. To achieve this you need to explicitly configure the `ServerConnector` class with `ConnectionFactory` instances, and provide them with common HTTP configuration.

The ManyConnectors example, configures a server with two `ServerConnector` instances: the http connector has a `HTTPConnectionFactory` instance; the https connector has a `SslConnectionFactory` chained to a `HttpConnectionFactory`. Both `HttpConnectionFactory` are configured based on the same `HttpConfiguration` instance, however the HTTPS factory uses a wrapped configuration so that a `SecureRequestCustomizer` can be added.

### Embedding Servlets

Servlets are the standard way to provide application logic that handles HTTP requests. Servlets are similar to a Jetty Handler except that the request object is not mutable and thus cannot be modified. Servlets are handled in Jetty by a `ServletHandler`. It uses standard path mappings to match a Servlet to a request; sets the requests `servletPath` and `pathInfo`; passes the request to the servlet, possibly via Filters to produce a response.

The MinimalServlets example creates a `ServletHandler` instance and configures a single HelloServlet:

    //
    //  ========================================================================
    //  Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //

    package org.eclipse.jetty.embedded;

    import java.io.IOException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.servlet.ServletHandler;

    public class MinimalServlets
    {

        public static Server createServer(int port)
        {
            // Note that if you set this to port 0 then a randomly available port
            // will be assigned that you can either look in the logs for the port,
            // or programmatically obtain it for use in test cases.
            Server server = new Server(port);

            // The ServletHandler is a dead simple way to create a context handler
            // that is backed by an instance of a Servlet.
            // This handler then needs to be registered with the Server object.
            ServletHandler handler = new ServletHandler();
            server.setHandler(handler);

            // Passing in the class for the Servlet allows jetty to instantiate an
            // instance of that Servlet and mount it on a given context path.

            // IMPORTANT:
            // This is a raw Servlet, not a Servlet that has been configured
            // through a web.xml @WebServlet annotation, or anything similar.
            handler.addServletWithMapping(HelloServlet.class, "/*");

            return server;
        }

        public static void main(String[] args) throws Exception
        {
            // Create a basic jetty server object that will listen on port 8080.
            int port = ExampleUtil.getPort(args, "jetty.http.port", 8080);
            Server server = createServer(port);

            // Start things up!
            server.start();

            // The use of server.join() the will make the current thread join and
            // wait until the server thread is done executing.
            server.join();
        }

        @SuppressWarnings("serial")
        public static class HelloServlet extends HttpServlet
        {
            @Override
            protected void doGet(HttpServletRequest request,
                                 HttpServletResponse response) throws IOException
            {
                response.setStatus(HttpServletResponse.SC_OK);
                response.setContentType("text/html");
                response.setCharacterEncoding("utf-8");
                response.getWriter().println("<h1>Hello from HelloServlet</h1>");
            }
        }
    }

### Embedding Contexts

A `ContextHandler` is a `ScopedHandler` that responds only to requests that have a URI prefix that matches the configured context path. Requests that match the context path have their path methods updated accordingly and the contexts scope is available, which optionally may include:

- A `Classloader` that is set as the Thread context `classloader` while request handling is in scope.
- A set of attributes that is available via the `ServletContext` API.
- A set of init parameters that is available via the `ServletContext` API.
- A base Resource which is used as the document root for static resource requests via the `ServletContext` API.
- A set of virtual host names.

The following OneContext example shows a context being established that wraps the HelloHandler:

    //
    //  ========================================================================
    //  Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //

    package org.eclipse.jetty.embedded;

    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.handler.ContextHandler;

    public class OneContext
    {
        public static Server createServer(int port)
        {
            Server server = new Server(port);

            // Add a single handler on context "/hello"
            ContextHandler context = new ContextHandler();
            context.setContextPath("/hello");
            context.setHandler(new HelloHandler());

            // Can be accessed using http://localhost:8080/hello

            server.setHandler(context);
            return server;
        }

        public static void main(String[] args) throws Exception
        {
            int port = ExampleUtil.getPort(args, "jetty.http.port", 8080);
            Server server = createServer(port);

            // Start the server
            server.start();
            server.join();
        }
    }

When many contexts are present, you can embed a `ContextHandlerCollection` to efficiently examine a request URI to then select the matching `ContextHandler`(s) for the request. The ManyContexts example shows how many such contexts you can configure:

    //
    //  ========================================================================
    //  Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //

    package org.eclipse.jetty.embedded;

    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.handler.ContextHandler;
    import org.eclipse.jetty.server.handler.ContextHandlerCollection;

    public class ManyContexts
    {
        public static Server createServer(int port)
        {
            Server server = new Server(port);

            ContextHandler context = new ContextHandler("/");
            context.setContextPath("/");
            context.setHandler(new HelloHandler("Root Hello"));

            ContextHandler contextFR = new ContextHandler("/fr");
            contextFR.setHandler(new HelloHandler("Bonjour"));

            ContextHandler contextIT = new ContextHandler("/it");
            contextIT.setHandler(new HelloHandler("Buongiorno"));

            ContextHandler contextV = new ContextHandler("/");
            contextV.setVirtualHosts(new String[]{"127.0.0.2"});
            contextV.setHandler(new HelloHandler("Virtual Hello"));

            ContextHandlerCollection contexts = new ContextHandlerCollection(
                context, contextFR, contextIT, contextV
            );

            server.setHandler(contexts);
            return server;
        }

        public static void main(String[] args) throws Exception
        {
            int port = ExampleUtil.getPort(args, "jetty.http.port", 8080);
            Server server = createServer(port);
            server.start();
            server.dumpStdErr();
            server.join();
        }
    }

### Embedding ServletContexts

A `ServletContextHandler` is a specialization of `ContextHandler` with support for standard sessions and Servlets. The following OneServletContext example instantiates a `DefaultServlet` to server static content from /tmp/ and a `DumpServlet` that creates a session and dumps basic details about the request:

    //
    //  ========================================================================
    //  Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //

    package org.eclipse.jetty.embedded;

    import java.io.IOException;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.EnumSet;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletRequestEvent;
    import javax.servlet.ServletRequestListener;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletResponse;

    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.servlet.DefaultServlet;
    import org.eclipse.jetty.servlet.ListenerHolder;
    import org.eclipse.jetty.servlet.ServletContextHandler;
    import org.eclipse.jetty.servlet.ServletHolder;
    import org.eclipse.jetty.util.resource.PathResource;
    import org.eclipse.jetty.util.resource.Resource;

    import static javax.servlet.DispatcherType.ASYNC;
    import static javax.servlet.DispatcherType.REQUEST;

    public class OneServletContext
    {
        public static Server createServer(int port, Resource baseResource)
        {
            Server server = new Server(port);

            ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
            context.setContextPath("/");
            context.setBaseResource(baseResource);
            server.setHandler(context);

            // add hello servlet
            context.addServlet(HelloServlet.class, "/hello/*");

            // Add dump servlet on multiple url-patterns
            ServletHolder debugHolder = new ServletHolder("debug", DumpServlet.class);
            context.addServlet(debugHolder, "/dump/*");
            context.addServlet(debugHolder, "*.dump");

            // add default servlet (for error handling and static resources)
            context.addServlet(DefaultServlet.class, "/");

            // sprinkle in a few filters to demonstrate behaviors
            context.addFilter(TestFilter.class, "/test/*", EnumSet.of(REQUEST));
            context.addFilter(TestFilter.class, "*.test", EnumSet.of(REQUEST, ASYNC));

            // and a few listeners to show other ways of working with servlets
            context.getServletHandler().addListener(new ListenerHolder(InitListener.class));
            context.getServletHandler().addListener(new ListenerHolder(RequestListener.class));

            return server;
        }

        public static void main(String[] args) throws Exception
        {
            int port = ExampleUtil.getPort(args, "jetty.http.port", 8080);
            Path tempDir = Paths.get(System.getProperty("java.io.tmpdir"));

            Server server = createServer(port, new PathResource(tempDir));

            server.start();
            server.dumpStdErr();
            server.join();
        }

        public static class TestFilter implements Filter
        {
            @Override
            public void init(FilterConfig filterConfig)
            {
            }

            @Override
            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
            {
                if (response instanceof HttpServletResponse)
                {
                    HttpServletResponse httpServletResponse = (HttpServletResponse)response;
                    httpServletResponse.setHeader("X-TestFilter", "true");
                }
                chain.doFilter(request, response);
            }

            @Override
            public void destroy()
            {

            }
        }

        public static class InitListener implements ServletContextListener
        {
            @Override
            public void contextInitialized(ServletContextEvent sce)
            {
                sce.getServletContext().setAttribute("X-Init", "true");
            }

            @Override
            public void contextDestroyed(ServletContextEvent sce)
            {
            }
        }

        public static class RequestListener implements ServletRequestListener
        {
            @Override
            public void requestInitialized(ServletRequestEvent sre)
            {
                sre.getServletRequest().setAttribute("X-ReqListener", "true");
            }

            @Override
            public void requestDestroyed(ServletRequestEvent sre)
            {
            }
        }
    }

### Embedding Web Applications

A `WebAppContext` is an extension of a `ServletContextHandler` that uses the standard layout and web.xml to configure the servlets, filters and other features from a web.xml and/or annotations. The following OneWebApp example configures the Jetty test webapp. Web applications can use resources the container provides, and in this case a `LoginService` is needed and also configured:

    //
    //  ========================================================================
    //  Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //

    package org.eclipse.jetty.embedded;

    import java.io.File;

    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.webapp.WebAppContext;

    public class OneWebApp
    {
        public static Server createServer(int port)
        {
            // Create a basic jetty server object that will listen on port 8080.
            // Note that if you set this to port 0 then a randomly available port
            // will be assigned that you can either look in the logs for the port,
            // or programmatically obtain it for use in test cases.
            Server server = new Server(port);

            // The WebAppContext is the entity that controls the environment in
            // which a web application lives and breathes. In this example the
            // context path is being set to "/" so it is suitable for serving root
            // context requests and then we see it setting the location of the war.
            // A whole host of other configurations are available, ranging from
            // configuring to support annotation scanning in the webapp (through
            // PlusConfiguration) to choosing where the webapp will unpack itself.
            WebAppContext webapp = new WebAppContext();
            webapp.setContextPath("/");
            File warFile = JettyDistribution.resolve("demo-base/webapps/async-rest.war").toFile();
            webapp.setWar(warFile.getAbsolutePath());

            // A WebAppContext is a ContextHandler as well so it needs to be set to
            // the server so it is aware of where to send the appropriate requests.
            server.setHandler(webapp);
            return server;
        }

        public static void main(String[] args) throws Exception
        {
            int port = ExampleUtil.getPort(args, "jetty.http.port", 8080);
            Server server = createServer(port);

            // Start things up!
            server.start();

            server.dumpStdErr();

            // The use of server.join() the will make the current thread join and
            // wait until the server is done executing.
            server.join();
        }
    }

### Like Jetty XML

The typical way to configure an instance of the Jetty server is via `jetty.xml` and associated configuration files. However the Jetty XML configuration format is just a simple rendering of what you can do in code; it is very simple to write embedded code that does precisely what the jetty.xml configuration does. The LikeJettyXml example following renders in code the behavior obtained from the configuration files:

- jetty.xml
- jetty-jmx.xml
- jetty-http.xml
- jetty-https.xml
- jetty-deploy.xml
- jetty-stats.xml
- jetty-requestlog.xml
- jetty-lowresources.xml
- test-realm.xml

    //
    //  ========================================================================
    //  Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //

    package org.eclipse.jetty.embedded;

    import java.io.FileNotFoundException;
    import java.lang.management.ManagementFactory;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;

    import org.eclipse.jetty.deploy.DeploymentManager;
    import org.eclipse.jetty.deploy.PropertiesConfigurationManager;
    import org.eclipse.jetty.deploy.bindings.DebugListenerBinding;
    import org.eclipse.jetty.deploy.providers.WebAppProvider;
    import org.eclipse.jetty.http.HttpVersion;
    import org.eclipse.jetty.jmx.MBeanContainer;
    import org.eclipse.jetty.rewrite.handler.MsieSslRule;
    import org.eclipse.jetty.rewrite.handler.RewriteHandler;
    import org.eclipse.jetty.rewrite.handler.ValidUrlRule;
    import org.eclipse.jetty.security.HashLoginService;
    import org.eclipse.jetty.server.AsyncRequestLogWriter;
    import org.eclipse.jetty.server.CustomRequestLog;
    import org.eclipse.jetty.server.DebugListener;
    import org.eclipse.jetty.server.Handler;
    import org.eclipse.jetty.server.HttpConfiguration;
    import org.eclipse.jetty.server.HttpConnectionFactory;
    import org.eclipse.jetty.server.LowResourceMonitor;
    import org.eclipse.jetty.server.SecureRequestCustomizer;
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.ServerConnectionStatistics;
    import org.eclipse.jetty.server.ServerConnector;
    import org.eclipse.jetty.server.SslConnectionFactory;
    import org.eclipse.jetty.server.handler.ContextHandlerCollection;
    import org.eclipse.jetty.server.handler.DefaultHandler;
    import org.eclipse.jetty.server.handler.HandlerCollection;
    import org.eclipse.jetty.server.handler.StatisticsHandler;
    import org.eclipse.jetty.util.ssl.SslContextFactory;
    import org.eclipse.jetty.util.thread.QueuedThreadPool;
    import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
    import org.eclipse.jetty.webapp.Configuration;

    /**
     * Starts the Jetty Distribution's demo-base directory using entirely
     * embedded jetty techniques.
     */
    public class LikeJettyXml
    {
        public static Server createServer(int port, int securePort, boolean addDebugListener) throws Exception
        {
            // Path to as-built jetty-distribution directory
            Path jettyHomeBuild = JettyDistribution.get();

            // Find jetty home and base directories
            String homePath = System.getProperty("jetty.home", jettyHomeBuild.toString());
            Path homeDir = Paths.get(homePath);

            String basePath = System.getProperty("jetty.base", homeDir.resolve("demo-base").toString());
            Path baseDir = Paths.get(basePath);

            // Configure jetty.home and jetty.base system properties
            String jettyHome = homeDir.toAbsolutePath().toString();
            String jettyBase = baseDir.toAbsolutePath().toString();
            System.setProperty("jetty.home", jettyHome);
            System.setProperty("jetty.base", jettyBase);

            // === jetty.xml ===
            // Setup Threadpool
            QueuedThreadPool threadPool = new QueuedThreadPool();
            threadPool.setMaxThreads(500);

            // Server
            Server server = new Server(threadPool);

            // Scheduler
            server.addBean(new ScheduledExecutorScheduler(null, false));

            // HTTP Configuration
            HttpConfiguration httpConfig = new HttpConfiguration();
            httpConfig.setSecureScheme("https");
            httpConfig.setSecurePort(securePort);
            httpConfig.setOutputBufferSize(32768);
            httpConfig.setRequestHeaderSize(8192);
            httpConfig.setResponseHeaderSize(8192);
            httpConfig.setSendServerVersion(true);
            httpConfig.setSendDateHeader(false);
            // httpConfig.addCustomizer(new ForwardedRequestCustomizer());

            // Handler Structure
            HandlerCollection handlers = new HandlerCollection();
            ContextHandlerCollection contexts = new ContextHandlerCollection();
            handlers.setHandlers(new Handler[]{contexts, new DefaultHandler()});
            server.setHandler(handlers);

            // === jetty-jmx.xml ===
            MBeanContainer mbContainer = new MBeanContainer(
                ManagementFactory.getPlatformMBeanServer());
            server.addBean(mbContainer);

            // === jetty-http.xml ===
            ServerConnector http = new ServerConnector(server,
                new HttpConnectionFactory(httpConfig));
            http.setPort(port);
            http.setIdleTimeout(30000);
            server.addConnector(http);

            // === jetty-https.xml ===
            // SSL Context Factory
            Path keystorePath = Paths.get("src/main/resources/etc/keystore").toAbsolutePath();
            if (!Files.exists(keystorePath))
                throw new FileNotFoundException(keystorePath.toString());
            SslContextFactory sslContextFactory = new SslContextFactory.Server();
            sslContextFactory.setKeyStorePath(keystorePath.toString());
            sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
            sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
            sslContextFactory.setTrustStorePath(keystorePath.toString());
            sslContextFactory.setTrustStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");

            // SSL HTTP Configuration
            HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
            httpsConfig.addCustomizer(new SecureRequestCustomizer());

            // SSL Connector
            ServerConnector sslConnector = new ServerConnector(server,
                new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
                new HttpConnectionFactory(httpsConfig));
            sslConnector.setPort(securePort);
            server.addConnector(sslConnector);

            // === jetty-deploy.xml ===
            DeploymentManager deployer = new DeploymentManager();
            if (addDebugListener)
            {
                DebugListener debug = new DebugListener(System.err, true, true, true);
                server.addBean(debug);
                deployer.addLifeCycleBinding(new DebugListenerBinding(debug));
            }
            deployer.setContexts(contexts);
            deployer.setContextAttribute(
                "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
                ".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$");

            WebAppProvider webAppProvider = new WebAppProvider();
            webAppProvider.setMonitoredDirName(jettyBase + "/webapps");
            webAppProvider.setDefaultsDescriptor(jettyHome + "/etc/webdefault.xml");
            webAppProvider.setScanInterval(1);
            webAppProvider.setExtractWars(true);
            webAppProvider.setConfigurationManager(new PropertiesConfigurationManager());

            deployer.addAppProvider(webAppProvider);
            server.addBean(deployer);

            // === setup jetty plus ==
            Configuration.ClassList classlist = Configuration.ClassList
                .setServerDefault(server);
            classlist.addAfter(
                "org.eclipse.jetty.webapp.FragmentConfiguration",
                "org.eclipse.jetty.plus.webapp.EnvConfiguration",
                "org.eclipse.jetty.plus.webapp.PlusConfiguration");

            classlist.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
                "org.eclipse.jetty.annotations.AnnotationConfiguration");

            // === jetty-stats.xml ===
            StatisticsHandler stats = new StatisticsHandler();
            stats.setHandler(server.getHandler());
            server.setHandler(stats);
            ServerConnectionStatistics.addToAllConnectors(server);

            // === Rewrite Handler
            RewriteHandler rewrite = new RewriteHandler();
            rewrite.setHandler(server.getHandler());
            server.setHandler(rewrite);
            rewrite.addRule(new MsieSslRule());
            rewrite.addRule(new ValidUrlRule());

            // === jetty-requestlog.xml ===
            AsyncRequestLogWriter logWriter = new AsyncRequestLogWriter(jettyHome + "/logs/yyyy_mm_dd.request.log");
            CustomRequestLog requestLog = new CustomRequestLog(logWriter, CustomRequestLog.EXTENDED_NCSA_FORMAT + " \"%C\"");
            logWriter.setFilenameDateFormat("yyyy_MM_dd");
            logWriter.setRetainDays(90);
            logWriter.setTimeZone("GMT");
            server.setRequestLog(requestLog);

            // === jetty-lowresources.xml ===
            LowResourceMonitor lowResourcesMonitor = new LowResourceMonitor(server);
            lowResourcesMonitor.setPeriod(1000);
            lowResourcesMonitor.setLowResourcesIdleTimeout(200);
            lowResourcesMonitor.setMonitorThreads(true);
            lowResourcesMonitor.setMaxMemory(0);
            lowResourcesMonitor.setMaxLowResourcesTime(5000);
            server.addBean(lowResourcesMonitor);

            // === test-realm.xml ===
            HashLoginService login = new HashLoginService();
            login.setName("Test Realm");
            login.setConfig(jettyBase + "/etc/realm.properties");
            login.setHotReload(false);
            server.addBean(login);

            return server;
        }

        public static void main(String[] args) throws Exception
        {
            int port = ExampleUtil.getPort(args, "jetty.http.port", 8080);
            int securePort = ExampleUtil.getPort(args, "jetty.https.port", 8443);
            Server server = createServer(port, securePort, true);

            // Extra options
            server.setDumpAfterStart(true);
            server.setDumpBeforeStop(false);
            server.setStopAtShutdown(true);

            // Start the server
            server.start();
            server.join();
        }
    }

Previous | Top | Next
Chapter 21. Embedding | Home | Embedded Examples

See an error or something missing? Contribute to this documentation at Github!(Generated: 2020-06-11)