6

I have an enum field in my Spring DTO which I use in my @RestController. I wish to create custom error message upon failed validation for this enum field:

public class ConversionInputDto {

    // validation annotations
    private BigDecimal sourceAmount;

    // enum field
    @NotNull(message = ERROR_EMPTY_VALUE)
    private CurrencyFormat targetCurrency;

    // no-args constructor and getters
} 

Receiving input as a String and making a custom annotation seems an overkill in my case, and the other alternative, which I know, catches all InvalidFormatException errors via @ControllerAdvise and returns the same error for them (thus, a user submitting e.g. String input for numeric property will get the same error message):

@ExceptionHandler(InvalidFormatException.class)
public void handleInvalidEnumAndAllOtherInvalidConversions(HttpServletResponse response) throws IOException {
    response.sendError(HttpStatus.BAD_REQUEST.value(), ERROR_MESSAGE);
}

The current default validation error is too long and I would like to make it more user-friendly like "Invalid currency format value. Please choose between....":

"Invalid JSON input: Cannot deserialize value of type com.foreignexchange.utilities.CurrencyFormat from String \"test\": not one of the values accepted for Enum class: [AUD, PLN, MXN, USD, CAD]; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type com.foreignexchange.utilities.CurrencyFormat from String \"test\": not one of the values accepted for Enum class: [AUD, PLN, MXN, USD, CAD]\n at [Source: (PushbackInputStream); line: 3, column: 20] (through reference chain: com.foreignexchange.models.ConversionInputDto[\"targetCurrency\"])",

Is there an elegant way to solve this? Perhaps with some additional logic in the @ExceptionHandler checking which field has failed validation?

Petar Bivolarski
  • 1,599
  • 10
  • 19
  • You might try [registering a custom deserializer](https://www.baeldung.com/jackson-deserialization) for your enum class that would throw a custom exception with a more user-friendly message – crizzis Mar 21 '20 at 14:16
  • does this help? https://stackoverflow.com/questions/52386294/notnull-validation-custom-message-not-displaying?answertab=active#tab-top – Marcos Barbero Mar 21 '20 at 14:19
  • I was hoping to avoid instanceOf checks, but it is the shortest way I could find. Thanks! – Petar Bivolarski Mar 21 '20 at 17:20

1 Answers1

3

Thanks to the comments, I found a solution by using isAssignableFrom() to provide custom error messages for the failed enum validation:

@ExceptionHandler(InvalidFormatException.class)
public void handleOfflineBankApi(HttpServletResponse response, InvalidFormatException ex) throws IOException {
    if (ex.getTargetType().isAssignableFrom(CurrencyFormat.class)) {
        response.sendError(HttpStatus.BAD_REQUEST.value(), Constants.ERROR_INVALID_CURRENCY_FORMAT);
    } else {
        response.sendError(HttpStatus.BAD_REQUEST.value(), ex.getMessage());
    }
}
Petar Bivolarski
  • 1,599
  • 10
  • 19