Bean validation

We can optionally add bean validation.

Example: HelloController

Add dependency

Add a dependency on controller-validator-hibernate. This will transitively bring in a dependency on hibernate-validator.

<dependency>
  <groupId>io.dinject</groupId>
  <artifactId>controller-validator-hibernate</artifactId>
  <version>1.1</version>
</dependency>

Add @Valid

Add @Valid annotation on controllers that we want bean validation to be included for. When we do this controller methods that take a request payload will then have the request bean (populated by JSON payload or form parameters) validated before it is passed to the controller method.

For the controller method below:

@Post("saveform")
@Form
void saveForm(HelloForm helloForm) {
  ...
}

The generated code now includes a validation of the helloForm before it is passed to the controller method. The generated code is:

ApiBuilder.post("/hello/saveform", ctx -> {
  ctx.status(201);
  HelloForm helloForm =  new HelloForm(
    ctx.formParam("name"),
    ctx.formParam("email")
  );
  helloForm.url = ctx.formParam("url");
  helloForm.startDate = toLocalDate(ctx.formParam("startDate"));

  validator.validate(helloForm);       // validation added here !!
  controller.saveForm(helloForm);
});

ValidationException handler

Add an exception handler for ValidationException like the one below. With bean validation we collect all the validation errors and these are included in the exception as a map keyed by the property path.

exception.getErrors() in the handler below is returning a Map<String, Object>

app.exception(ValidationException.class, (exception, ctx) -> {

  Map<String,Object> map = new LinkedHashMap<>();
  map.put("message", exception.getMessage());
  map.put("errors", exception.getErrors());
  ctx.json(map);
  ctx.status(exception.getStatus());
});