What is difference between ServletContextHandler.setResourceBase and ResourceHandler.setResourceBase when using Jetty embedded container?

I'm using embedded Jetty to create a static web site. Does ServletContextHandler.setResourceBase("...") have a same effect as ResourceHandler.setResourceBase("...")?

Example:

// ServletContextHandler case
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setResourceBase("/tmp/...");
// ResourceHandler case
ResourceHandler resourceHandler = new ResourceHandler();
resourceHandler.setResourceBase("/tmp/...");

I have tried test both of them. ResourceHandler works exactly what I want. But otherwise doesn't. What's the difference between them?

(Sorry for my poor English :P)

Update

After changed, below is whole code. Context("/") serves static files, wsContext("/ws") serves web socket endpoints. Of course Context("/") is able to serve web socket endpoints as well.

 server = new Server();
 server.setStopAtShutdown(true);
 ServerConnector connector = new ServerConnector(server);
 connector.setPort(8000);
 server.addConnector(connector);

 // Setup the basic application "context" for this application at "/"
 // This is also known as the handler tree (in jetty speak)
 ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);

 context.setContextPath("/");
 context.setResourceBase(System.getProperty("webapp.path"));

 ServletContextHandler wsContext = new ServletContextHandler();
 wsContext.setContextPath("/ws");

 ContextHandlerCollection contexts=new ContextHandlerCollection();
 contexts.setHandlers(new Handler[]{context, wsContext});

 server.setHandler(contexts);

 context.addServlet(DefaultServlet.class, "/");

 // Initialize javax.websocket layer
 ServerContainer wsContainer = WebSocketServerContainerInitializer.configureContext(wsContext);

 // Add WebSocket endpoint to javax.websocket layer
 // code omitted...

 server.start();
 logger.info("WebServer started.");

Solution 1:

With that setup, the resourceHandler will never be called, as the DefaultServlet processing (or Default404Servlet) at the end of the ServletContextHandler chain will always respond, not allowing resourceHandler to even execute.

If you have a ServletContextHandler, do not use ResourceHandler use the DefaultServlet in that ServletContextHandler to setup and serve your static files.

ResourceHandler is very simplistic, if you want more control / features, use a DefaultServlet configured in your ServletContextHandler instead.

Ok, with that out of the way ...

The ServletContextHandler.setBaseResource(Resource) is the place for the ServletContext itself to configure its context-wide resourceBase.

(Note: the parameter of setResourceBase() is a URL string that can point to a file:// directory or even a jar:file:// location. Pretty much anything supported by Resource.newResource(String))

  • ${resourceBase}/ is the lookup point for various methods in javax.servlet.ServletContext such as:
    • String getRealPath(String path)
    • URL getResource(String path)
    • InputStream getResourceAsStream(String path)
    • Set<String> getResources(String path)
  • Requested resources that don't match any of your servlets or filters, will then be handled by the DefaultServlet, which might serve static resources (such as *.html, *.css, *.js) from the specified ${resourceBase}/${request.pathInfo}

ResourceHandler does not participate in ServletContextHandler is an is inappropriate to mix with ServletContextHandler.

Also, don't forget to set ServletContextHandler.setContextPath(String) to your desired context path (usually "/")

And yes, you can even have multiple DefaultServlet configurations in a single ServletContextHandler.