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

Introducing the Validator

The Javalin Validator is a class for validating user input. It will let you do useful things, like:

  • Kotlin
  • Java
// validate two dependent query parameters:
val fromDate = ctx.validatedQueryParam("from").asClass<Instant>().getOrThrow()
val toDate = ctx.validatedQueryParam("to").asClass<Instant>()
        .check({ it.isAfter(fromDate) }, "'to' has to be after 'from'")
        .getOrThrow()

// validate a json body:
val myObject = ctx.validatedBody<MyObject>()
        .check({ it.myObjectProperty == someValue })
        .getOrThrow()
// validate two dependent query parameters:
Instant fromDate = ctx.validatedQueryParam("from").asClass(Instant.class).getOrThrow();
Instant toDate = ctx.validatedQueryParam("to").asClass(Instant.class)
        .check(it -> it.isAfter(fromDate), "'to' has to be after 'from'")
        .getOrThrow();

// validate a json body:
MyObject myObject = ctx.validatedBodyAsClass(MyObject.class)
        .check(obj -> obj.myObjectProperty == someValue)
        .getOrThrow();

If validation fails, Javalin will throw a BadRequestResponse with a nice error message:

"Query parameter 'to' with value '1262347100000' invalid - 'to' has to be after 'from'"

Architecture

There are two classes:

  • Validator - This is the base class. It has three validation methods: notNullOrEmpty(), matches(), check(). It also has methods for turning itself into a TypedValidator<T>
  • TypedValidator<T> - When the String has been validated, additional type-safe checks can be performed by calling check() on this class.

Both classes have getOrThrow() for getting the value.

Validation is available both on the Context and standalone.

Context

If called on the Context, you get nice default prefixes:

ctx.validatedFormParam("abc") // "Form parameter 'abc' with value '$value'"
ctx.validatedPathParam("abc") // "Path parameter 'abc' with value '$value'"
ctx.validatedQueryParam("abc") // "Query parameter 'abc' with value '$value'"
ctx.validatedBody<T>() // "Request body as $clazz"

Standalone

If called standalone, you can supply your own message prefix:

JavalinValidation.validate(jsonProp, "jsonProp").notNullOrEmpty().getOrThrow()
// -> jsonProp cannot be null or empty

If you leave out the prefix it defaults to “Value”:

JavalinValidation.validate(jsonProp).notNullOrEmpty().getOrThrow()
// -> Value cannot be null or empty

Typing a Validator

Conversion for basic data types is included on the base Validator class:

asBoolean()
asDouble()
asFloat()
asInt()
asLong()

Conversion for other data types can be done by calling:

asClass<MyClass>()

In which case you’ll have to register a converter for your class by calling JavalinValidation#register:

JavalinValidation.register(Instant::class.java) { Instant.ofEpochMilli(it.toLong()) }

We’re very grateful for the all the community input we received for this feature.

JSON Futures

A json(future) method has been added to the Context:

fun json(future: CompletableFuture<*>): Context {
    val mappingFuture = future.thenApply { obj -> JavalinJson.toJsonMapper.map(obj) }
    return contentType("application/json").result(mappingFuture)
}

This method will allow you to set an object as a future result, then Javalin will serialize it to JSON when it’s ready.