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

Improve documentation on applicability of mapped interceptors with the Spring MVC config #31185

Closed
ch-beck opened this issue Sep 7, 2023 · 3 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: documentation A documentation task
Milestone

Comments

@ch-beck
Copy link

ch-beck commented Sep 7, 2023

Affects: 5.3.29 (most likely current as well)

In the documentation for Interceptors in Spring MVC the methods for adding them via WebMvcConfigurer.addInterceptors(InterceptorRegistry) and <mvc:interceptors/> (in XML) are presented as equivalent, which is not strictly true.

Interceptors registered via <mvc:interceptors/> are added as MappedInterceptors to the ApplicationContext to be later picked up by AbstractHandlerMapping.detectMappedInterceptors(List<HandlerInterceptor>) (via initApplicationContext()) and added to the list of Interceptors.

Interceptors configured via WebMvcConfigurer.addInterceptors() (or WebMvcConfigurationSupport) will be directly set as Interceptors via a call to AbstractHandlerMapping.setInterceptors() (in requestMappingHandlerMapping()).

As a result, FlowHandlerMapping (and possibly others) will be aware of Interceptors if these are configured via XML, but not via recommended Java Config.

As far as I understand it, there is one workaround and the possibility to make the configuration explicit.

Workaround

Instead of adding the Interceptor in addInterceptors(), a bean of type MappedInterceptor is defined in the configuration class:

    @Bean
    public MappedInterceptor openSessionInViewInterceptor(SessionFactory sessionFactory) {
        OpenSessionInViewInterceptor interceptor = new OpenSessionInViewInterceptor();
        interceptor.setSessionFactory(sessionFactory);
        return new MappedInterceptor(null, interceptor);
    }

That way the Interceptor gets picked up the same way as being configured via <mvc:interceptors/> (while not being obvious).

Explicit configuration

The Interceptor is configured as bean, added in addInterceptors() and available for usage in other handlers (in this example Spring Web Flows FlowHandlerMapping).

    @Autowired private SessionFactory sessionFactory;

   @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addWebRequestInterceptor(openSessionInViewInterceptor());
    }

    @Bean
    public OpenSessionInViewInterceptor openSessionInViewInterceptor() {
        OpenSessionInViewInterceptor interceptor = new OpenSessionInViewInterceptor();
        interceptor.setSessionFactory(sessionFactory);
        return interceptor;
    }

    @Bean
    public FlowHandlerMapping flowMappings() {
        FlowHandlerMapping mapping = new FlowHandlerMapping();
        // [..]
        mapping.setInterceptors(openSessionInViewInterceptor());
        return mapping;
    }

Proposed Solution

To document this difference in behavior, I would propose another "Note" in the documentation. Something like:

Note: Interceptors configured via <mvc:interceptors/> will be internally wrapped as MappedInterceptors and picked up on initialization. That way all HandlerMappings – even those not from Spring MVC, especially Spring Web Flows FlowHandlerMapping – will configured with those Interceptors.
If you are using Java Configuration you will have to make the Interceptor available as Bean to be explicitly set while configuring other relevant HandlerMappings.

Wishlist

I am aware of the falling out of favor of the "Open Session in View" pattern and prevalent usage of other web technologies not depending on server rendering and therefore Spring Web Flow. At the same time, I think there are many applications out there using these technologies and pattern. Therefore I would appreciate it, if you could use OpenSessionInViewInterceptor as example in your documentation (perhaps even mentioning FlowHandlerMapping) to make it web searchable and obvious, that there is something to consider while switching from XML to Java Config

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Sep 7, 2023
@sbrannen sbrannen added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Sep 7, 2023
@rstoyanchev rstoyanchev self-assigned this Sep 8, 2023
@rstoyanchev rstoyanchev added type: documentation A documentation task and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Sep 8, 2023
@rstoyanchev rstoyanchev added this to the 6.0.12 milestone Sep 8, 2023
@rstoyanchev rstoyanchev changed the title Enhancement for documentation regarding Interceptor configuration in Spring MVC Improve documentation on applicability of mapped interceptors with the Spring MVC config Sep 8, 2023
@rstoyanchev
Copy link
Contributor

Thank you for taking the time to make this suggestion to improve the experience of others. I've added a paragraph to the documentation that clarifies this. While it is an important clarification to make, I also don't want it to overtake the section itself, and did not add any examples. That said I think the summary is sufficiently clear, but do let me know if you have further comments.

@ch-beck
Copy link
Author

ch-beck commented Sep 8, 2023

Thank you for your prompt response!

There is just one spelling error ("conifgure") and I would insert another part to the last sentence:

To re-use the same interceptors across Spring MVC and other framework HandlerMapping
beans with the MVC Java config, either declare MappedInterceptor beans (and don't
manually add them via addInterceptors())
, or configure the same interceptors in both
the Java config and in other HandlerMapping beans.

(just do avoid potentially duplication of Inspectors).

I understand your concern about to much "clutter" with an extended example... I just had a lot of trouble finding the cause of my problems and wasn't able to find anything mentioning FlowHandlerMapping and OpenSessionInViewInterceptor to explain configuration by Java config. Perhaps this issue might be a stand-in in the future.

rstoyanchev added a commit that referenced this issue Sep 8, 2023
@rstoyanchev
Copy link
Contributor

I've made the suggested update.

I do understand the point about mentioning FlowHandlerMapping and OpenSessionInViewInterceptor specifically but there are other HandlerMapping implementations too and it wouldn't be feasible to solve the issue in this way. This issue here however will come up on searches as you mentioned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: documentation A documentation task
Projects
None yet
Development

No branches or pull requests

4 participants