We’ve been running on Jetty for the last couple of years now. About a year ago we moved from deploying our warfiles to deploying executable jars (überjars). Here’s an updated recipe for creating your Jetty executables with Jetty7@Eclipse and Maven.
Last year Johannes Brodwall wrote an excellent blog post on the why and hows of using Jetty in production, I really recommend that post as a good background reading.
The aim is of course to be able to start your application like:
:➜ java -jar webapp.jar
Stop it like
:➜ java -jar webapp.jar stop or
:➜ kill <pid-of-webapp>
This approach integrates very well into how Unix-based operating systems handle dæmons, and makes it a lot easier to maintain for operations.
TL;DR? Fork the code at GitHub: https://github.com/bekkopen/jetty-pkg
After reading the aforementioned blogpost, I started using the one-jar-plugin, and this worked somewhat all right for over a year with continuous deployments of different apps and systems. However, there are numerous of smaller issues with one-jar, such as coughs when being built from a modularized project, or being built from another root and other unmavenesque behaviour. Jetty 7@Eclipse has been stable for a good while, and comes with a number of improvements and changes, so last week I decided to rewrite our embedded container with Jetty 7 and maven-shade-plugin. Although Jetty 7 comes with a separate start.jar and is fairly simple to configure using properties and/or Jetty’s XML configuration files, I still prefer writing my own (coded) version.
Surprisingly I could not find a recent blog-post about it (I might not have looked too hard), so without (much) further ado here is my simple recipe:
We usually use Maven to build our Java-projects. To create the executable jar, what I do first is to create a simple Maven project, and use some plugin to merge our webapp war-file and other dependencies together with our Jetty launcher. I like using the standard maven-plugins as long as they exist. Both the maven-shade-plugin and the maven-assembly-plugin are able to merge dependencies (quite similarly).
Next we need to execute Jetty, here is my current take on this (slightly simplified):
The small nugget I’ve included here is the BigIPNodeHandler example. Several large enterprises I’ve worked with utilize F5 BigIP Hardware Load Balancers in front of their application servers. Big IP comes with several nice features, one of them is a very simple, yet very well functioning graceful completion of (sticky) sessions. This enables us to redeploy with zero downtime and the customers will (hopefully) never get a hiccup, be stopped in a workflow or loose a transaction during their use of the systems. In essence the BigIP implementation of this function works like this:
With URL: appserver:port/node.txt
- if status is 2xx, and response contains text ‘offline’; mark as maintenance, do not accept new sessions, but allow active sessions to complete.
- if status is 200 OK and response contains ‘online’; full throttle.
- if status is no response or other than 2xx; full break.
When we deploy a new version we start off marking node(s) offline, poll active sessions directly from the BigIP instance, and first once the session count has reached zero, we commence the deployment of our new version.
Example BigIPNodeHandler (see the GitHub repo for the working implementation):
Again; To see a fully working example and get you started, Fork the code at GitHub.
EDIT: Corrected last GIST.