Writing a custom Undertow Handler

In this quick quick tutorial we will learn how to add a custom Handler to Undertow and then we will install it on WildFly as a module.

The main Undertow functionality is provided by io.undertow.server.HttpHandler instances. These handlers can be chained together to form a complete server. In this example, we will add a TimedHandler which will allow to handle request between a time frame. Out of this timeframe, a service unavailable will be returned.

Here is our Handler:

package com.mastertheboss;

import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;

import io.undertow.util.StatusCodes;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

public class TimedHandler implements HttpHandler {

    private HttpHandler next;

    public TimedHandler(HttpHandler next) {
        this.next = next;
    }

    // Default values
    String from ="09:00";
    String to ="13:00";

    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    @Override
    public void handleRequest(final HttpServerExchange exchange) throws Exception {


        if (checkTime()) {
            next.handleRequest(exchange);
        } else {
            exchange.setStatusCode(StatusCodes.SERVICE_UNAVAILABLE);
            exchange.endExchange();
        }
    }


    public boolean checkTime() {
        Calendar now = Calendar.getInstance();

        int hour = now.get(Calendar.HOUR_OF_DAY); // Get hour in 24 hour format
        int minute = now.get(Calendar.MINUTE);

        Date date = parseDate(hour + ":" + minute);
        Date dateCompareOne = parseDate(from);
        Date dateCompareTwo = parseDate(to);

        if (dateCompareOne.before( date ) && dateCompareTwo.after(date)) {
            return true;
        }
        return false;
    }
    private Date parseDate(String date) {

        final String inputFormat = "HH:mm";
        SimpleDateFormat inputParser = new SimpleDateFormat(inputFormat, Locale.US);
        try {
            return inputParser.parse(date);
        } catch (java.text.ParseException e) {
            return new Date(0);
        }
    }

}

In order to compile this class, you will need the following Maven dependency:

<dependency>
  <groupId>io.undertow</groupId>
  <artifactId>undertow-core</artifactId>
  <version>2.0.29.Final</version>
</dependency>

Now let’s install the Undertow Handler as a Module. Assumed that you have packaged your Handler in the file undertow-handler-1.0-SNAPSHOT.jar</>, connect to the CLI:

$ ./jboss-cli -c

Then execute the following commands that will install the module and add it to the Undertow subsystem:

module add --name=com.mastertheboss.demohandler --slot=main --resources=undertow-handler-1.0-SNAPSHOT.jar --dependencies=io.undertow.core,javaee.api,javax.api

/subsystem=undertow/configuration=filter/custom-filter=example-handler:add(class-name=com.mastertheboss.TimedHandler, module=com.mastertheboss.demohandler)

As the Handler supports the “from” and “to” parameters, we will add a beginning and the end of the service:

/subsystem=undertow/configuration=filter/custom-filter=example-handler:write-attribute(name=parameters.from,value="08:00")
/subsystem=undertow/configuration=filter/custom-filter=example-handler:write-attribute(name=parameters.to,value="18:00")

Finally, add the filter ref to the host to enable it:

/subsystem=undertow/server=default-server/host=default-host/filter-ref=example-handler:add()

This is undertow configuration after these commands:

<subsystem xmlns="urn:jboss:domain:undertow:10.0" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other" statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}">
    <buffer-cache name="default"/>
    <server name="default-server">
        <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
        <https-listener name="https" socket-binding="https" ssl-context="ssl-context-server.keystore_1" enable-http2="true"/>
        <host name="default-host" alias="localhost">
            <location name="/" handler="welcome-content"/>
            <filter-ref name="example-handler"/>
            <http-invoker security-realm="ApplicationRealm"/>
        </host>
    </server>
    <servlet-container name="default">
        <jsp-config/>
        <websockets/>
    </servlet-container>
    <handlers>
        <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
    </handlers>
    <filters>
        <filter name="example-handler" class-name="com.mastertheboss.TimedHandler" module="com.mastertheboss.demohandler">
            <param name="from" value="08:00"/>
            <param name="to" value="18:00"/>
        </filter>
    </filters>
</subsystem>

You can check, if you issue an HTTP request beyond the defined timeframe, an error will be raised:

curl http://localhost:8080
<html><head><title>Error</title></head><body>503 - Service Unavailable</body></html>

Source code for this tutorial: Here

Found the article helpful? if so please follow us on Socials