Important: This news article covers an old version of Javalin (v2.8.0). The current version is v6.3.0.
See the documentation page for up-to-date information.

Validation improvements

The validation added in 2.2.0 is one of Javalin’s most popular features, but the syntax is a bit wonky:

val myQpStr = ctx.queryParam("my-qp")
val myQpInt = ctx.validatedQueryParam("my-qp").asInt().getOrThrow()
val myQpInt = ctx.validatedQueryParam("my-qp").asInt().check{ it  > 4 }.getOrThrow()
val instant = ctx.validatedQueryParam("my-qp").asClass<Instant>().getOrThrow()

The naming of the validation methods make the code overly verbose, and everything looks a very inconsistent. In 2.8.0 we’re deprecating ctx.validated... and introducing overloads instead:

  • Kotlin
  • Java
val myQpStr = ctx.queryParam("my-qp")
val myQpInt = ctx.queryParam<Int>("my-qp").get()
val myQpInt = ctx.queryParam<Int>("my-qp").check{ it > 4 }.get()
val instant = ctx.queryParam<Instant>("my-qp").get()
var myQpStr = ctx.queryParam("my-qp");
var myQpInt = ctx.queryParam("my-qp", Integer.class).get();
var myQpInt = ctx.queryParam("my-qp", Integer.class).check(i -> i > 4).get();
var instant = ctx.queryParam("my-qp", Instant.class).get();

This should make controllers a lot easier to read. The methods will be removed completely in 3.0.0.

Micrometer support

You can enable Micrometer easily by doing app.enableMicrometer().

Misc fixes

  • CORS now supports cookies (allow-credentials: true)
  • You can now use any connector (such as UnixSocketConnector) with the embedded Jetty server
  • Jetty no longer retries a request if a java.lang.Error is thrown in a handler
  • Javalin used to log.error(...) if it failed to start, now it throws instead
  • sessionHandler() no longer throws exceptions if SessionHandler looks misconfigured

Simplified startup logging

This might seem like a minor thing, but we got some complaints about verbose and cryptic log messages from Jetty. We agree that these messages aren’t really all that helpful, so we removed them.

Before


[main] INFO io.javalin.Javalin -
_________________________________________
|        _                  _ _           |
|       | | __ ___   ____ _| (_)_ __      |
|    _  | |/ _` \ \ / / _` | | | '_ \     |
|   | |_| | (_| |\ V / (_| | | | | | |    |
|    \___/ \__,_| \_/ \__,_|_|_|_| |_|    |
|_________________________________________|
|                                         |
|    https://javalin.io/documentation     |
|_________________________________________|
[main] INFO io.javalin.Javalin - Starting Javalin ...
[main] INFO org.eclipse.jetty.server.Server - jetty-9.4.15.v20190215; built: 2019-02-15T16:53:49.381Z; git: eb70b240169fcf1abbd86af36482d1c49826fa0b; jvm 1.8.0_162-b12
[main] INFO org.eclipse.jetty.server.session - DefaultSessionIdManager workerName=node0
[main] INFO org.eclipse.jetty.server.session - No SessionScavenger set, using defaults
[main] INFO org.eclipse.jetty.server.session - node0 Scavenging every 600000ms
[main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started i.j.c.u.initialize$httpHandler$1@e320068{/,null,AVAILABLE}
[main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@52f759d7{/,null,AVAILABLE}
[main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@7276c8cd{HTTP/1.1,[http/1.1]}{0.0.0.0:7000}
[main] INFO org.eclipse.jetty.server.Server - Started @2823ms
[main] INFO io.javalin.Javalin - Jetty is listening on: [http://localhost:7000/]
[main] INFO io.javalin.Javalin - Javalin has started \o/

After


[main] INFO io.javalin.Javalin -
           __                      __ _
          / /____ _ _   __ ____ _ / /(_)____
     __  / // __ `/| | / // __ `// // // __ \
    / /_/ // /_/ / | |/ // /_/ // // // / / /
    \____/ \__,_/  |___/ \__,_//_//_//_/ /_/

        https://javalin.io/documentation

[main] INFO io.javalin.Javalin - Starting Javalin ...
[main] INFO io.javalin.Javalin - Listening on http://localhost:7070/
[main] INFO io.javalin.Javalin - Javalin started in 267ms \o/