This guide is meant to be a resource for creating lightweight web servers in Java without a framework. You are expected to have Java and HTTP experience. It will cover the basics from a simple hello world server to a functional server side rendered website as well as a JSON web service. Along the way it will cover HTTP routing, verbs, query parameters, path parameters, headers, cookies, form data, json, logging and debugging techniques. Most topics will be split out into their own posts and this will serve as a directory / recommended reading order.

We will be using several libraries from our Recommended Java Libraries. If there are any topics missing you would like covered Suggest a topic. To see how dependencies are managed check out multi-project builds with gradle. This site is built with these exact same techniques and a lot of the shared classes.

Hello World

For the impatient let's get a minimal hello world up and running quickly. For whatever reason some developers like to see how few lines it takes to start a server. Let's see what that looks like.

public static void main(String[] args) {
            .addHttpListener(8080, "localhost")
            .setHandler((exchange) -> exchange.getResponseSender().send("hello world"))

If we really wanted this could be a one liner. You can also pass the HttpHandler into the addHttpListener method as a third argument. This is required if you want different handlers to run on different ports.


Why logging? Logging is a critical tool for understanding what is happening and extremely useful for debugging. It also happens to be overlooked quite frequently. When projects are several years old without proper logging you can't even compute the developer hours wasted debugging issues.

Undertow HttpHandlers

HttpHandler's are the building blocks of Undertow. They can be used to send responses, change status codes, log, meter / time, handle exceptions and much more. Undertow's simplicity is the main reason we use it. Try looking at mose frameworks and many of the concepts listed above have their own object models. Filtering / Interceptors often have strange APIs that only work before or after a request and you need to add both if you want to wrap a request. Exception handlers sometimes follow very different APIs and you don't have access to the same data you would expect. Undertow is simple. Most building blocks are simply HttpHandlers. Handlers are meant to be composed together. This allows you to use as little or as much functionality as you need. Does your web service have a special case where it is only a single route? Cut out the routing logic you don't need it!

Request Parameters

So far most of our handlers have been fairly static. We want some dynamic content, let's explore using out HTTP parameters.

Sending Responses

HTTP responses have some extremely crucial data. Status codes, content types, setting cookies, sending headers and much more. Often times large frameworks try to abstract this away from you by sending different Entity types back as the response. We are big boys here HTTP doesn't scare us.

JSON Web Service

We won't call it REST because we are not sticklers on naming / conventions. We use Jackson for all JSON serialization.

Server Side HTML with Handlebars

SPAs are all the rage these days. However you can't beat the complicity and speed of building server side rendered web apps (Especially if you are a server side developer and aren't a js guru). SPAs make sense in a lot of use cases. However, they don't make sense in all cases. There is nothing wrong with going back to our roots.