Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue in HandlerMethodValidationException.visitResults when class level annotations are used in @RequestBody #34105

Open
joaoduartemiranda opened this issue Dec 17, 2024 · 0 comments
Labels
status: waiting-for-triage An issue we've not yet triaged or decided on

Comments

@joaoduartemiranda
Copy link

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.

debug

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.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Dec 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage An issue we've not yet triaged or decided on
Projects
None yet
Development

No branches or pull requests

2 participants