0

I'm struggling to find a way to add request interceptors from within one or more add-on modules (modules being Maven modules in this case).

In the main module, there is a Web MVC configuration class that looks like this:

@Configuration
public class WebMvcConfig extends DelegatingWebMvcConfiguration {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // main module interceptors are registered here via
        // registry.addInterceptor(interceptor);
    }

}

Now, in add-on module 1 I have MyFirstCustomInterceptor and in add-on module 2 MySecondCustomInterceptor which I would like to add to the same interceptor registry. I feel like this should be easy but I couldn't find an obvious way to do it when reading through the official Spring MVC documentation.

One approach, that is mentioned in the documentation and that sounded promising, was to use the RequestMappingHandlerMapping bean and it's setInterceptors(Object[] interceptors) method.

I tried that by injecting the bean into an application-started event listener class and adding the custom interceptors through requestMappingHandlerMapping.setInterceptors(myCustomerInterceptorArray). Unfortunately, that didn't quite work. It seems the interceptor is being added but Spring uses another interceptor list - adaptedInterceptors - for the execution chain. Unfortunately, there don't seem to be any public methods available to add an interceptor to the adaptedInterceptors list.

I'm thinking that maybe the RequestMappingHandlerMapping.setInteceptors() method needs to be called earlier, or that there must be a way to extend the WebMvcConfig to the add-on module. But I'm unsure how that would be done.

Edit:

Another idea I just had, is based on injecting a list of all HandlerInterceptor beans. For example:

@Configuration
public class WebMvcConfig extends DelegatingWebMvcConfiguration {

    @Inject private List<HandlerInterceptor> handlerInterceptors;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // Note: the order of the interceptors would likely be an issue here
        for (HandlerInterceptor interceptor : handlerInterceptors) {
            registry.addInterceptor(interceptor);
        }
    }

}

The only problem with this approach would be that there isn't a really good way to order the interceptors. That could be solved with a custom solution, like adding an order annotation on each interceptor class and taking that into account when adding them to the registry. But it still doesn't feel 100% clean. So I'm still hoping there is a better way.

4
  • Just add a bean implementing DelegatingWebMvcConfiguration or extending WebMvcConfigurerAdapter and add it. Just add this class to your module. Don't extend DelegatingWebMvcConfiguration in you root application just add a @Configuration class that is annotated with @EnableWebMvc to customize your configuration you can use the WebMvcConfigurer. All the beans implementing WebMvcConfigurer are considered when the mvc stuff is configured. Commented Jan 29, 2015 at 7:00
  • Thanks for the comment! Not sure I fully understand and I still can't seem to get it working. In my main module I'm extending DelegatingWebMvcConfiguration instead of using the EnableWebMvc annotation because I'm doing some advanced config in there. It was my understanding that having a @Configuration class that extends DelegatingWebMvcConfiguration is the equivalent of using @EnableWebMvc. I tried adding both a @Configuration class that implements WebMvcConfigurer and a bean that implements the same. But for neither one I see the addInterceptors method being called. Commented Jan 30, 2015 at 3:15
  • If you are extending DelegatingWebMvcConfiguration and override some of the method in there the delegating isn't happening anymore. Hence it isn't working. What kind of configuration are you doing? Generally you should not have to extend the DelegatingWebMvcConfiguration and you might want to split things up in adding interceptors and your advanced configuration (but maybe you can add the full configuration class). Commented Jan 30, 2015 at 6:47
  • Thanks, I didn't realize that the default implementation was consulting all configurers and that overriding it would break that functionality. After adding super.addInterceptors(registry) in the override method it looks like it's working as expected. I had to extend DelegatingWebMvcConfiguration a while back because of a limitation on how the message converters could be configured through WebMvcConfigurerAdapter if I remember correctly. I will review and see if that is now unnecessary with the newest Spring version. Thanks again! Commented Jan 30, 2015 at 12:38

1 Answer 1

0

Generally when using Spring MVC you should have a configuration based class with @EnableWebMvc.

This would be in your root configuration

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {        
        // Add the interceptors for the root here.
    }
}

Now in your additional projects just add a configuration class which only adds the interceptors.

@Configuration
public class ModuleAWebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {        
        // Add the interceptors for the Module A here.
    }
}

All WebMvcConfigurers are consulted when configuring Spring @MVC.

In your case however that isn't going to work because you have extended DelegatingWebMvcConfiguration and broke the delegation because you have overriden the addInterceptors method.

The default implementation of that method is

protected void addInterceptors(InterceptorRegistry registry) {
    this.configurers.addInterceptors(registry);
}

Which consults all configurers (the WebMvcConfigurers it detected). However due to your overriden method this isn't happening anymore and the normal extension mechanism isn't working anymore.

Sign up to request clarification or add additional context in comments.

3 Comments

Using this approach, is there any way to add interceptors from different modules to a specific position in the interceptor list? I realize I could add an @Order annotation on the configuration class but that wouldn't give fine-grained control about the position of individual interceptors.
No not really also there shouldn't really be a dependency in your interceptors. That would beat the purpose of having multiple modules each contributing functionality. You can @Order interceptors and inject the full list/collection into your root config (the order should be honored). But as mentioned imho there shouldn't be an importance in the ordering.
Thanks for confirming. For the most part I agree but in some cases I could see an order mechanism on the InterceptorRegistry be useful. Maybe similar to how filters are set on HttpSecurity. But that's not as big of a deal as there is the workaround of injecting the list of interceptors if needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.