1

I have a JAX-RS resource in Quarkus whose inputs I want to validate. One of the properties in this validation bean below, which will validate the input from a PUT method, contains a property which is expected to be a number.

public class UpdateBookDTO {

    public Optional<@Length(min = 2, max = 100) String> title;

    public Optional<@Length(min = 2, max = 100) String> author;

    public Optional<@Positive @Digits(fraction = 0, integer = 10) String> pages;

    @Override
    public String toString() {
        return "UpdateBookDTO{" +
                "title=" + title +
                ", author=" + author +
                ", pages=" + pages +
                '}';
    }
}

However, since the @Digits' annotation doesn't work with the Integer data type, I have to use a String. The issue with this of course is that it requires an extra step of parsing. Can I, and how, do this directly in the validation bean with some "magical" annotation, or is this not possible?

Thanks in advance!

Saddex
  • 117
  • 1
  • 11
  • I'm thinking what you need is to validate that `pages` is an integer, no more than 10 digits long. This can be expressed like `Optional<@Positive @Max(999999999) Integer> pages`. If the JSON deserializer cannot convert the input to an integer, you will get a bad request error. To be honest, I do not know how will the deserializer behave if the input is a decimal (throw or round?) but maybe it's worth trying. By the way, I see that `@Digits` applies to `int`, you can use that instead of `@Max`. – Nikos Paraskevopoulos Dec 10 '21 at 08:51
  • 1
    @NikosParaskevopoulos I asked a senior about this whole issue on Friday and apparently this is not how his team would do it. They usually build a global exception handler that catches an exception like this (which in this case would be ProcessingException) and then gives a cleaner error message. My team is also going to build the frontend, so the error messages from the backend won't need to be 100% precise all the time. This handler would probably be akin to something described here: https://stackoverflow.com/questions/60008540/quarkus-exception-handler Gonna try it out tomorrow. – Saddex Dec 12 '21 at 13:00

1 Answers1

0

The solution I went for is descibed in the comments. I created a new package called "exceptions" containing global handler to catch the exceptions generated when trying to execute the operation I described the the question. The basic handler ended up looking like this:

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ProcessingException;

@Provider
public class CustomExceptionHandler implements ExceptionMapper<ProcessingException> {

    @Override
    public Response toResponse(ProcessingException e) {

        e.printStackTrace();
        return Response.status(400).entity("Unsupported data type").build();
    }
}

The implementation that actually was built based on the code above is a bit more sophisticated - the logic also parses which field is faulty and also tells you if it's located within a nested class - but this is how it would be done following basic principle. It should work out of the box without any other config, as long as you have the @Provider decorator present.

Saddex
  • 117
  • 1
  • 11