1

Is it possible to store static resources inside the uber jar created with an embedded jetty server project? I created this simple project based on an answer by @JoakimErdfelt Serving static files from alternate path in embedded Jetty. I kept the default-servlet to serve the static content, but I switched the dynamic-servlet for a restful jersey-servlet and it works great as long as the jar is in the same directory as the index.html. I would like to be able to embed the index.html file inside the jar but when I issue "mvn clean install" the webapp directory doesn't appear in the jar that's built. I think the pom.xml needs an entry but I don't know what it is and I think the jetty.java needs to change to find the index.html inside the embedded webapp directory. Here is the current directory structure.

static-rest\src\main\java\org\rest\jetty.java

static-rest\src\main\java\org\rest\rest.java

static-rest\src\main\java\webapp\index.html

static-rest\pom.xml

jetty.java

package org.rest;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

public class Jetty {
    public static void main(String[] args) throws Exception {

        System.setProperty("org.eclipse.jetty.LEVEL","INFO");

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

        // Setup the basic appliation "context" for this application at "/"
        // This is also known as the handler tree (in jetty speak)
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");
        server.setHandler(context);

        // The filesystem paths we will map
        String homePath = System.getProperty("user.home");
        String pwdPath = System.getProperty("user.dir");

        // add a simple Servlet at "dynamic/*"
        ServletHolder holderDynamic = new ServletHolder(
            "dynamic", org.glassfish.jersey.servlet.ServletContainer.class);
        context.addServlet(holderDynamic, "/dynamic/*");

        holderDynamic.setInitOrder(0);

        // Tells the Jersey Servlet which REST service/class to load.
        holderDynamic.setInitParameter(
           "jersey.config.server.provider.classnames",
           Rest.class.getCanonicalName());

        // add special pathspec of "/home/" content mapped to the homePath
        ServletHolder holderHome = new ServletHolder(
            "static-home", DefaultServlet.class);
        holderHome.setInitParameter("resourceBase",homePath);
        holderHome.setInitParameter("dirAllowed","true");
        holderHome.setInitParameter("pathInfoOnly","true");
        context.addServlet(holderHome,"/home/*");

        // Lastly, the default servlet for root content (always needed, to satisfy servlet spec)
        // It is important that this is last.
        ServletHolder holderPwd = new ServletHolder(
            "default", DefaultServlet.class);
        holderPwd.setInitParameter("resourceBase",pwdPath);
        holderPwd.setInitParameter("dirAllowed","true");
        context.addServlet(holderPwd,"/");

        try
        {
            server.start();
            server.dump(System.err);
            server.join();
        }
        catch (Throwable t)
        {
            t.printStackTrace(System.err);
        }
    }
}

rest.java

package org.rest;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

    @Path("/rest")
public class Rest {

    @GET
    @Path("/{msg}")
    @Produces(MediaType.TEXT_PLAIN)
    public String echo(@PathParam("msg") String msg) {
        return "echo: " + msg;
    }
}

index.html

<html>
<body>
<p>Send Restful Request Demo</p>
<input type="text" id="myText" value="message">
<button onclick="myFunction()">Send</button>
<p id="demo"></p>
<script>
function myFunction() {
  var msg = document.getElementById("myText").value;
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.onreadystatechange = function(){
    if (xmlhttp.readyState==4 && xmlhttp.status==200){
      document.getElementById("demo").innerHTML=xmlhttp.responseText;
    }
  }
  xmlhttp.open("GET", "http://localhost:8080/dynamic/rest/" + msg, true);
  xmlhttp.send();
}
</script>
</body>
</html>

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.games.solitaire</groupId>
  <artifactId>static-rest</artifactId>
  <packaging>jar</packaging>
  <version>0.1-SNAPSHOT</version>
  <name>static-rest</name>
  <url>http://maven.apache.org</url>
  <dependencies>
     <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-server</artifactId>
      <version>9.2.3.v20140905</version>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-servlet</artifactId>
      <version>9.2.3.v20140905</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.core</groupId>
      <artifactId>jersey-server</artifactId>
      <version>2.7</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.containers</groupId>
      <artifactId>jersey-container-servlet-core</artifactId>
      <version>2.7</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.containers</groupId>
      <artifactId>jersey-container-jetty-http</artifactId>
      <version>2.7</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.media</groupId>
      <artifactId>jersey-media-moxy</artifactId>
      <version>2.7</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>1.6</version>
        <configuration>
          <createDependencyReducedPom>true</createDependencyReducedPom>
          <filters>
            <filter>
              <artifact>*:*</artifact>
              <excludes>
                <exclude>META-INF/*.SF</exclude>
                <exclude>META-INF/*.DSA</exclude>
                <exclude>META-INF/*.RSA</exclude>
              </excludes>
            </filter>
          </filters>
        </configuration>

        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer
                  implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                <transformer
                  implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <manifestEntries>
                    <Main-Class>org.rest.Jetty</Main-Class>
                  </manifestEntries>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>
Community
  • 1
  • 1
shirha
  • 305
  • 2
  • 9

0 Answers0