How to create a simple HTTP server in Java - with Undertow
Icon by Smashicons from www.flaticon.com
Sometimes, we all just need something really simple.
A simple breakfast. A simple supper. Or perhaps, a simple Java web server demo.
To do this, you could use something like Spring Boot or Quarkus.
But these frameworks require a little bit of knowledge upfront, and they add a lot of layers of complexity and overhead, for something that can really be very simple.
So in this tutorial, I’ll show you how to create a standalone Java application with a main
method, which uses the Undertow web server to serve a simple “Hello, world!” message over HTTP.
You’ll create a simple, standalone command-line Java application, which is packaged as a self-contained, nicely-portable, executable JAR.
Why though?
But first - why? Where would you use this?
I created this little setup to scratch my own itch. Quite often, I need a very simple example Java application to use as part of a demo.
Sometimes, I’m writing CI/CD pipelines and I need to have a demo app that I can run through the pipeline to check that it works.
Or sometimes, I’m teaching about containers and I want a simple application that students can use and play with.
Here are some other reasons why you might use something like this:
-
To run a minimal web server in Java, which returns a static web page
-
To have an example Java app that you can use as part of something else: like a CI/CD pipeline, or perhaps to package into a Docker image and deploy to Kubernetes
-
To see how to write a standalone Java application without having to use a framework like Spring Boot or Quarkus (yes, it’s possible!)
-
How small you can go…. this produces a self-contained (fat-jar) application that packages super-small - less than 3MB! (well, small by Java standards :))
Prerequisites
In this example we’ll use:
-
Java 8+: You’ll need to be running Java 8 or higher, because this example uses lambda syntax. So make sure you have a JDK installed.
-
Maven: We’ll use Maven as the build tool, so make sure Maven is installed.
-
Undertow: This is an embedded web server for Java. We’ll add Undertow to the project and use it to serve a simple HTML page. You don’t need to download it, as Maven will pull it in during the build.
What is Undertow?
Undertow is an alternative to other embedded web servers like Tomcat or Jetty.
Creating the project
This tutorial has just 2 files, the pom.xml
and the Application
class.
Your project tree should look something like this when finished:
.
├── pom.xml
└── src
└── main
└── java
└── com
└── tutorialworks
└── demos
└── hellorestjava
└── Application.java
Set up pom.xml
We need to set up Maven first. So we create a pom.xml
in the root. This will contain all of the dependencies that we need. Inside the pom.xml
:
-
Add the
io.undertow:undertow-core
dependency to yourpom.xml
. -
Configure the
maven-assembly-plugin
to build ajar-with-dependencies
– this tells Maven to build our “fat-jar” artifact. You also need to tell the Assembly Plugin themainClass
which will boot your application.
Your pom.xml
should look something like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tutorialworks.demos</groupId>
<artifactId>hello-java</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>Hello Java</name>
<description>An extremely simple web service that returns Hello World!</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<undertow.version>2.0.27.Final</undertow.version>
</properties>
<dependencies>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
<version>${undertow.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>com.tutorialworks.hellorestjava.Application</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Set up Application.java
Next we need to add the main code. Since this is a simple, standalone Java application, we’re going to create a main class – that is, a class with a public static void main()
method, which will be the entry point to our program.
-
You can create your
Application.java
in any package you like, but in this example I’ve located it atsrc/main/java/com/tutorialworks/demos/hellorestjava/Application.java
-
In the
main
method, import packages fromio.undertow
and create an instance ofUndertow
. We use thebuilder()
to configure the host and port that the web server will listen on, and the payload that it should return.
Your code should look something like this:
package com.tutorialworks.demos.hellorestjava;
import io.undertow.Undertow;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.Headers;
/**
* Hello world!
* Returns a simple web page on port 8080.
*/
public class Application {
public static void main(String[] args) {
Undertow server = Undertow.builder()
// Set up the listener - you can change the port/host here
.addHttpListener(8080, "0.0.0.0")
.setHandler(exchange -> {
// Sets the return Content-Type to text/html
exchange.getResponseHeaders()
.put(Headers.CONTENT_TYPE, "text/html");
// Returns a hard-coded HTML document
exchange.getResponseSender()
.send("<html>" +
"<body>" +
"<h1>Hello, world!</h1>" +
"</body>" +
"</html>");
}).build();
// Boot the web server
server.start();
}
}
Compile and run
Now, to compile the application:
mvn clean package
What does this build?
This will build a “fat-jar” (a JAR containing your application, and all of its dependencies) inside the target/
folder:
$ ll target/hello-java-1.0.0-SNAPSHOT.jar
-rw-r--r--. 1 tdonohue tdonohue 2.8M Dec 8 08:37 target/hello-java-1.0.0-SNAPSHOT.jar
As you can see, the final jar on my laptop was only 2.8Mb!
And now to run the application, just run java -jar
with the relative path to the packaged JAR file:
java -jar target/hello-java-1.0.0-SNAPSHOT.jar
Undertow should now be running on port 8080. You can use a web browser to go to http://localhost:8080 to see the output rendered as a web page, or you can use a command-line HTTP client, like curl
, to fetch the web page:
$ curl http://localhost:8080
<html><body><h1>Hello, world!</h1></body></html>
To quit, just press Ctrl+C.
Summary
There you have it! We’ve created a simple Java application with an embedded web server, Undertow. The web server returns a simple web page that says “hello world”, ideal for your next demo or simple application to test.
Happy coding!