The Quick Way to a Java 8 Webserver Using Spark
Spark is a framework for making Java web apps for Java 8. Here's how to whip up a Java 8 webserver from Spark.
Join the DZone community and get the full member experience.
Join For FreeOne of the bigger criticisms of Java has always been regarding it’s verbosity; what would take one or two lines in C# or python would take 5 or 6 oftern convoluted statements in Java. In many ways Java 8 has been seen as the solution to this with the introduction of functional syntax allowing code to be condensed to a much cleaner, briefer form.
With little effort to upgrade code it has been simple to reduce complexity to a degree, but fundamentally most libraries are understandably still based in Java 7 or earlier and can be slow to take full advantage of the new features of the language.
This is why I was so excited when I heard about Spark, a framework for creating Java web apps built specifically for Java 8 and inspired by the Sinatra library in Ruby. Web Servers have always been a particular pain in Java for me, often being heavyweight containers like Tomcat or verbose libraries like Jetty. Take Hello World from the Jetty documentation for example:
public class HelloWorld extends AbstractHandler {
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
response.setContentType("text/html; charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("<h1>Hello World</h1>");
baseRequest.setHandled(true);
}
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
server.setHandler(new HelloWorld());
server.start();
server.join();
}
}
That’s a lot of code! Now check out the equivalent in Spark
public class HelloWorld {
public static void main(String[] args) {
get("/hello", (req, res) -> "Hello World");
}
}
Much cleaner. There’s no magic here; Spark is actually just an language abstraction over the top of Jetty so you can be comfortable knowing you’ve got a mature codebase under the bonnet.
I’ve found Spark to be invaluable in my day to day programming; Whether it be for quickly exposing some information from my application in a util page or knocking up a full web app, Spark allows me to very easily put together webpages with the minimum of fuss, particularly as it has support for a bunch of templating libraries, including handlebars, freemarker and thymeleaf.
A Slightly More Complex Example
A few months ago I created a basic Gist clone for use behind the great work firewall using Spark (full source at https://github.com/samberic/jist for those inclined). The main method, where all the handling is set up, is as simple as this:
private static Storage storage = new SqliteStorage();
public static void main(String[] args) throws SQLException {
storage.connect();
staticFileLocation("static");
post("/add", new AddJist(storage));
get("/jists/:id", new ServeJist(storage), new MustacheTemplateEngine());
get("/", new ServeJist(storage), new MustacheTemplateEngine());
}
To set up Spark to serve basic static files is as simple as telling them where they live: staticFileLocation(“static”). Easy peasy.
The following three lines are also self explanatory; the server will handle gets and posts at those URLS using the handlers names (e.g. ServeJist), and if present using the MustacheTemplateEngine. If you’re not using a template engine then your handler can directly return HTML.
Let's look at the handler for viewing prior Jists. The URL format for the getter is “/jists/:id”. This means that :id can be anything, and that we want access to it’s value as a variable. Let’s take a look at the handler for the request, ServeJist.
public class ServeJist implements TemplateViewRoute {
private Storage storage;
public ServeJist(Storage storage) {
this.storage = storage;
}
public ModelAndView handle(Request request, Response response) {
Optional<String> jistId = Optional.ofNullable(request.params(":id"));
final Map map = new HashMap();
jistId.ifPresent(id -> map.put("jist", storage.getJist(Integer.parseInt(id))));
map.put("isNewJist", !jistId.isPresent());
map.put("server", request.host());
return new ModelAndView(map, "jist.mustache");
}
}
TemplateViewRoute has the single method, handle, which returns a ModelAndView- the map of variables we want to smush with our template. We can pull the parameters out using request.params(“:theParamWeWant”). Unsuprisingly, Spark will also give you access to basically anything Jetty will; cookies, headers, uri etc. It’s a full powered Web Server that’s clean to write and easy to read.
This has only been a brief intro into the world of Spark and has hopefully peaked your interest enough to give it a go next time you need a web server. If there’s any specific tutorials you’d like to see then let me know in the comments.
Opinions expressed by DZone contributors are their own.
Comments