Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

customizing spring mvc auto configuration does not work for interceptors #2870

Closed
mreiterer opened this issue Apr 23, 2015 · 24 comments
Closed

Comments

@mreiterer
Copy link

I added my own WebMvcConfigurerAdapter as stated in the documentation:

If you want to keep Spring Boot MVC features, and you just want to add additional MVC configuration (interceptors, formatters, view controllers etc.) you can add your own @bean of type WebMvcConfigurerAdapter, but without @EnableWebMvc.

The addInterceptors method never gets called. I did some debugging and found out that the delegates are empty at the point in time when addInterceptors is called on DelegatingWebMvcConfiguration.

@esodot
Copy link

esodot commented Apr 27, 2015

little bit confused, following is not working for you?

@configuration
@EnableWebMvc
@componentscan
public class MvcConfig extends WebMvcConfigurerAdapter {

@Bean
public LocaleResolver localeResolver() {
    SessionLocaleResolver slr = new SessionLocaleResolver();
    slr.setDefaultLocale(Locale.GERMAN);
    return slr;
}   

@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
    LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
    lci.setParamName("locale");     
    return lci;
}   

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(localeChangeInterceptor());
    registry.addInterceptor(new ResolveLocaleThemeInterceptor());
}       

@Bean       
public InternalResourceViewResolver internalResourceViewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/jsp/");
    resolver.setSuffix(".jsp");
    return resolver;
}   

@wilkinsona
Copy link
Member

It works for me:

package demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@SpringBootApplication
public class Gh2870Application {

    public static void main(String[] args) {
        SpringApplication.run(Gh2870Application.class, args);
    }

    @Bean
    public WebMvcConfigurerAdapter adapter() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                System.out.println("Adding interceptors");
                super.addInterceptors(registry);
            }
        };
    }
}

addInterceptors is called as expected when the app starts up:


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.2.3.RELEASE)

2015-04-30 17:15:16.351  INFO 66830 --- [           main] demo.Gh2870Application                   : Starting Gh2870Application on aw-rmbp.local with PID 66830 (/Users/awilkinson/dev/workspaces/spring/spring-boot/gh-2870/target/classes started by awilkinson in /Users/awilkinson/dev/workspaces/spring/spring-boot/gh-2870)
2015-04-30 17:15:16.388  INFO 66830 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@215a730d: startup date [Thu Apr 30 17:15:16 BST 2015]; root of context hierarchy
2015-04-30 17:15:16.836  INFO 66830 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2015-04-30 17:15:17.376  INFO 66830 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2015-04-30 17:15:17.549  INFO 66830 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2015-04-30 17:15:17.549  INFO 66830 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.0.20
2015-04-30 17:15:17.623  INFO 66830 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2015-04-30 17:15:17.623  INFO 66830 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1237 ms
2015-04-30 17:15:18.103  INFO 66830 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2015-04-30 17:15:18.106  INFO 66830 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2015-04-30 17:15:18.106  INFO 66830 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2015-04-30 17:15:18.249  INFO 66830 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@215a730d: startup date [Thu Apr 30 17:15:16 BST 2015]; root of context hierarchy
Adding interceptors
2015-04-30 17:15:18.291  INFO 66830 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2015-04-30 17:15:18.291  INFO 66830 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],methods=[],params=[],headers=[],consumes=[],produces=[text/html],custom=[]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest)
2015-04-30 17:15:18.309  INFO 66830 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-04-30 17:15:18.310  INFO 66830 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-04-30 17:15:18.342  INFO 66830 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-04-30 17:15:18.388  INFO 66830 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2015-04-30 17:15:18.426  INFO 66830 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2015-04-30 17:15:18.428  INFO 66830 --- [           main] demo.Gh2870Application                   : Started Gh2870Application in 2.29 seconds (JVM running for 2.552)

Can you share a sample project that illustrates the problem?

@wilkinsona wilkinsona added the status: waiting-for-feedback We need additional information before we can continue label Apr 30, 2015
@mreiterer
Copy link
Author

The following does not work for me:

In my main app i have an import on this configuration class:

@Configuration
public class CustomWebMvcConfigurer extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(new ZuniCommRequestInterceptor(zuniCommLogService)).addPathPatterns("/zunicomm/**");
        super.addInterceptors(registry);
    }
}

@esodot: This is not my use case, i do not want to use the @EnableWebMvc as is stated in my first post.

@mreiterer
Copy link
Author

Ok, getting closer, disabling SecurityAutoConfiguration.class -> adding interceptors works again.

@wilkinsona
Copy link
Member

Still works for me. I added a WebMvcConfigurerAdapter subclass to spring-boot-sample-web-secure and the preHandle, postHandle, and afterCompletion methods are all called as expected. If you'd like us to investigate further, please provide a sample that illustrates the problem.

@mreiterer
Copy link
Author

Thanks for your investigation. I am using the swagger-springmvc project, when using the @EnableSwagger annotation, my addInterceptors method is not called anymore. Will post the issue in the swagger-springmvc project.

@wilkinsona
Copy link
Member

Thanks for the update. I'm going to close this for now. If further investigation suggests that it's a problem with Spring Boot after all, please comment and we can reopen the issue.

@wilkinsona wilkinsona removed the status: waiting-for-feedback We need additional information before we can continue label Jun 9, 2015
@AmeyKamat
Copy link

Hi, even I am facing similar issue with spring boot, and I found similar issues on four systems of widely different configuration. Following are the details of the issue

  1. WebConfig class which extends WebMvcConfigurerAdapter gets initialized (constructor is being called)
  2. addResourceHandlers and addViewHandlers methods in WebCofig class do not get called.
  3. Things become even weird further. When I rename WebConfig as MvcConfig, the above functions get called.
  4. The observation noted in 4 only works on one out of four cases that I have seen.
  5. We could not find any common characteristics in the systems in which this issue occurs
  6. The spring boot project (without renaming WebConfig) still works of many other systems without any issue.

Only console message that I get is

10:59:30,150  WARN PageNotFound:1120 - No mapping found for HTTP request with URI [/login] in DispatcherServlet with name 'dispatcherServlet'

PS: I am not using any third party spring project other than spring-boot

@philwebb
Copy link
Member

@AmeyKamat Are you able to provide a sample application that demonstrates the issue? Also I don't understand what you mean by "The observation noted in 4 only works on one out of four cases that I have seen", can you clarify?

@AmeyKamat
Copy link

I have created a sample app that fails to work on some system:
https://github.com/AmeyKamat/spring-boot-demo-for-404

Sorry...it was typo... I meant that renaming of file from WebConfig.class to MvcConfig.class works only in one of the systems.

@philwebb philwebb reopened this Jun 17, 2015
@AmeyKamat
Copy link

@philwebb Is there a temporary workaround for this? I have posted corresponding question at stack overflow: http://stackoverflow.com/questions/30910642/webmvcconfigureradapter-does-not-work

@wilkinsona
Copy link
Member

@AmeyKamat I would expect the code that you've shared to fail on every system.

By default,@SpringBootApplication enables component scanning from the package where it's declared, i.e. hello in this case. Your WebConfig class is in the config package so it's never found. Moving it into hello.config means that it's found and the view controller is added as expected.

@AmeyKamat
Copy link

Ok...I dint know that...bt still in my original project that I am working on...main package is called app and WebConfig file is in app.config package. Still I will try this on sample code.

@AmeyKamat
Copy link

@wilkinsona nope....it doesn't...I will update sample code.

@wilkinsona
Copy link
Member

@AmeyKamat Ok, let me know once you've made the updates and I'll take another look.

@wilkinsona wilkinsona added the status: waiting-for-feedback We need additional information before we can continue label Jun 18, 2015
@AmeyKamat
Copy link

@wilkinsona I have pushed the changes

@wilkinsona
Copy link
Member

Why did you change WebConfig to extend WebMvcConfigurationSupport? WebMvcConfigurationSupport is the class that is imported by @EnableWebMvc so annotating your class with @EnableWebMvc and extending WebMvcConfigurationSupportwill be configuring things twice. You should go back to extending WebMvcConfigurerAdapter as you were before.

As an aside, you should probably also remove the @EnableWebMvc annotation as Boot will do that for you. The only reason to use it is if you want to take complete control of the configuration of Spring MVC. This, along with the use of WebMvcConfigurerAdapter, is all described in the reference documentation.

@philwebb philwebb removed the status: waiting-for-feedback We need additional information before we can continue label Jun 19, 2015
@AmeyKamat
Copy link

Following @philwebb 's suggestion I removed @EnableWebMvc and the demo app started working. Then I tried stripping down project files one by one to see at what point error disappears. I found that I had two classes in the project, one, extended from WebMvcConfigurationSupport and the second, from WebMvcConfigurerAdapter. removing the former class from the project fixed the error.

What I want to know is, why did this happen? Secondly, why doesnt this error appear on all systems?

@wilkinsona
Copy link
Member

Glad to hear that you've got things working.

What I want to know is, why did this happen?

It's impossible to say without seeing some code that reproduces the problem. I would guess that, as I explained above, it's because you were configuring things twice and one of those configurations has to "win".

Secondly, why doesnt this error appear on all systems?

Assuming that my guess about the duplicate configuration is correct, the order in which they processed is probably undefined (you could fix the order using @Order). When it's undefined, the one that wins can vary.

@onlyeat3
Copy link

public class XXXConfiguration extends WebMvcConfigurationSupport {
  @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping requestMappingHandlerMapping = super.requestMappingHandlerMapping();
        MetricsRequestMappingMeterInterceptor interceptor = new MetricsRequestMappingMeterInterceptor();
        requestMappingHandlerMapping.setInterceptors(interceptor);
        return requestMappingHandlerMapping;
    }

@bclozel
Copy link
Member

bclozel commented Jul 24, 2018

@liuyuyu extending WebMvcConfigurationSupport is equivalent to annotating your class with @EnableWebMvc, which is a bad idea because that's what created the problem in the first place.
Here's you're configuring interceptors but completely disabling the Spring Boot auto-configuration for Spring MVC.

I don't know if your comment is supposed to show a solution to this issue - because in fact it is not.

@onlyeat3
Copy link

Thanks Reply. Although not particularly elegant, this approach does solve my problem, code address: https://github.com/liuyuyu/shadow/blob/master/shadow-metrics/src/main/java/io/github/liuyuyu/shadow/metrics/config/ShadowMetricsMVCConfiguration.java. Do you have any better suggestions?

@bclozel
Copy link
Member

bclozel commented Jul 25, 2018

Yes, asking a question on StackOverflow. We're usually answering questions there because it helps the broader community.

@onlyeat3
Copy link

@bclozel Sorry, I thought this issue was the same as discussing the issue with me. The situation I encountered is different. I will sort out the code that can reproduce the problem and put it in the new issue later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants