Search code examples
javabean-validationmicronaut

micronaut applying @Validation to inbound controller POJO(s) doesn't validate


Given this controller method.

import io.micronaut.validation.Validated;
...

@Validated
@Get(value = "test{?page*}", produces = APPLICATION_JSON)
public HttpResponse<TransactionListResponseDto> get(
        PageDto page) {
    Sort sort = Pageable.from(page.getPage(), page.getSize(), sortFrom(page.getSort()));
    return HttpResponse.ok();
}

and the PageDto that looks like this.

import javax.validation.constraints.Min;
...

@Getter
@Setter
@Introspected
@JsonInclude(NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class PageDto {
    @Min(1)
    private int page = 1;
    private int size = 10;
    private String sort;
}

and the necessary validation includes in the gradle file.

implementation "io.micronaut:micronaut-validation:$micronautVersion"
implementation "io.micronaut.beanvalidation:micronaut-hibernate-validator:$micronautVersion"

I am expecting that controller method to validate the arguments, but it's very happy for me to pass in (for example) -100 as the page number, despite the validation attributes. Following the documentation and advice.

I have to conclude I am missing a build step or something?


Solution

  • Annotate the page parameter by @Valid annotation to instruct Micronaut to use nested validation:

    @Get(value = "test{?page*}", produces = APPLICATION_JSON)
    public HttpResponse<TransactionListResponseDto> get(@Valid PageDto page) {
        ...
        return HttpResponse.ok();
    } 
    

    Then it will behave like this:

    $ curl http://localhost:8080/test?page=-100
    {
      "message": "page.page: must be greater than or equal to 1",
      "_links": {
        "self": {
          "href": "/test?page=-100",
          "templated": false
        }
      }
    }
    

    If you have Micronaut Data in you project then you can use already existing io.micronaut.data.model.Pageable interface for pagination and pass it directly into repository classes. In that case your method can look like this:

    @Get(value = "test", produces = APPLICATION_JSON)
    public HttpResponse<Page<ItemOverview>> get(@Valid Pageable pageable) {
        return HttpResponse.ok(someRepository.findAll(pageable))
    }