I am using Spring MVC 3.2.2
I have defined a custom HandlerMethodArgumentResolver class like this
public class CurrentUserArgumentResolver implements HandlerMethodArgumentResolver {
public CurrentUserArgumentResolver() {
System.out.println("Ready");
}
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(CurrentUser.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Principal principal = webRequest.getUserPrincipal();
System.out.println("*** Principal ***: " + principal);
return principal;
}
}
And added the following to my app-servlet.xml
<mvc:annotation-driven>
<mvc:argument-resolvers>
<beans:bean class="my.package.CurrentUserArgumentResolver" lazy-init="false"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
and created an annotation for CurrentUser
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {
}
When I start the application up the class is constructed as I can see the log message "Ready" but the resolver does not execute when I annotate a controller method as such (in a class that has @Controller annotation)
@RequestMapping(method = RequestMethod.POST, value = "/update")
public ModelAndView update(@RequestParam MultipartFile background, @CurrentUser Principal principal) {
...
}
If I put breakpoints on either method in the CurrentUserArgumentResolver class, neither work. So not sure what I am missing?
If anybody ever wants to prioritize custom handlers over default handlers added by spring, here's a snippet that does it for me, I do this in a @Configuration
file
private @Inject RequestMappingHandlerAdapter adapter;
@PostConstruct
public void prioritizeCustomArgumentMethodHandlers () {
List<HandlerMethodArgumentResolver> argumentResolvers =
new ArrayList<> (adapter.getArgumentResolvers ());
List<HandlerMethodArgumentResolver> customResolvers =
adapter.getCustomArgumentResolvers ();
argumentResolvers.removeAll (customResolvers);
argumentResolvers.addAll (0, customResolvers);
adapter.setArgumentResolvers (argumentResolvers);
}
OK I worked out that Spring was already resolving the Principal object in my above example and so my argument resolver was not kicking in. I had been lazy and added the @CurrentUser annotation to an existing parameter.
So I changed my example
@RequestMapping(method = RequestMethod.POST, value = "/update")
public ModelAndView update(@RequestParam MultipartFile background, @CurrentUser Principal principal) {
...
}
to use my User model class
@RequestMapping(method = RequestMethod.POST, value = "/update")
public ModelAndView update(@RequestParam MultipartFile background, @CurrentUser User user) {
...
}
and now it works!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With