Spring MVC RequestMappingHandlerMapping happens twice when application starts Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of Spring MVC RequestMappingHandlerMapping happens twice when application starts without wasting too much if your time.

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 }) 
})
We are here to answer your question about Spring MVC RequestMappingHandlerMapping happens twice when application starts - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji