0

I basically have the same issue as this question:

Setting Jetty resourcebase to static file embedded in the same jar file

where I am using embedded Jetty, and I want to access some static HTML files in the same JAR file.

Here is how the Jetty server is set up:


    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath("/");
    String res = ApiServer.class.getClassLoader().getResource("res").toExternalForm();
    context.setResourceBase(res);

    jettyServer = new Server(port);
    jettyServer.setHandler(context);

    ServletHolder jerseyServlet = context.addServlet(ServletContainer.class, "/*");
    jerseyServlet.setInitOrder(0);

    // Tells the Jersey Servlet which REST service/class to load.
    String classes = new StringJoiner(",")
            .add(MyClass1.class.getCanonicalName())
            .add(MyClass2.class.getCanonicalName())
            .toString();

    jerseyServlet.setInitParameter(ServerProperties.PROVIDER_CLASSNAMES, classes);

The folder structure of the JAR is like this:

root
  |  src (Java classes in here)
  |  res
      |  index.html

However it just doesn't work. I have tried to access the URL in various ways:

http://localhost:12345/res/index.html

or

http://localhost:12345/index.html

but neither works.

What am I doing wrong?

Joakim Erdfelt
  • 46,896
  • 7
  • 86
  • 136
Chin
  • 19,717
  • 37
  • 107
  • 164

1 Answers1

2

The code you have ...

String res = ApiServer.class.getClassLoader().getResource("res").toExternalForm();
context.setResourceBase(res);

Does not work for me, as you cannot use a classloader to obtain a directory reference, only file references. The call ClassLoader.getResource("res") always returns null.

This needs to be fixed first.

Next, your declaration of Jersey is exceedingly greedy.

ServletHolder jerseyServlet = context.addServlet(ServletContainer.class, "/*");
jerseyServlet.setInitOrder(0);

This means that Servlet (ServletContainer.class) is handling 100% of all requests, even requests for static content.

It is impossible for that Servlet, based on your url-pattern, to "not handle" static requests and let Jetty serve those static requests.

Relax this url-pattern, to say /api/* and then you'll be one step closer.

The final thing you need is a DefaultServlet (the component in the Servlet spec, and Jetty that serves static files).

So you'll wind up with the following code ...

ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
URL url = ApiServer.class.getClassLoader().getResource("res/index.html");
if (url == null)
   throw new FileNotFoundException("Whoops, can't find static resources folder");
URI webroot = url.toURI().resolve("./");
context.setBaseResource(Resource.newResource(webroot));

ServletHolder jerseyServlet = context.addServlet(ServletContainer.class, "/api/*");
jerseyServlet.setInitOrder(0);

// Tells the Jersey Servlet which REST service/class to load.
String classes = new StringJoiner(",")
        .add(MyClass1.class.getCanonicalName())
        .add(MyClass2.class.getCanonicalName())
        .toString();

jerseyServlet.setInitParameter(ServerProperties.PROVIDER_CLASSNAMES, classes);

// always named "default", always last, always on url-pattern "/"
ServletHolder defaultServ = new ServletHolder("default", DefaultServlet.class);
defaultServ.setInitParameter("dirAllowed","true");
context.addServlet(defaultServ,"/");

jettyServer = new Server(port);
jettyServer.setHandler(context);
Joakim Erdfelt
  • 46,896
  • 7
  • 86
  • 136