I want to register a custom HandlerMethodArgumentResolver
that could handle the following @Controller
handler method definition
@RequestMapping(method = RequestMethod.POST)
public String createDomain(@Valid Domain domain, BindingResult errors, @RequestParam("countryId") Long countryId) {
I can register my resolver, which just creates a Domain
object through request parameters, by overriding addArgumentResolver()
from WebMvcConfigurerAdapter
. When Spring tries to resolve the Domain
parameter, it goes through its list of HandlerMethodArgumentResolver
(there are a lot) and picks the first one that supports()
it.
In the above example, although my resolver will get called and my Domain
argument will get initialized, the @Valid
annotation won't have been processed and the resolver for BindingResult
, an ErrorsMethodArgumentResolver
will fail because it requires a @ModelAttribute
, @RequestBody
or the @RequestPart
argument in the handler method, which I don't have.
If I try to fix it by adding @ModelAttribute
@RequestMapping(method = RequestMethod.POST)
public String createDomain(@Valid @ModelAttribute Domain domain, BindingResult errors, @RequestParam("countryId") Long countryId) {
a HandlerMethodArgumentResolver
implementation, ModelAttributeMethodProcessor
, will get checked first with supports()
and resolve the argument (with @ModelAttribute
and @Valid
) before my custom resolver. The BindingResult
won't fail, but I won't have my custom creation behavior on the Domain
instance.
I could just copy-paste the code for validation and adding to model that's in ModelAttributeMethodProcessor
, but I was hoping there was an easier way to resolve my parameters and perform validation without adding an object to the model. Is there such a way?
Nice description of the issue that you are facing.
I checked out the code that you have outlined and have come to the same conclusion that you have - there is no built-in way to have both a custom HandlerMethodArgumentResolver
as well as @Valid
related validation applied at the same time, the only choice is to do what the ModelAttributeMethodProcessor
does which is to check if the parameter has a @Valid
annotation and call the validation logic related code.
You can probably derive your HandlerMethodResolverArgumentResolver
from ModelAttributeMethodProcessor
and call super.validateIfApplicable(..)
atleast this way the existing code is leveraged.