Sun’s secret web server
For a while now I’d been looking for something to just run up an HTTP server to answer simple queries.
The Java Servlet APIs are comprehensive, and there are a number of very good implementations (we use Resin in highly loaded environments and it scales like a dream; we recommend it heartily to our clients). Nevertheless, sometimes you’re working on something small or ad-hoc, and you just want a simple web server that doesn’t involve application descriptors, XML, configuring an entire service instance, and everything else. Somewhat to everyone’s long standing annoyance (not to mention the derision of people who work in other languages), there is nothing in the Java standard library to just get on with this.
In their release of Java 1.6, however, Sun quietly included such a server. Apparently it had been around for some time powering internals of various other projects, but in 1.6 they exposed it as a public library, in package com.sun.net.httpserver, and it ships alongside the rest of their Java VM and standard library.
It’s got a rather nice API. You fire up a server and add one or more handlers:
addr = new InetSocketAddress("localhost", 8000);
server = HttpServer.create(addr, 10);
server.createContext("/eg", new ExampleHandler());
server.start();
the “contexts” are paths from root that are handled by different HttpHandler instances; implementing that interface is simply:
public void handle(HttpExchange t) throws IOException {
...
}
Once there, you’ve got a number of really straight forward methods on HttpHandler to get done what needs doing:
t.getProtocol();
t.getRequestMethod();
t.getRequestURI();
t.getRequestHeaders();
t.sendResponseHeaders(code, length);
for the metadata, and an InputStream and an OutputStream from:
t.getRequestBody();
t.getResponseBody();
respectively. You write the response to the later. Too easy. I did up a modified version of the example they have in the package description file as something that echos back the HTTP request as the response and it was quite straight forward. Java programmers can glance at EchoServer.java if they’re interested.
The catch
Nothing is ever simple. The bytecode for the com.sun.net.httpserver package is bundled in with the rt.jar that comprises the bulk of the standard library, but for whatever reason they didn’t include the JavaDoc for these classes in the same tree as the rest of the API documentation.¹ This is a huge pain, because once you’ve told Eclipse where to look for the docs for a given blob (in this case, for rt.jar) you can’t then tell it to look somewhere else for a sub part. And if you’re trying to develop something in a beautiful IDE like Eclipse, the idea of not having inline popup documentation and completion working properly is just a non-starter.
You can point Eclipse at either a JavaDoc tree, or at the raw sources and it’ll just extract the documentation on the fly. But since the src.zip shipping with Sun’s proprietary Java 1.6 didn’t include the classes for this web server code, that didn’t work either.
So that would have been the writing on the wall for Sun’s httpserver.
Open Java to the rescue
After chatting with some people in #gentoo-java and #classpath, we suddenly realized that the solution was at hand. Source code to Open Java is available.² And even though it’s still not yet a fully Libre replacement for Sun’s proprietary Java 1.6 (the size of the binary proprietary plugs you have to drop into it to make it work is staggering), it does contain most of the sources to the Java standard library. So we grabbed a copy of the openjdk 1.6 b08 code drop, and just pointed Eclipse at it as the sources for rt.jar for cases where it couldn’t find the JavaDoc when it was looking something up. And ta-da!
So, amidst considerable astonishment but great pleasure, here was an example of something someone had Open Sourced working in a synergistic way but in a way that they hadn’t quite expected. This wouldn’t have worked if Sun hadn’t Open Sourced (most of) Java; but because they have we were able to use those sources to solve a problem. Thanks to the heroes at Sun Microsystems who made this possible!
Eclipse users will have to adjust their filters so that com.sun.* isn’t excluded from Type completions and what not; While we’ve all loved our com.sun.* excludes, it blots out com.sun.net.httpserver. If you plan on using it, then I suggest switching to excluding com.sun.org.* and com.sun.xml.*, etc. A pain, but that’s what we get for Sun not having put this into the standard library.
Speaking of which, I doubt we’ll ever see this as a part of the “Java” (wouldn’t java.net.httpserver just do the trick?) because the marketing side of Sun has a fairly strong fixation on “Servlets are what you use for everything”. Oh well. It would be a really pleasant surprise, though. Here’s hoping.
But not really
We would never use this in something we were distributing to anyone outside; after all, they might be using some other VM and com.sun.net.httpserver isn’t available as a standalone library. And that’s not to mention scalability; if you need something bulletproof then use the Resin servlet runner. But if you need a quick-and-dirty but easy-to-use HTTP server and you happen to have Sun Java or the future tense Open Java available, then this should do the trick for you. And if you’re feeling like whipping up something of your own, this really does have a nice API (somewhat a rarity in the Java landscape) and so this might be a good starting point for you. Either way, have a look.
AfC
¹ As mentioned, the API docs for com.net.sun.httpserver are not in the usual location at docs/api/ along with the rest of the standard library but at docs/jre/api/net/httpserver/spec/ of all places. Who knows what they were smoking that day.
² I am very tired of apologizing to people who have just installed “Java” on their Linux boxes that they have to download something else. I’ve given up trying to explain the difference between a JRE and a JDK to people; even after I do people respond with “who cares; I just want a working Java that I can use to build your software.” Sun having attempted to brand their Libre implementation of Java as “Open JDK” just perpetuates this nonsense. Not including the compiler classes in something that is already 18 MB big is stupid, and it’s not like the desktop VM is what you use on a resource limited embedded device. Open Java works just fine as a name, thank you very much, and it is (almost) a Free Java. Almost.
