Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

<mvc:annotation-driven /> with un-annotated controllers

My project includes older un-annotated controllers together with newer annotation-based controllers.

I am using the latest Spring jars (3.0.5) and in my dispatcher-servlet.xml there's <mvc:annotation-driven />.

The problem is that <mvc:annotation-driven /> causes the request mapping (through the name property of the controller beans in the dispatcher-servlet.xml) to my un-annotated controllers not to work... each time I direct the request to an un-annotated controller I am getting an error message such as:

org.springframework.web.servlet.DispatcherServlet noHandlerFound  
WARNING: No mapping found for HTTP request with URI [/some_path/some_page.htm] in DispatcherServlet with name 'dispatcher'

How can I keep the un-annotated controllers as they are but tell spring to recognize their (old style) mapping?

I am looking for solutions with minimum change to the Java code of the controllers that I already have.

Thanks!

like image 265
rapt Avatar asked Aug 26 '11 03:08

rapt


People also ask

What is the use of mvc annotation-driven />?

mvc:annotation-driven is used for enabling the Spring MVC components with its default configurations. If you dont include mvc:annotation-driven also your MVC application would work if you have used the context:component-scan for creating the beans or defined the beans in your XML file.

What does mvc annotation-driven do?

<mvc:annotation-driven /> declares explicit support for annotation-driven MVC controllers (i.e. @RequestMapping , @Controller , although support for those is the default behaviour), as well as adding support for declarative validation via @Valid and message body marshalling with @RequestBody / ResponseBody .

What happens when a class is annotated with the @controller annotation?

The @Controller annotation indicates that a particular class serves the role of a controller. There is no need to extend any controller base class or reference the Servlet API. You are of course still able to reference Servlet-specific features if you need to.

What is @controller annotation in Spring MVC?

Spring MVC @Controller This is simply a specialization of the @Component class, which allows us to auto-detect implementation classes through the classpath scanning. We typically use @Controller in combination with a @RequestMapping annotation for request handling methods.


2 Answers

When you add <mvc:annotation-driven /> to your config, it replaces the default set of handler mappings and handler adapters, and those defaults were the ones that handled the old-style controllers.

You have 2 options. First thing to try is to remove <mvc:annotation-driven />. You can still use annotated controllers without this. It does add extra features like Jackson JSON support, but if you don't need those extra features, then you don't need it. So try your app without <mvc:annotation-driven /> and see if it still works.

Failing that, you can reinstate the mappings and adapters for your old controllers. You didn't say how your controllers used to have their URLs mapped, but try adding these to your config:

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<bean class="org.springframework.web.servlet.handler.ControllerClassNameHandlerMapping"/>

If you used SimpleUrlHandlerMapping, then that should be working already.

You also need to add the HandlerAdapter back in:

<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

Don't just add these in blindly. Try them individually, and see what the minimal set is to get your old controllers working alongside the new ones.

like image 174
skaffman Avatar answered Sep 30 '22 13:09

skaffman


I found that by exploding the mvc:annotation-driven into it's actual replacement, it was easier to figure out.

<mvc:annotation-driven /> explodes to this:

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="order" value="0" />
</bean>

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="webBindingInitializer">
        <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
            <property name="validator" ref="validator" />
        </bean>
    </property>
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
            <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
        </list>
    </property>
</bean>

<!-- Configures a validator for spring to use -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="messageInterpolator">
        <bean class="com.eps.web.spring.validation.SpringMessageSourceMessageInterpolator" />
    </property>
</bean>

<bean id="conversion-service" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />

Once the magic was gone, I got this error trying to load an "Old" controller: javax.servlet.ServletException: No adapter for handler [org.springframework.web.servlet.mvc.ParameterizableViewController@

From that point, I added

<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />

And all my old controllers worked.

like image 45
Brad Lee Avatar answered Sep 30 '22 14:09

Brad Lee