18

It should be easy:

<bean id="handlerMapping"
   class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="interceptors">
        <list>
            <ref bean="myInterceptor" />
        </list>
    </property>
</bean>

but this way the interceptor isn't called.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140

5 Answers5

29

By default, Spring will register a BeanNameUrlHandlerMapping, and a DefaultAnnotationHandlerMapping, without any explicit config required.

If you define your own HandlerMapping beans, then the default ones will not be registered, and you'll just get the explicitly declared ones.

So far, so good.

The problem comes when you add <mvc:annotation-driven/> to the mix. This also declares its own DefaultAnnotationHandlerMapping, which replaces the defaults. However, if you also declare your own one, then you end up with two. Since they are consulted in order of declaration, this usually means the one registered by <mvc:annotation-driven/> gets called first, and your own one gets ignored.

It would be better if the DefaultAnnotationHandlerMapping registered by <mvc:annotation-driven/> acted like the default one, i.e. if explicitly declared ones took precedence, but that's not the way they wrote it.

My current preference is to not use <mvc:annotation-driven/> at all, it's too confusing, and too unpredictable when mixed with other config options. It doesn't really do anything especially complex, it's not difficult or verbose to explicitly add the stuff that it does for you, and the end result is easier to follow.

skaffman
  • 398,947
  • 96
  • 818
  • 769
13

Problem I faced: Spring MVC tag doesn't go well with custom definition of DefaultAnnotationHandlerMapping.

Why..? the reason is very well explained in the answers above.

Why i wanted to use DefaultAnnotationHandlerMapping? I want to define an interceptor for my every request. a Spring-Mobile interceptor to determine the USER AGENT..mobile or a browser?

Now Due to this clash of mvc-annotation and DefaultAnnotationHandlerMapping, I cant use DefaultAnnotationHandlerMapping anymore. The problem comes down to how can i register my interceptors with tag.

The solution was simple...but hard to find. Posting it so it can be helpful to the other solution seekers.. Use tag and register the interceptor bean in your dispathcer-servlet.xml example :

<mvc:interceptors>
 <!-- This runs for all mappings -->
     <bean  class="main.com.XXX.MobileDeviceResolverHanlderInterceptor"/>
</mvc:interceptors>
9

The reason for this behaviour is that two beans of type org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping exist in the application context. Spring resolves the two, but asks only the first for interceptors. To fix this, the following init parameter should be set to the DispatcherServlet

<init-param>
    <param-name>detectAllHandlerMappings</param-name>
    <param-value>false</param-value>
</init-param>

This makes the dispatcher servlet use only the handlerMapping defined in the x-servlet.xml

It is beyond me why this is the default behaviour. I'm expecting an answer from the spring community.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 3
    The defaults when using the `` namespace are wildly confusing. I prefer the older style of specifying everything yourself - the namespace configuration methods seem to rely too much on not-easily-found-in-documentation defaults – matt b Jul 12 '10 at 17:59
6

In my case I can NOT get rid of <mvc:annotation-driven/> as I am using jackson for json support using annotation.

What I tried, moved my all interceptors <mvc:interceptors> in separate "xml" file (interceptor-config.xml) and imported it from my x-dispatcher-servlet.xml

<import resource="interceptor-config.xml"/>

It solve my issue and avoid default 'DefaultAnnotationHandlerMapping' beans my application context.

Rather than creating separate 'xml', you can copy/paste interceptor contents directly in 'x-dispatcher-servlet.xml'.

Following is my interceptor:

  <mvc:interceptors> 
         <mvc:interceptor>
             <!-- Intercepting specific URL -->
             <mvc:mapping path="/abc/**" />
             <bean id= "myInterceptor" 
                 class="xx.xxx.xxx.MyInterceptor" />
         </mvc:interceptor>
<mvc:interceptors>
arviarya
  • 650
  • 9
  • 9
3

In Spring MVC 3.0 you can use <mvc:interceptors> instead of manual defining the handler mapping.

axtavt
  • 239,438
  • 41
  • 511
  • 482