Spring Web MVC 3.1.1 argument resolver called before interceptor

springspring-mvc

I'm configuring my Spring MVC 3.1.1 app as summarized below. Logging shows that 'MyArgumentResolver.resolveArgument' is invoked before 'MyInterceptor.preHandle'. When using both in an old fashion configuration (with exclicitly defined AnnotationMethodHandlerAdapter bean etc.) they are invoked vice versa. I read that <mvc:annotation-driven> is somehow critical, since its configuration does not complement other settings of mvc: namespace. Am I facing the same problem?

<mvc:annotation-driven>
  <mvc:message-converters>
   ...
  </mvc:message-converters>     
  <mvc:argument-resolvers>
    <bean class="[...].MyArgumentResolver"/>
  </mvc:argument-resolvers>    
</mvc:annotation-driven>
<mvc:interceptors>
  <mvc:interceptor>       
    <mvc:mapping path="/home/**" />
    <bean class="[...].MyInterceptor" />
  </mvc:interceptor>
</mvc:interceptors>

Many Thanks!

Best Answer

Spring 3.1 with <mvc:annotation-driven> uses a different set of classes for handling requests - e.g., AnnotationMethodHandlerAdapter is replaced with RequestMappingHandlerAdapter. You can read more about that here: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-31-vs-30

In order to work properly with those classes, they've added a new HandlerMethodArgumentResolver that supersedes the old WebArgumentResolver interface. However, I believe that Spring will automatically try to "upgrade" old WebArgumentResolvers by wrapping them in an AbstractWebArgumentResolverHandlerAdapter, which is the behavior that I was seeing during the process of upgrading. The JavaDoc for AbstractWebArgumentResolverHandlerAdapter says:

Note: This class is provided for backwards compatibility. However it is recommended to re-write a WebArgumentResolver as HandlerMethodArgumentResolver. Since supportsParameter(org.springframework.core.MethodParameter) can only be implemented by actually resolving the value and then checking the result is not WebArgumentResolver#UNRESOLVED ...

After stepping through the code, I think what may be happening in your case is that it the new classes call the supportsParameter function before executing preHandle in the interceptors, but the implementation of AbstractWebArgumentResolverHandlerAdapter actually calls the resolveArgument method and checks for 'UNRESOLVED' as the return type in order to determine if the argument resolver supports the given argument, which would give the appearance of them being called out of order.

I suspect if you rewrite your argument resolver to implement the new HandlerMethodArgumentResolver interface, it will solve your problem.