Marcel Overdijk
Marcel Overdijk

Reputation: 11467

How to use different error codes for validation messages?

I have a Spring Boot REST server which should return specific error codes when invalid input is provided. I don't need any i18n here, just plain English error codes like 'missing' is sufficient.

Using Spring Boot with Hibernate Validator, after validation I get a back Spring Errors object.

For each error I can get the code and defaultMessage. For a @NotBlank constraint this would return NotBlank and may not be null resp.

Basically I want to translate this error to just missing as I'm not interested in i18n translation. Also other constraints I want to more REST friendly error codes.

I though to use use a simple messages.properties or ValidationMessages.properties inside src/main/resources but this wouldn't work unfortunately. Note I tried both adding a general NotBlank=missing and specific NotBlank.entity.field=missing properties.

I'm not sure why it's not working... maybe because resolving i18n messages (in jsp world) does not go directly via Spring Errors but through the MessageCodesResolver implementation (just guessing).

Probably I could get the error code from the Spring Error and do a lookup from the message code resolver. But I wonder why error.getDefaultMessage does not return the appropriate value form the ValidationMessages.properties.

Any suggestion is welcome.

Upvotes: 1

Views: 3172

Answers (1)

M. Deinum
M. Deinum

Reputation: 124526

The default message is the message as stated by the programmer. In the case of those JSR-303 annotations probably the ones as Hibernate thought of them. The default message including the code is passed to the MessageSource.getMessage method, which contains a parameter defaultMessage

When you look at the Errors object or actually the ObjectError method you will see that it implements the MessageSourceResolvable interface. This means you can just pass the error, as is, to the MessageSource, including the Locale if you want.

@RequestMapping
public Object foo(@Valid @RequestBody MyObject obj, Errors errors, Locale locale) {
    for (ObjectError err : errors.getAllErrors()) {
        String msg = messageSource.getMessage(err, locale);
        // Do something with msg
    }
}

Something like the above should resolve the message. The advantage of using the ObjectError itself is that next to the code you also have the parameters (for @Range or @Min) which you can then use in your message with placeholders.

Upvotes: 1

Related Questions