Introducing Winstone, an ultra-lightweight alternative to Tomcat and Jetty
Recently, my frustration with Tomcat and Jetty set me off Googling for possible alternatives. After some searching, I came across a relatively new open-source servlet engine called Winstone. I think this server may well be a great replacement for both Tomcat and Jetty, at the very least as a development tool. Before I delve in to more detail on Winstone, let me share a little background on Java servlet engines, and my particular issues with Tomcat and Jetty.
1. Brief History of Java Servlet Engines
Websites built on Java technology require not just a web server, but also a servlet engine to invoke and run the Java code that renders the site’s front end (“servlets”). Java websites sometimes also require a full stack of services beyond basic page rendering (messaging, state management, resource directories, etc.), in which case a fully stacked application server is needed, but the core of all Java websites is the servlet engine. The early days of Java Web development in the late 90s and early 2000s was built on servlet engine offerings from large enterprise vendors like IBM, WebLogic and Sun (both now Oracle). However, in the last five years or so, an open-source alternative to these products emerged in the form of Apache Tomcat. Tomcat is now on version 7 and it’s fair to say it has been a massive success in terms of both developer mind share and large-scale enterprise deployments.
2. The Problems with Tomcat
Tomcat’s strength lies in its maturity (road-tested by thousands of IT shops) and its simplicity. The Tomcat installation consists of a handful of XML configuration files, and a library of open-source code. It also has evolved over time to support the most common web development requirements such as Apache/IIS integration, HTTPS support, single sign-on, and clustering. However, Web development has evolved at a greater rate than Tomcat has, and the role of the servlet engine has been much reduced in Java Web code written today. Modern Web development not only relies more heavily on client-side scripting, but even on the back-end, servlets are often relegated to mere ‘controller’ roles—routing requests to HTML-templating engines (Freemarker, Velocity) or component-rendering engines (GWT, Wicket) rather than processing the requests themselves and rendering a response. The sum of this evolution is that the legacy lynchpin of Java Web development, the Java Server Page, has been marginalized, and as a consequence so has the role of the servlet engine. What Java Web developers require now is a servlet engine that acts a service within the application purely to process servlet request/response cycles and little else (much like a database service or a logging service within an application, each provides a single purpose). Increasingly, the servlet engine is no longer the all-encompassing runtime framework of Java-based websites. Ideally, it’s ‘just’ a cohesive and modular component of the application runtime. It’s singular, but essential, responsibility is to parse HTTP requests and route them to the appropriate sub-service.
Put simply, what this means for Tomcat is that it’s starting to look like a pretty bloated stack. Developers no longer require a servlet engine that provides logging, naming/directory services, connection pooling, a security container, etc. In fact, they are now keen to embed the servlet engine in their own applications (directly, or via OSGI) just to provide a servlet handler. In this regard, Tomcat is overkill. It even weighs down development time with its large-memory footprint, both in terms of the JVM and the actual file system. Is there an alternative? Increasingly, judging from my own discussions with colleagues and discussions like this at stackoverflow.com, Java web developers have been turning to an open-source server called Jetty.
3. Jetty Has a Steep Learning Curve
Jetty is an elegantly designed servlet engine with a modular architecture that lends itself to both simple and sophisticated use cases. It also has a smaller footprint than Tomcat, and has a reputation for being faster at both page rendering and general server processing. Indeed, it definitely seems to bootstrap/redeploy much faster than Tomcat in my ad hoc testing (my current Tomcat development instance takes four seconds to bootstrap itself or redeploy a webapp, and this is with much redundant configuration removed). Jetty is also vastly easier to embed in your application than Tomcat, requiring about six lines of code, instead of the 15 or so needed to get Tomcat setup in your application as a singleton service. However, after a week or so of trying to use Jetty (v7) in a variety of use cases, I felt I spent a lot of time chasing my tail. Here are my main gripes with Jetty:
- Poor documentation, often missing or incomplete.
- Confusing product ownership, with the original developers Mortbay passing it over to the Eclipse organization between releases 6 and 7. A lot of features and functionality straddle these two releases and its can be very confusing to figure out which to use.
- The modular, expandable nature of Jetty means that its a composite of many library files and many XML configuration files. This is architecturally elegant, but makes basic configuration points difficult to track down
4. Introducing Winstone
Winstone is at version 0.9, and available here. It has simple but complete documentation at that site, and the whole server is contained in just one small JAR file download with a shallow dependency graph. Compare this with the multitude of JAR files required to run Tomcat and/or Jetty, even in simple embedded mode. It gets better; to run your Java web application(s) with Winstone, you simply invoke the Winstone JAR file from the command line, passing in the location of your webapp(s) exploded directory or JAR file as a parameter. Here is an example:
java -jar winstone.jar --webroot [your-exploded-war-base-directory-or-war-file-location]
Following convention, Winstone will run at port 8080 by default (you can override this by passing in your preferred port number as a run-time variable). In line with the current vogue to bypass JSP development altogether, Winstone ships with JSP support disabled, but this (and a myriad other settings you might want to use) can be toggled by using a simple local key-value pair properties file. This is all clearly documented at the project site. Additionally, if you’re a Maven user, you can simply include Winstone in your project using this pom declaration:
<dependency>
<groupId>net.sourceforge.winstone</groupId>
<artifactId>winstone</artifactId>
<version>0.9.10</version>
</dependency>
My favorite feature of Winstone is the ease at which it can be embedded in to your application. You may want to do this to give your application a web server front end and/or servlet engine, or embed a server in your test scripts. Either way, you can do this in just four lines of code:
Map config = new HashMap();
config.put(“webroot”, “webapps/my-killer-app/”);
Launcher.initLogger(config);
Launcher winstone = new Launcher(config);
I have yet to test Winstone in a production setting, or anything other than my development laptop, but I am sold on it as a development tool at the very least. In addition to the base settings it ships with, it has these keys capabilities, which suggest it will fit a wide range of needs beyond pure servlet compilation:
- HTTPS support
- JAAS support
- Apache/JK support
- Cluster support
- Hot-redeploy of servlet classes
- JNDI support
- HTTP control ports provided for starting/stopping the server remotely
Winstone seems to be the work of a sole developer, Rick Knowles, but I have found him to be very responsive to my email queries. Responsiveness aside, there’s always some risk with single-developer projects lacking group oversight, which is that the project will apathy if the developer decides to move on.
I am keen to see how Winstone performs as I expand my use of it, and I look forward to benchmarking its performance on a production-grade machine. For now, I am very happy to have found such a lightweight and user-friendly servlet engine for my development needs. I am also eager to hear from developers who have or want to use Winstone in their projects, so please feel free to comment on this post.
