1
votes

I have been searching without success in how to get an embedded jetty server to serve a handful of html files that are contained within the same jar. Surely this is possible?

I really don't want to go through the hassle of building and working with a war if I don't have to. Ideally I wouldn't have to create a WEB-INFO dir and a web.xml files either, though all solutions I've read seem to point to doing this and using a WebAppContext.

I've read the following links, but haven't found a way to set the ResourceBase or BaseResource property when running from a jar.

Start java application with jetty without WAR file

What is correct URL to specify ResourceBase of JAR "resources/webapp" folder for embedded Jetty?

Embedded Jetty looking for files inside its Jar file

Running through an IDE during DEV it was simple, the code worked and looked something like this..

Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(httpPort);
server.addConnector(connector);

ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.setWelcomeFiles(new String[]{"welcome.html"});
server.setHandler(context);

ServletHolder holderPwd = new ServletHolder("default", DefaultServlet.class);
holderPwd.setInitParameter("resourceBase","./Relative/Path/To/Html/Files");
holderPwd.setInitParameter("dirAllowed","true");
context.addServlet(holderPwd,"/");

server.start();
server.join();

So, do I have to use WebAppContext instead of ServletContextHandler? If yes, then do I have to add a webapp/WEB-INFO/web.xml directory structure too? And if I do that, then do I have to package as a war?

1
I don't see the setResourceBase call from the 3rd question; that should do it. Or you could just specify your own servlet implementation and use ClassLoader.getResource().Kenney
Kenny - I thought I was doing that via the following?. holderPwd.setInitParameter("resourceBase",...)user2952021
You're probably right. Have you tried passing something like this.class.getClassLoader().getResource("com/company/project/mywebdir").toExternalForm(); as the 2nd parameter? What results are you getting, 404?Kenney
Kenney, the externalForm() provides a path but it just results in 404s unfortunatelyuser2952021

1 Answers

10
votes

You need to set the Resource Base for the Context to the URL/URI to where your static content can be accessed from.

Note: you set this at the ServletContext level, not the DefaultServlet level, that way all servlets in your context have access to the same information and the various methods in ServletContext related to real file paths and resources are sane.

public static void main(String[] args) throws Exception
{
    Server server = new Server(8080);

    // Figure out what path to serve content from
    ClassLoader cl = MyEmbeddedJettyMain.class.getClassLoader();
    // We look for a file, as ClassLoader.getResource() is not
    // designed to look for directories (we resolve the directory later)
    URL f = cl.getResource("static-root/hello.html");
    if (f == null)
    {
        throw new RuntimeException("Unable to find resource directory");
    }

    // Resolve file to directory
    URI webRootUri = f.toURI().resolve("./").normalize();
    System.err.println("WebRoot is " + webRootUri);

    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath("/");
    context.setBaseResource(Resource.newResource(webRootUri));
    context.setWelcomeFiles(new String[]{"welcome.html"});

    ServletHolder holderPwd = new ServletHolder("default", DefaultServlet.class);
    holderPwd.setInitParameter("dirAllowed","true");
    context.addServlet(holderPwd,"/");

    server.setHandler(context);

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