spring-boot: Unable to have custom RequestMappingHandlerMapping

I want to override the default RequestMappingHandlerMapping as follows:

    @Configuration
    public static class VersionConfig extends WebMvcConfigurationSupport {


        @Override
        protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
            return new VersionRequestMappingHandlerMapping();
        }

    }

where VersionRequestMappingHandlerMapping simply overrides some stub methods:


@Component
public class VersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping {

    @Override protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        VersionRange typeAnnotation = AnnotationUtils.findAnnotation(handlerType, VersionRange.class);
        return (typeAnnotation != null) ? new VersionRangeRequestCondition(typeAnnotation.value()) : null;
    }

    @Override
    protected RequestCondition<?> getCustomMethodCondition(Method method) {
        VersionRange methodAnnotation = AnnotationUtils.findAnnotation(
                method, VersionRange.class);
        return  (methodAnnotation != null) ? new VersionRangeRequestCondition(methodAnnotation.value()) : null;
    }
}

The issue is that because I am extending WebMvcConfigurationSupport in my config, WebMvcAutoConfiguration fails it’s conditional:

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
public class WebMvcAutoConfiguration {

I think the main issue is that the method :

    @Bean
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {

in WebMvcConfigurationSupport does too much work in the sense that it doesn’t simply create a new instance of RequestMappingHandlerAdapter so if I had to create my own @Bean returning a RequestMappingHandlerAdapter I would have to paste large chunks of code from WebMvcConfigurationSupport. If we had some factory available, I would just override that to inject my version instead.

There was a similar discussion reported on http://stackoverflow.com/questions/22267191/is-it-possible-to-extend-webmvcconfigurationsupport-and-use-webmvcautoconfigurat but the workaround only worked because it is invoking methods on the existing bean, not overriding them like in my case.

I’m willing to attempt a patch but I’d rather take up some comments/suggestions first.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 16 (10 by maintainers)

Commits related to this issue

Most upvoted comments

Thanks for the reply. Could you please provide any pointers for how to currently configure a spring boot application to provide everything that WebMvcAutoConfiguration provides but use a custom RequestMappingHandlerMapping? I mean is there anything better than just copying the entire existing WebMvcAutoConfiguration into a new class, modifying it, and registering it as an auto configuration?

I’ve gone ahead and added a couple more protected methods (https://github.com/spring-projects/spring-framework/commit/ebccfd023a7c7bb862bff96796310d8a35305f87) to allow plugging in custom sub-classes.

After giving this some more thought here is the way I see this. At the lowest level the Spring Framework provides two modes of MVC Java config. A simple callback-based configuration API (i.e. WebMvcConfigurer) that does not require seeing or knowing what beans are behind it and a more advanced option to extend directly from the bean-providing configuration (i.e. WebMvcConfigurationSupport). A user can choose one of these two modes.

Boot as an opinionated user chooses the advanced option which still allows applications to exercise control via one or more WebMvcConfigurer config classes. When a Boot user wants to do more advanced things they can extend Boot’s own WebMvcAutoConfiguration which could be a top-level class called BootWebMvcConfigurationSupport. Furthermore Boot can detect and hook in custom sub-classes of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, and ExceptionHandlerExceptionResolver so that switching to advanced configuration is not needed.

I think this model would make the most sense in terms of what’s expected on each level. At the Spring MVC level we can continue to make sure what needs to be extensible is. At the Spring Boot level we can then automatically detect user-provided custom sub-classes.

@michaelkrog unfortunately this will turn off all Spring Boot auto-configuration for Spring MVC and defeats the purpose of this issue. I believe this should still work in Spring Boot 2.0+:

@Component
public class CustomMvcRegistrations implements WebMvcRegistrations {

  public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
    return new CustomRequestMappingHandlerMapping();
  }
}

If it doesn’t, please open a new issue with a small project reproducing the error. Thanks!