In this tutorial we will discuss about Undertow Web server which is the new Web server implementation for WildFly application server.
Undertow Web server is a fast and light Java Web server based on non-blocking IO. It consists of a few different parts:
- A core HTTP server that supports both blocking and non-blocking IO
- A Servlet 3.1 implementation
- A JSR-356 compliant web socket implementation
As part of WildFly application server, it is packaged as extension in a file named “wildfly-undertow-8.0.0.Final.jar” that is referenced in the main Web server configuration with the name “org.wildfly.extension.undertow”. Although we can use it as part of the application server, we can also embed it in our applications with a few simple lines of code. We will demonstrate in this tutorial how to do it.
First of all, start by creating a new Maven quickstart project that is just able to run Java applications:
mvn archetype:generate -DgroupId=com.mastertheboss.undertow -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false -DartifactId=undertow-server
Now let’s pickup the basic HelloWorld example from the documentation and let’s past it in our project:
import io.undertow.Undertow; import io.undertow.server.*; import io.undertow.util.Headers; /** * Hello world! * */ public class App { public static void main(final String[] args) { Undertow server = Undertow.builder().addHttpListener(8080, "localhost") .setHandler(new HttpHandler() { public void handleRequest(final HttpServerExchange exchange) throws Exception { exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain"); exchange.getResponseSender().send("Hello World"); } }).build(); server.start(); } }
As you can see from the above class, the io.undertow.Undertow class is a Factory class which contains a convenience method builder that is used to create new instances of the Web Server. In order to be usable, the Web server should include at least two components:
- A listener which is going to intercept HTTP/HTTPS requests on a specific interface and port
- A handler that is associated to the listener. The handler must eventually either call another handler or end the exchange.
In order to compile the basic App class, you need to include two specific dependencies to your pom.xml as follows:
<dependency> <groupId>io.undertow</groupId> <artifactId>undertow-core</artifactId> <version>1.0.1.Final</version> </dependency> <dependency> <groupId>io.undertow</groupId> <artifactId>undertow-servlet</artifactId> <version>1.0.1.Final</version> </dependency>
Now include as well a plugin to execute the App Java class:
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <executions> <execution> <goals> <goal>java</goal> </goals> </execution> </executions> <configuration> <mainClass>com.mastertheboss.undertow.App</mainClass> </configuration> </plugin> </plugins> </build>
And run the test with:
mvn exec:java
Once that you point your browser to localhost:8080 you will obviously get:
Deploying applications on Undertow
Moving away from the basic example, we will learn how to deploy a web application to Undertow which contains a set of components such as:
- A Servlet
- A Web listener
The following class, uses the DeploymentInfo API (part of the undertow-servlet artifact) to deploy a Servlet (assigning the URL Path “/myservlet”). Additionally a SessionListener is included in the deployment, whose name is set to “test.war”:
public class ServletEngine { public static final String MYAPP = "/myapp"; public static void main(final String[] args) { try { DeploymentInfo servletBuilder = deployment() .setClassLoader(ServletEngine.class.getClassLoader()) .setContextPath(MYAPP) .setDeploymentName("test.war") .addListener(new ListenerInfo(MySessionListener.class)) .addServlets( servlet("ExampleServlet", ExampleServlet.class) .addInitParam("message", "Hello World") .addMapping("/myservlet")); DeploymentManager manager = defaultContainer().addDeployment(servletBuilder); manager.deploy(); HttpHandler servletHandler = manager.start(); PathHandler path = Handlers.path(Handlers.redirect(MYAPP)) .addPrefixPath(MYAPP, servletHandler); Undertow server = Undertow.builder() .addHttpListener(8080, "localhost") .setHandler(path) .build(); server.start(); } catch (ServletException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
The above class, will start up an instance of Undertow Web server and deploy a Servlet which is accessible at localhost:8080/myapp/myservlet as shown:
Serving Web content using Undertow
If you need to serve resources which are generally placed in the WebContent of your application, then you can use ResourceManager that is able to return a server resource for a given path. Supposing that you want to publish content which is available under the src/main/webapp folder of your project:
DeploymentInfo servletBuilder = deployment() .setClassLoader(ServletEngine.class.getClassLoader()) .setContextPath(MYAPP) .setResourceManager(new FileResourceManager(new File("src/main/webapp"), 1024)) .setDeploymentName("test.war"));
References: http://undertow.io/documentation/
Thanks to Stuart Douglas for providing support in writing this article!