58

I'm trying to build a simple demo app with embedded Jetty that serves static files from a "html" directory that's a subdirectory of the current working directory. The idea is that the directory with the demo jar and content can be moved to a new location and still work.

I've tried variations of the following, but I keep getting 404s.

ServletContextHandler context = 
                       new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");

context.getInitParams().put(
                       "org.eclipse.jetty.servlet.Default.resourceBase", "html");
context.addServlet(new ServletHolder(new DefaultServlet()), "/html");

Server jetty = new Server(8080);
jetty.setHandler(context);

jetty.start();

Update: Here's a solution as documented in the Jetty tutorial. As mentioned in the correct answer, it uses a ResourceHandler instead of a ServletContextHandler:

    Server server = new Server();
    SelectChannelConnector connector = new SelectChannelConnector();
    connector.setPort(8080);
    server.addConnector(connector);

    ResourceHandler resource_handler = new ResourceHandler();
    resource_handler.setDirectoriesListed(true);
    resource_handler.setWelcomeFiles(new String[]{ "index.html" });

    resource_handler.setResourceBase(".");

    HandlerList handlers = new HandlerList();
    handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });
    server.setHandler(handlers);

    server.start();
    server.join();
Cœur
  • 37,241
  • 25
  • 195
  • 267
HolySamosa
  • 9,011
  • 14
  • 69
  • 102
  • pom.xml file that works with this: https://code.google.com/p/ram-badger/source/browse/trunk/static-jetty/pom.xml – cwash Jul 31 '13 at 06:31
  • 1
    this doesn't seem to work with jetty 9... – Ilya Buziuk Feb 05 '15 at 13:53
  • 1
    if one face same issues with jetty 9 @see - http://stackoverflow.com/questions/28346438/resourcehandler-stop-hosting-files-with-jetty-9-404-not-found-error-works-fin – Ilya Buziuk Feb 05 '15 at 14:31

5 Answers5

34

Use a ResourceHandler instead of ServletContextHandler.

msrd0
  • 7,816
  • 9
  • 47
  • 82
Guy Hillyer
  • 568
  • 4
  • 5
  • 1
    Indeed... http://jetty.codehaus.org/jetty/jetty-6/apidocs/org/mortbay/jetty/handler/ResourceHandler.html – Spencer Kormos Apr 23 '12 at 18:59
  • 4
    That did the trick! Thanks guys! The code is even given in the Jetty tutorial. Doh! http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty#Configuring_a_File_Server – HolySamosa Apr 23 '12 at 19:16
  • 1
    you still may want to use `ServletContextHandler` if you need javax.servlet.Filter (for details, please see my comment below) – xorcus Oct 28 '13 at 12:18
  • 5
    Back when Jetty 6 existed, this advice made sense. Today, with Jetty 9, this advice is no longer valid. See http://stackoverflow.com/a/28419106/775715 – Joakim Erdfelt Feb 13 '15 at 13:26
  • The first link is dead. Anyone knows how to get to that page? – The Impaler Jul 12 '18 at 00:25
20

There is an important difference between serving static content using a ResourceHandler and using a DefaultServlet (with a ServletContextHandler).

When a ResourceHandler (or a HandlerList holding multiple ResourceHandler instances) is set as a context handler, it directly processes requests and ignores any registered javax.servlet.Filter instances.

If you need filters, the only way to go about it is using a ServletContextHandler, adding filters to it, then adding a DefaultServlet and finally, setting the base Resource.

The base Resource represents a resourceBase path a ResourceHandler would be initialised with. If serving static resources from multiple directories, use a ResourceCollection (which is still a Resource) and initialise it with an array of resourceBase strings:

ResourceCollection resourceCollection = new ResourceCollection();
resourceCollection.setResources(getArrayOfResourceBaseDirs());
xorcus
  • 999
  • 1
  • 11
  • 12
19

In my small web server I have two files, a index.html and a info.js locate under /src/webapp and I want them to be served from the embedded jetty web server.

This is how I solve the problem with static content.

Server server = new Server(8080);

ServletContextHandler ctx = new ServletContextHandler();
ctx.setContextPath("/");

DefaultServlet defaultServlet = new DefaultServlet();
ServletHolder holderPwd = new ServletHolder("default", defaultServlet);
holderPwd.setInitParameter("resourceBase", "./src/webapp/");

ctx.addServlet(holderPwd, "/*");
ctx.addServlet(InfoServiceSocketServlet.class, "/info");

server.setHandler(ctx);

Worked like a charm!

akatran
  • 1,057
  • 9
  • 15
  • 2
    Could you take a look at this question - http://stackoverflow.com/questions/39011587/jetty-files-outside-war-and-context – Pavel_K Aug 18 '16 at 06:48
3

I managed to achieve something similar by adding a mapping for the "css" directory in web.xml. Explicitly telling it to use DefaultServlet:

<servlet>
  <servlet-name>DefaultServlet</servlet-name>
  <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>DefaultServlet</servlet-name>
  <url-pattern>/css/*</url-pattern>
</servlet-mapping>
QaZ
  • 31
  • 2
2

This is Main.java file:

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;

public class Main
{
    public static void main(String[] args) throws Exception
    {
        Server server = new Server(8080);
        ResourceHandler resource_handler = new ResourceHandler();
        resource_handler.setResourceBase("C:/Users/serge.klimkovitch/Documents/images");
        HandlerList handlers = new HandlerList();
        handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });
        server.setHandler(handlers);
        server.start();
        server.join();
    }
}

=====================================

And this is gradle.build file:

apply plugin: 'java'
apply plugin: 'application'

mainClassName = 'SheetsQuickstart'
sourceCompatibility = 1.7
targetCompatibility = 1.7
version = '1.0'

repositories {
    mavenCentral()
}

dependencies {
compile group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.4.16.v20190411'

}

jar {
  manifest {
    attributes(
      'Main-Class': 'SheetsQuickstart'
    )
  }
  from {
    configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
  }
}

=====================================

Assuming that the following file exists: C:\Users\serge.klimkovitch\Documents\images\image.html

Then, run in Eclipse, and go to http://localhost:8080/image.html in your browser to see this file being served.

sklimkovitch
  • 251
  • 4
  • 8