Executable WARs with Jetty

Executable WARs with Jetty

Today I want to talk about one of the younger members in the Eclipse family: Jetty. It is great to have such an interesting project on board and it is yet another example of how Eclipse has become more than just an IDE.

What I wanted to with jetty was to create an executable, standalone and self-contained WAR. I first encountered this concept in Hudson. The hudson.war contains an embedded Winstone servlet container, which makes it possible to run the application by executing

java -jar hudson.war

This makes test driving the application really simple. The idea was to do the same with Jetty. Embedding the Jetty runtime in the war proved to be the easy part, as it was just a matter of declaring the jetty dependencies in the maven pom.xml.

The tricky part was telling jetty where to find the war-file to serve. My first try was to hardcode the filename, but that left a foul aftertaste. Finding a solution took quite some time, which is why I am posting this for future reference. This is the Main-Class used to bootstrap Jetty (adapted from the Wicket quickstart archetype):

import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.bio.SocketConnector;
import org.mortbay.jetty.webapp.WebAppContext;

public class Start {

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

    // Set some timeout options to make debugging easier.
    connector.setMaxIdleTime(1000 * 60 * 60);
    connector.setSoLingerTime(-1);
    connector.setPort(8080);
    server.setConnectors(new Connector[] { connector });

    WebAppContext context = new WebAppContext();
    context.setServer(server);
    context.setContextPath("/");

    ProtectionDomain protectionDomain = Start.class.getProtectionDomain();
    URL location = protectionDomain.getCodeSource().getLocation();
    context.setWar(location.toExternalForm());

    server.addHandler(context);
    try {
      server.start();
      System.in.read();
      server.stop();
      server.join();
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(100);
    }
  }
}

The interesting bit is the getProtectionDomain()/getCodeSource() part, which tells us the location of the war-file. That’s all there is to it. Presto, executable web-application powered by Jetty in jar.

Edit: Added the import statements as per Tim’s suggestion.

18 Comments
  • Benjamin Muskalla
    Posted at 11:33 am, October 2, 2009

    Great stuff. Did you tried it with a RAP application yet?

  • sud
    Posted at 1:53 pm, October 2, 2009

    This is interesting. I’m curious to see what the same code would like for embedded glassfish. I remember seeing it somewhere and it may have been even simpler.

  • Posted at 7:37 pm, October 7, 2009

    Manuel, there is a WAR containing all the regular rap demos apps.

  • Joel
    Posted at 6:46 pm, October 8, 2009

    Thx for the info, I was looking to do the same thing. But i can’t make it runnable like hudson. When executing my war with “java -jar myWar.war”, I always get the following exception : Exception in thread “main” java.lang.NoClassDefFoundError: org/mortbay/jetty/Connector

    Could you tell me how you configured the manifest file so it worked?

    Currently, i setted my “Main” class in the root of the jar, just like hudson and configured the manifest to use it. But jetty’s jar is in WEB-INFlib unlike winstone in hudson that is in the root.

    I tried to set an explicit classpath in the manifest without any success.

    If you could provide the layout of your packaged WAR with the manifest you are using, it would really be appreciated.

  • Posted at 5:04 pm, October 12, 2009

    Hey Manuel,

    This is great stuff – although, you really need to include the import statements in your code snippet so people know where those classes are coming from as its not clear.

  • Fernnado
    Posted at 6:06 pm, October 14, 2009

    Maybe you should get this into the maven-jetty-plugin, as an option to publish an executable war file 🙂

  • Posted at 7:39 pm, December 17, 2009

    Thanks for the tip, probably saved me a lot of time 🙂

    Used your example as the base for a gradle script that takes a war and “jettyfies” it. Might be interesting to someone: http://bit.ly/standalone-war

  • Posted at 10:00 pm, January 12, 2011

    Thanks for the tip. I got inspired and did a proof of concept to build an executable war using maven, grails and jetty.
    Notes is available @ krishnadasari.blogspot.com

  • Posted at 12:06 am, March 31, 2011

    Note the executable-war-archetype , used as starting-point in the http://Mifos.org WAR, see http://goo.gl/nwZNE.

  • Frederik Heick
    Posted at 1:59 pm, April 29, 2011

    But how do you build it?
    What goal do you use and what dependencies is nessecary?

    Need a bit more info.

    So if I have Maven project which generates a war file.
    How do I make it executable with Jetty.?

  • Posted at 8:58 am, September 16, 2011

    And how do you get support for JSP?

    I get this: “NO JSP Support for /, did not find org.apache.jasper.servlet.JspServlet”

    I have no idea of how to pass in the option, like this: $ java -jar jetty.jar OPTIONS=Server,jsp from
    http://manolocarrasco.blogspot.com/2009/09/tip-enabling-jsp-support-in-jetty700.html

  • Paolo Milani
    Posted at 6:26 pm, February 12, 2012

    I was doing this myself, as I was also inspired by Hudson/Jenkins.
    It seems the only way to support loading via “java -jar” requires to put the main .class and its dependencies in the “root” of the WAR, as it needs to be found via “Main-Class” attribute in MANIFEST.MF.
    I can’t get over the fact that sorting out the package structure is hacky.

    If anybody knows a different solution, please share!

    Anyway, the getProtectionDomain() trick is pretty neat.

  • U Wieske
    Posted at 10:07 pm, February 27, 2012

    Paolo,

    I have the same thoughts as you, about the “hacky” part. Have you already found another alternative for the aforementioned solution?
    I keep on getting the same references to the “Start” example solution on Internet.

    I wonder…. can these alien resources (classes in the root of this webapp) be served as response of a HTTP request? ….. :-/

  • Paolo Milani
    Posted at 12:08 pm, February 28, 2012

    In short, I lost the WAR — but won the battle 😉
    The only benefit of packaging a WAR in such a configuration is to build a single artifact that supports 2 different environments.
    More precisely a WAR is a particularly structured package that is understood by a standard JEE servlet container.
    We don’t need to support a servlet container anymore as we are migrating this app out of a JBoss.
    In the case of running an embedded Jetty server, you can get away much more easily by creating a “uber-jar”.
    I used the maven-shade-plugin for that, I found it easier and more controllable than the assembly plugin or onejar.

    Hope this gives you some ideas,
    cheers