AllenKll
AllenKll

Reputation: 1056

Embedded Jetty: Servlet not initialized

I am trying to embed a Jetty server in an application with servlets.

When I hit the url: https://127.0.0.1:8443/hello

I get:

HTTP ERROR: 503

Problem accessing /hello.html. Reason:

javax.servlet.UnavailableException: Servlet not initialized

Powered by Jetty://

Here is my code:

public class Main 
{
  public static void main(String[] args) throws Exception 
  {
    // path to keystore.
    String jetty_home = System.getProperty("jetty.home","c:\\jetty.home");
    System.setProperty("jetty.home", jetty_home);

    // Create a basic jetty server object 
    Server server = new Server();

    // HTTP Configuration
    HttpConfiguration http_config = new HttpConfiguration();
    http_config.setSecureScheme("https");
    http_config.setSecurePort(8443);
    http_config.setOutputBufferSize(32768);

    // SSL Context Factory for HTTPS
    SslContextFactory sslContextFactory = new SslContextFactory();
    sslContextFactory.setKeyStorePath(jetty_home + "\\keystore");
    sslContextFactory.setKeyStorePassword("password");
    sslContextFactory.setKeyManagerPassword("password");

    // HTTPS Configuration
    HttpConfiguration https_config = new HttpConfiguration(http_config);
    https_config.addCustomizer(new SecureRequestCustomizer());

    // HTTPS connector
    ServerConnector https = new ServerConnector(server,
        new SslConnectionFactory(sslContextFactory, "http/1.1"),
        new HttpConnectionFactory(https_config));
    https.setPort(8443);

    // Set the connectors
    server.setConnectors(new Connector[] {  https });

    // Specify the Session ID Manager
    HashSessionIdManager idmanager = new HashSessionIdManager();
    server.setSessionIdManager(idmanager);

    // Sessions are bound to a context.
    ServletContextHandler context = new ServletContextHandler(null, "/", ServletContextHandler.SESSIONS|ServletContextHandler.NO_SECURITY);
    server.setHandler(context);

    // Create the SessionHandler (wrapper) to handle the sessions
    HashSessionManager manager = new HashSessionManager();
    SessionHandler sessions = new SessionHandler(manager);
    context.setHandler(sessions);

    // handle the servlets in the session inside of SessionHandler 
    ServletHandler servletHandler = new ServletHandler();
    sessions.setHandler(servletHandler);

    // tree should look like this:
    // Server
    //   + Connector -> HTTPS
    //      + ContextHandler( "/" )
    //         + SessionHandler
    //             + servletHandler

    // set up the servlet
    ServletHolder servletHolder = new ServletHolder(Main.MyServlet.class);

    servletHandler.addServletWithMapping(servletHolder, "/*");

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

  public static class MyServlet extends HttpServlet
  {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
      resp.getOutputStream().print("<html><body><h1>Hello</h1></body></html>");
    }
  }
}

What am I missing? How/Where does a servlet get initialized.

Upvotes: 1

Views: 3820

Answers (1)

Joakim Erdfelt
Joakim Erdfelt

Reputation: 49462

Since you didn't state what version of Jetty, I'll assume you are using Jetty 9.2.3.v20140905

This block of code is odd

// Sessions are bound to a context.
ServletContextHandler context = new ServletContextHandler(null, "/",
   ServletContextHandler.SESSIONS|ServletContextHandler.NO_SECURITY);
server.setHandler(context);  // <-- this is the ServletContext

// Create the SessionHandler (wrapper) to handle the sessions
HashSessionManager manager = new HashSessionManager();
SessionHandler sessions = new SessionHandler(manager);
context.setSessionHandler(sessions); // <-- set the session handler

// set up the servlet
ServletHolder servletHolder = new ServletHolder(Main.MyServlet.class);
context.addServlet(servletHolder, "/*");

First, don't manage the ServletHandler yourself, you are just undoing all of the work that the ServletContextHandler itself does.

Also, don't manage the handler tree yourself, let the internals manage the proper linking, hence the switch to .setSessionHandler()

Finally, use the context.addServlet() instead of .addServletWithMapping()

Upvotes: 3

Related Questions