Environment
Spring Boot: 3.3.6 Spring Web: 6.1.15 Java: 21
Context:
A @RequestMapping
that makes use of @Constraint
annotations to validate @RequestHeader
and uses @Valid
annotation to validate @RequestBody
.
Controller
@RestController
@RequestMapping("/api")
public class DemoController {
@PostMapping("/test")
public Mono<String> test(
@RequestHeader(name = "x-channel") @Size(min=4, max=4) String channel,
@Valid @RequestBody RequestDto requestDto
) {
return Mono.just("test");
}
}
Dto
@ValidatorTestAnnotation
public record RequestDto(@NotEmpty String id) {
}
Please note that the RequestDto
uses @Constraint
annotations at field level and also class level.
CustomAnnotation and Validator
@Constraint(validatedBy = TestAnnotationValidator.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidatorTestAnnotation {
String message() default "Example fail message";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class TestAnnotationValidator implements ConstraintValidator<ValidatorTestAnnotation, RequestDto> {
@Override
public boolean isValid(RequestDto dto, ConstraintValidatorContext context) {
// Dummy validation. Return false for the purpose of this example
return false;
}
}
Since I have @Contraint
annotations declared directly on method parameters, the exception raised is HandlerMethodValidationException
.
I'm using the HandlerMethodValidationException.visitResults
to handle the errors.
@RestControllerAdvice
public class DemoControllerAdvice {
@ExceptionHandler(HandlerMethodValidationException.class)
public String handlerMethodValidationException(HandlerMethodValidationException e) {
e.visitResults(new HandlerMethodValidationException.Visitor() {
@Override
//implementation...
Issue:
When I use a @Constraint
annotation at class level, the HandlerMethodValidationException
validationResult list is composed of a ParameterValidationResult
instead of a ParameterErrors
object.
This fails in the visitor assertion that exists in HandlerMethodValidationException.asErrors
method:
(...)
RequestBody requestBody = param.getParameterAnnotation(RequestBody.class);
if (requestBody != null) {
visitor.requestBody(requestBody, asErrors(result));
continue;
}
(...)
private static ParameterErrors asErrors(ParameterValidationResult result) {
Assert.state(result instanceof ParameterErrors, "Expected ParameterErrors"); <------- FAILS HERE
return (ParameterErrors) result;
}
Thanks for the support.