Query Parameters and Path Parameters are also fairly straight forward in Undertow. There is some slight boilerplate because technically query and path params can have multiple values. We are using some helper functions (PathParameters.java and QueryParameters.java

Path Parameter and Query Parameter RoutingHandler

Fairly standard path param syntax. Undertow uses {param} you may be used to :param from other frameworks. Path parameters are a great way to have human readable urls which can benefit users and SEO. ToonStyle's URL for the page on Kung Fu Panda Merchandise can be constructed by slugifying the franchise name into the following url /franchise/{franchiseName}.

private static final HttpHandler ROUTES = new RoutingHandler()
    .get("/hello", ParametersServer::queryParam)
    .get("/hello/{name}/{num}", ParametersServer::pathParam)
    .get("/users/{userId}", ParametersServer::obfuscatedIdRoute)

Path Parameter and Query Parameter HttpHandlers

These should be straight forward. Once again we are using the following helpers PathParameters.java and QueryParameters.java

private static void queryParam(HttpServerExchange exchange) {
    String name = Exchange.queryParams().queryParam(exchange, "name").orElse("world");
    int num = Exchange.queryParams().queryParamAsInteger(exchange, "num").orElse(1);
    Exchange.body().sendText(exchange, "Hello " + name + Strings.repeat("!", num));

private static void pathParam(HttpServerExchange exchange) {
    String name = Exchange.pathParams().pathParam(exchange, "name").orElse("world");
    int num = Exchange.pathParams().pathParamAsInteger(exchange, "num").orElse(1);
    Exchange.body().sendText(exchange, "Hello " + name + Strings.repeat("!", num));


public static void main(String[] args) {
    // Just some examples for obfuscated parameters.
    LongStream.range(100_000_000, 100_000_003).forEach( id -> {
       log.debug("id: " + id + " hashed: " + HashIds.encode(id));
    SimpleServer server = SimpleServer.simpleServer(ROUTES);


curl localhost:8080/hello
Hello world!
curl localhost:8080/hello?name=bill
Hello bill!
curl 'localhost:8080/hello?name=bill&num=5'
Hello bill!!!!!
curl 'localhost:8080/hello/bill/5'
Hello bill!!!!!

Best Practices

Although it's not very hard calling params in this way we recommend extracting the logic out even further. Take a look at Request Utilities in the REST post. Here you define the string literals and defaults once and only once. Everywhere else in the code that references this param is called just like UserRequests.email(exchange). This way if you change the param name or even the type of param it updates all of your code at once. Sharing defaults is also incredibly useful. Another feature of this is you can cache values on the HttpServerExchange so you can use expensive calls in multiple routes with the cached values.

Obfuscating Sequential Ids

Sometimes you may want to obfuscate sequential ids to reduce the possibility of giving away some information. A quick example on Obfuscating and Shortening Sequential ids with HashIds.