The question is published on by Tutorial Guruji team.
I recently converted my Spring 4 MVC web application from XML configuration to a java based configuration. After doing so, all of the controllers are mapped twice. I feel like it has to do with the component scans but I am not able to figure out why. I can post the old XML configuration setup if that will help. The application works fine, it just prints the controller mapping twice in the logs.
Here they are loaded to the root context
... INFO RequestMappingHandlerMapping - Mapped "{[/user/changePassword],methods=[POST]}" onto public org.springframework.web.servlet.ModelAndView com.rapidtest.mvc.controller.UserController.changePasswordSubmit(com.rapidtest.mvc.form.user.ChangePasswordFormBean,org.springframework.validation.BindingResult) throws java.lang.Exception INFO SimpleUrlHandlerMapping - Mapped URL path [/pub/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] INFO SimpleUrlHandlerMapping - Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler] INFO RequestMappingHandlerAdapter - Looking for @ControllerAdvice: Root WebApplicationContext: startup date [Thu Oct 22 16:16:24 MDT 2015]; root of context hierarchy
Here they are also loaded to the message dispatcher context
... INFO RequestMappingHandlerMapping - Mapped "{[/user/changePassword],methods=[POST]}" onto public org.springframework.web.servlet.ModelAndView com.rapidtest.mvc.controller.UserController.changePasswordSubmit(com.rapidtest.mvc.form.user.ChangePasswordFormBean,org.springframework.validation.BindingResult) throws java.lang.Exception INFO SimpleUrlHandlerMapping - Mapped URL path [/pub/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] INFO SimpleUrlHandlerMapping - Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler] INFO RequestMappingHandlerAdapter - Looking for @ControllerAdvice: WebApplicationContext for namespace 'website-servlet': startup date [Thu Oct 22 16:16:28 MDT 2015]; parent: Root WebApplicationContext
Here is my web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <servlet-name>website</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> </init-param> <init-param> <param-name>contextConfigLocation</param-name> <param-value>com.rapidtest.config.mvc.MVCConfig</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>website</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>com.rapidtest.config.spring</param-value> </context-param> <context-param> <param-name>contextInitializerClasses</param-name> <param-value>com.rapidtest.util.properties.ArchaiusPropertyInitializer</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping> <filter> <filter-name>EncodingFilter</filter-name> <filter-class>com.rapidtest.web.filter.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>/index.jsp</welcome-file> </welcome-file-list> <error-page> <error-code>404</error-code> <location>/error/404</location> </error-page> <error-page> <location>/error/general</location> </error-page> </web-app>
Here is my java MVC Configuration
package com.rapidtest.config.mvc; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.web.multipart.commons.CommonsMultipartResolver; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled=true) @ComponentScan("com.rapidtest.mvc.controller") public class MVCConfig extends WebMvcConfigurationSupport { // <mvc:resources mapping="/pub/**" location="/pub/" /> @Override public void addResourceHandlers(final ResourceHandlerRegistry registry) { registry.addResourceHandler("/pub/**").addResourceLocations("/pub/"); } @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } // <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> // <property name="prefix"> // <value>/WEB-INF/jsp/</value> // </property> // <property name="suffix"> // <value>.jsp</value> // </property> // </bean> @Bean public ViewResolver configureViewResolver() { InternalResourceViewResolver viewResolve = new InternalResourceViewResolver(); viewResolve.setPrefix("/WEB-INF/jsp/"); viewResolve.setSuffix(".jsp"); return viewResolve; } // <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" /> @Bean(name = "multipartResolver") public CommonsMultipartResolver getMultipartResolver() { return new CommonsMultipartResolver(); } }
Here is my RootConfig. All of my other @Configuration classes are in the same package.
package com.rapidtest.config.spring; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ControllerAdvice; import com.rapidtest.util.properties.ArchaiusPropertyPlaceholderConfigurer; @Configuration //@ComponentScan(basePackages = {"com.rapidtest"}, useDefaultFilters=false, excludeFilters={ // @ComponentScan.Filter(type=FilterType.ANNOTATION, value={Controller.class, ControllerAdvice.class})}) @ComponentScan(basePackages = {"com.rapidtest"} ) public class RootConfig { //<bean id="propertyConfigurer" class="com.rapidtest.util.properties.ArchaiusPropertyPlaceholderConfigurer" /> @Bean(name = "propertyConfigurer") public static ArchaiusPropertyPlaceholderConfigurer getPropertyPlaceholder() { return new ArchaiusPropertyPlaceholderConfigurer(); } }
Answer
I was able to solve the problem by ignoring all @Configuration classes from the component scan.
@ComponentScan(basePackages = { "com.rapidtest.*" }, excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, value = { Configuration.class }) })