Hi Spring boot team!

This PR attempts to close gh-37081 by implementing the unwrap method in boot/autoconfigure/validation/ValidatorAdapter provided by Spring's SmartValidator interface which was added in consequence to Spring's gh-31082.

It has been tested against the sample project provided in gh-31082 and returns a Bad Request as long as the @Validated annotation is removed from class-level.

2023-08-28T19:55:01.610+03:00  INFO 14176 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 3.059 seconds (process running for 3.702)
2023-08-28T19:55:10.613+03:00 DEBUG 14176 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter    : [01873b0d-1] HTTP GET "/class/-1"
2023-08-28T19:55:10.642+03:00 DEBUG 14176 --- [ctor-http-nio-3] s.w.r.r.m.a.RequestMappingHandlerMapping : [01873b0d-1] Mapped to com.example.demo.ClassLevelController#getEntity(Long)
2023-08-28T19:55:10.849+03:00 DEBUG 14176 --- [ctor-http-nio-3] org.springframework.web.HttpLogging      : [01873b0d-1] Resolved [HandlerMethodValidationException: 400 BAD_REQUEST "Validation failure"] for HTTP GET /class/-1
2023-08-28T19:55:10.892+03:00 DEBUG 14176 --- [ctor-http-nio-3] org.springframework.web.HttpLogging      : [01873b0d-1] Encoding [{timestamp=Mon Aug 28 19:55:10 EEST 2023, path=/class/-1, status=400, error=Bad Request, requestId=0 (truncated)...]
2023-08-28T19:55:10.938+03:00 DEBUG 14176 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter    : [01873b0d-1] Completed 400 BAD_REQUEST
2023-08-28T19:55:28.995+03:00 DEBUG 14176 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter    : [01873b0d-2] HTTP GET "/method/-1"
2023-08-28T19:55:28.996+03:00 DEBUG 14176 --- [ctor-http-nio-3] s.w.r.r.m.a.RequestMappingHandlerMapping : [01873b0d-2] Mapped to com.example.demo.MethodLevelController#getEntity(Long)
2023-08-28T19:55:29.003+03:00 DEBUG 14176 --- [ctor-http-nio-3] org.springframework.web.HttpLogging      : [01873b0d-2] Resolved [HandlerMethodValidationException: 400 BAD_REQUEST "Validation failure"] for HTTP GET /method/-1
2023-08-28T19:55:29.004+03:00 DEBUG 14176 --- [ctor-http-nio-3] org.springframework.web.HttpLogging      : [01873b0d-2] Encoding [{timestamp=Mon Aug 28 19:55:29 EEST 2023, path=/method/-1, status=400, error=Bad Request, requestId= (truncated)...]
2023-08-28T19:55:29.005+03:00 DEBUG 14176 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter    : [01873b0d-2] Completed 400 BAD_REQUEST

However it appears that boot.autoconfigure.validation.ValidationAutoConfigurationTests#methodValidationPostProcessorValidatorDependencyDoesNotTriggerEarlyInitialization fails when building against latest Spring 6.1.0-SNAPSHOT logging multiple warnings of

Bean 'org.springframework.boot.autoconfigure.validation.ValidationAutoConfigurationTests$CustomValidatorConfiguration$SomeServiceConfiguration' of type [org.springframework.boot.autoconfigure.validation.ValidationAutoConfigurationTests$CustomValidatorConfiguration$SomeServiceConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [methodValidationPostProcessor]

I've taken the liberty in submitting this PR as the above test also fails when not having my changes incorporated, I am not sure whether this is deemed an issue in Spring or in Spring boot but I think it shows some resemblence to Spring's gh-24553.

Comment From: wilkinsona

Thanks, @zpavloudis. I've opened https://github.com/spring-projects/spring-framework/issues/31137 for the test failure caused by the Framework upgrade.

Comment From: wilkinsona

@zpavloudis there are several commits here that are unrelated to the validator unwrapping. Could you please try rebasing your changes on the HEAD of the main branch and force pushing?

Comment From: zpavloudis

@wilkinsona Now I do understand this is not the place to ask the why's and how's of git rebase but I have git rebase upstream/main and git came back with

First, rewinding head to replay your work on top of it... Applying: Unwrap a validator instance of specified type contained in SpringValidatorAdapter

and when attempting to push to origin - not via the terminal but through intellij's push dialog the list still reports several unrelated commits, as if it wants to update the forked branch with all the latest commits adding my work on top of it.

I can certainly try a force push but would this not lead to the same situation as before?

Comment From: wilkinsona

You might need to do a git rebase --interactive and then delete all of the commits that aren't related to your change.

Comment From: zpavloudis

@wilkinsona Thank you for your feedback. looks like that's done it!

Comment From: zpavloudis

Thanks again for the PR, @zpavloudis. I've left a few comments for your consideration. It would also be good to test the unwrapping. Would you like to do that by adding a few tests to ValidatorAdapterTests?

Thank your for your feedback.

I've opted for 1 test that runs through the unwrap method asserting that target is unwrapped to a Jakarta Validator as well as asserting an IllegalArgumentException is thrown when an unsupported type is passed.

I could be missing something so I remain open to suggestions.

Comment From: wilkinsona

Thanks very much for making your first contribution to Spring Boot, @zpavloudis.

I polished your changes a little bit:

  • split the two tests into separate methods
  • add a test for a SmartValidator that's wrapped multiple times
  • fix the unwrap implementation to handle multiple wrapping