12

We want a simple embedded Jetty servelet with the web resources inside a JAR-file's resources folder. We have some properties files in the JAR and load them using a resources path. We want to specify the Jetty Resource Base to be:

  • resources/webapp
  • set: resource_handler.setResourceBase( "webapp" )
    • Via the correct URL to point to that resource in the JAR file.

Folder in the JAR file. This is a bare bones JAR file (not WAR, no frameworks, without Spring, as vanilla as we may). Initial tests continue to throw exceptions for something like the following strings:

webPath = "jar:file:!/webapp";     //.... runs the Jetty server 
 ... 
resource_handler.setResourceBase( webPath );

Although the server seems to run, the result fails to find my index.html. (Update:) This example is just taking from the Jetty "Embedded File Server" example. In this case, the requirement is for the Jetty Resource Base to map to the JAR file (full-URL):

  • "jar:file:!/webapp/index.html",

as follows:

  • resource_handler.setResourceBase("jar:file:!/webapp");

Instead of the example given:

  • resource_handler.setResourceBase(".");

And we want this to map the browser URL as:

  • localhost:8080/index.html
    • ... giving ...
  • jar:file:!/webapp/index.html

For contrast the JAR path that work for config files below. The question: what should the URL be so Jetty resource base can serve-up my Index.html file?

  • resources/
    • config/
      • display.properties

file is: "/config/display.properties" and this works in the same project code using a load resources operation. The layout is like this:

 app.jar
   +----- com /
   |        +--- ( classes ... )
   |
   +----- config /
   |        |
   |        +--- display.properties
   |
   +----- webapp /
            |
            +--- index.html

To give the general idea.

similar questions:

Community
  • 1
  • 1
will
  • 4,799
  • 8
  • 54
  • 90
  • `http://localhost:8080/index.html`? When jar runs. – Joop Eggen Aug 06 '14 at 07:49
  • Sorry, no. The question is about the appropriate JAR file URL to bind to Jetty's **ResourceBase**. Even with, "jar:file:!/webapp", the embedded server does NOT find the: "http://localhost:8080/index.html" resource. Reason: "**Not Found**" – will Aug 06 '14 at 10:09
  • Sorry too. `resource_handler.setResourceBase(this.class.getClassLoader().getResource("/webapp").toExternalForm());` See http://docs.codehaus.org/display/JETTY/Embedding+Jetty – Joop Eggen Aug 06 '14 at 10:33
  • Thank you, yes we used that, this gives a **null** because there is no file-path to: "/webapp". The correct Java URL for the JAR is as explained in: [JarUrlConnection](http://docs.oracle.com/javase/7/docs/api/index.html?java/net/JarURLConnection.html). That is: "_jar:file:!/webapp_". The challenge is that this Resource Base can't resolve the browser input-URL: "localhost:8080/index.html" to map to: "**jar:file:!/webapp/index.html**" in the [JAR file](http://docs.oracle.com/javase/7/docs/api/index.html?java/net/JarURLConnection.html) – will Aug 06 '14 at 10:53
  • That looks like default functionality. Did you try a demo sample project, before checking where your project differs? Sorry no time now. – Joop Eggen Aug 06 '14 at 11:23

2 Answers2

10

I have a working solution - Work-around that I'm posting in the hope that this approach will inspire correct method. I still believe there ought to be a way to specify a folder inside the JAR, relative to the JAR.

Anyway this method works. I used it to server static web content from within the JAR. Essentially I have Java resolve the absolute path to the running JAR resource and pass that path name to Jetty. When I do that Jetty displays my "helloWorld.html", welcome file.

    String  baseStr  = "/webapp";  //... contains: helloWorld.html, login.html, etc. and folder: other/xxx.html
    URL     baseUrl  = SplitFileServerRunner.class.getResource( baseStr ); 
    String  basePath = baseUrl.toExternalForm();

      .... 
    resource_handler.setDirectoriesListed(true);      //... just for testing
    resource_handler.setWelcomeFiles(new String[]{ "helloWorld.html" });
    resource_handler.setResourceBase( basePath );
    LOG.info("serving: " + resource_handler.getBaseResource());

In the welcome file, I have put specific text to identify the file's origin (in the resources folder). In the browser:

  • localhost:8080

Serves the helloWorld.html file.

  • localhost:8080/other

Shows a directory listing of the jar:/webapp/other/ directory inside the JAR file. This relies on not changing the JAR while the server is running.

On Linux if someone cp-s a new jarfile on-top of the running JAR, Jetty gives:

 HTTP ERROR: 500

 Problem accessing /. Reason:

        java.lang.NullPointerException

And you can't access pages any more. That was unexpected (evidently the JAR is kept open). The good news is that if you mv-s the jarfile:

  • mv fileserver.jar fileserverXX.jar

Jetty happily continues serving from the (renamed) fileserverXX.jar content. I can be happy with that. However I'd still like to know the equivalent relative path to match the absolute file name.

will
  • 4,799
  • 8
  • 54
  • 90
  • I had hoped someone would come along with an alternative solution by now (6 months later). Let's call it answered and move along. I believe this is a relevant requirement for the new Java (9??) packaging container -- But the requirement would need to be more general purpose. – will Mar 25 '15 at 12:19
  • 1
    ... and this method still works in 2022 :) – gaborsch May 04 '22 at 17:29
0

Some methods changed since the original answer so the following works the same way but with Jetty's version: 9.4.12.v20180830:

ServletContextHandler webappContext = new ServletContextHandler(ServletContextHandler.SESSIONS);  
URL webRootLocation = JettyStart.class.getResource("/webapp/index.html");  
URI webRootUri = URI.create(webRootLocation.toURI().toASCIIString().replaceFirst("/index.html$", "/"));  
webappContext.setContextPath("/");
webappContext.setBaseResource(Resource.newResource(webRootUri));
webappContext.setWelcomeFiles(new String[] { "index.html" });
Oliver
  • 1,218
  • 1
  • 17
  • 21
  • 1
    I see, yes. Actually for full disclosure a method that uses the `...getResource("/webapp/index.html")` method _ought_ to more correctly be considering the Class Loader that relates to the required resource URI. Packages like Jetty often use their own class loader(s). – will Jul 01 '19 at 02:55