Search code examples
javabean-validation

How to get which field is failed in custom jakarta bean validation?


I added custom validation as annotation and add it to my DTO's as @UUID and it works expected. I add this annotation whenever I need to validate if a field is valid UUID. Whenever it fails it throws exception with GlobalExceptionHandler as I expect.

{
    "exception": "org.springframework.web.bind.MethodArgumentNotValidException",
    "timeStamp": 1676468004793,
    "errorDetail": [
        {
            "key": "invalid.uuid",
            "message": "Invalid UUID",
            "errorCode": null,
            "args": null
        }
    ]
}

How can I make validator to tell me which field has failed when I have such dto ?

DTO

@Data
public class CollectionCreateRequest {
    @UUID
    private String gitlabId = null;
    @UUID
    private String teamId;

}

Validator

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import jakarta.validation.ReportAsSingleViolation;
import jakarta.validation.constraints.Pattern;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Constraint(validatedBy={})
@Retention(RetentionPolicy.RUNTIME)
@Pattern(regexp="^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$|")
@ReportAsSingleViolation
public @interface UUID {
    String message() default "invalid.uuid";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Solution

  • As you are using Spring and GlobalExceptionHandler you would want to make sure that you have a handler for MethodArgumentNotValidException in it. Somethig along next lines would do it:

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Problem handleValidationExceptions(MethodArgumentNotValidException ex) {
        ex.getFieldErrors().forEach((error) -> {
            FieldError fieldError = (FieldError) error;
            String fieldName = fieldError.getField();
            String errorMessage = error.getDefaultMessage();
            // get any other properties you need
            // create a response based on the collected info
        });
        // return your built error result
    }