Jetty ResourceHandler in multi project gradle build looks in the wrong directory

321 views Asked by At

I have a multi project build using Gradle in the form:

project1
--build.gradle
--settings.gradle
project2
--src
----main
------java
--------LocalJettyRunner.java
------webapp
--------static
----------index.html

When I run my LocalJettyRunner and load localhost:8135 I get a 404 when I am expecting my ResourceHandler to return my Index.html. I have debugged the ResourceHandler.handle(...) method it appears to be looking in my project1/static directory which obviously doesn't exist. What am I doing wrong?


LocalJettyRunner

public class LocalJettyRunner {}

    public void start() throws Exception {
        log.info("Starting api");

        ResourceHandler webHandler = new ResourceHandler();
        webHandler.setDirectoriesListed(true);
        webHandler.setResourceBase("static/");
        webHandler.setWelcomeFiles(new String[]{"index.html"});

        HandlerCollection handlers = new HandlerCollection();
        handlers.addHandler(webHandler);

        Server server = new Server(8135);
        server.setHandler(handlers);
        server.start();
    }

    public static void main(String[] args) throws Exception {
        new LocalJettyRunner().start();
    }
}
2

There are 2 answers

2
Joakim Erdfelt On BEST ANSWER

ResourceBase is an absolute path and/or URL to an absolute path.

The fact that it works without an absolute path is because of how the new File(String).toAbsolutePath() works.

Try looking up a resource that you know is in the ResourceBase, via the ClassPath, and then using the URL reference to set an absolute path.

Example:

Assuming you have a src/main/resources/webroot/, with your static content in it (such as index.html), then you can resolve it first, then pass it into the base resource.

package jetty.resource;

import java.net.URI;
import java.net.URL;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.util.resource.Resource;

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

        // Figure out what path to serve content from
        ClassLoader cl = ResourceHandlerExample.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("webroot/index.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);

        ResourceHandler handler = new ResourceHandler();
        handler.setBaseResource(Resource.newResource(webRootUri));

        server.setHandler(handler);

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

Incidentally, you have a src/main/webapp/ which tends to indicate a proper webapp / war file for Maven. For a full blown webapp, it might be easier to skip ResourceHandler and just use WebAppContext directly (it wires everything up, and does not use ResourceHandler, but rather DefaultServlet, which is better all around for serving static files)

0
Eduardo On

Setting the ResourceBase to "../project2/src/main/webapp/static" seems to fix it although I'm not sure why the handler is looking in project1 to begin with.