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

Duplicate calls of a custom HandlerInterceptor's methods after updating to Spring Data REST 3.4 #1955

Closed
lwitzani opened this issue Jan 12, 2021 · 10 comments
Assignees
Labels
type: bug A general bug

Comments

@lwitzani
Copy link

Hi,
Background:
We have a Spring Boot project and recently updated our dependencies from Spring Boot 2.3.7.RELEASE to 2.4.0!
Spring Framework therefore changed from 5.2.12.RELEASE to 5.3.1

Use case:
We have a custom interceptor (let's call it ActivityLoggerInterceptor) that implements org.springframework.web.servlet.HandlerInterceptor
We are registering the interceptor similar to the following:

@Configuration
public class WebMvcConfig {

    @Bean
    public MappedInterceptor mappedInterceptor() {
        return new MappedInterceptor(
                new String[]{"/api/**"},
                new ActivityLoggerInterceptor()
        );
    }
}

This worked perfectly on Spring Boot 2.3.7.RELEASE / Spring 5.2.12.RELEASE meaning the handler methods preHandle and afterCompletion were called once per request.

The issue:
After updating to Spring Boot 2.4.0 / Spring 5.3.1 the methods preHandle and afterCompletion in our interceptor are each called twice

Observations:
After some debugging i found that our Interceptor is somehow now found twice (see the picture below).
duplicateInterceptorCalls

From there it goes deep into Spring ...
Because of this and because i did not find anything that our registration of the Interceptor could be wrong now, i am writing this issue.
Looking through the closed and open issues i did not find anything that would match this problem. But it seems that something around MappedInterceptors has changed in Spring.

Can you help me somehow :)? Thanks so much!

Best regards,
Lukas

@rstoyanchev
Copy link
Contributor

It looks like it's not as simple as adding such a bean to a Boot 2.4.1 application. Any more details on how to reproduce or if you can provide a sample? You can also try debugging in AbstractHandlerMapping#initApplicationContext to see how the interceptor chain gets initialized.

@lwitzani
Copy link
Author

Hi,
thanks for answering!

I made a sample project that reproduces the issue. You can find it here https://github.com/lwitzani/springIssue26378
The project has two branches where the only difference is the used Spring Boot version.
I did not debug into AbstractHandlerMapping yet but will do now.

Best regards,
Lukas

@lwitzani
Copy link
Author

It seems that on application start in class RepositoryRestMvcConfiguration in method restHandlerMapping() in both branches the result is equal (repositoryMapping has my interceptor in adaptedInterceptors as well as basePathMapping has my my interceptor in adaptedInterceptors).

So when doing the post request i noticed that on the branch with the old version
Class: AbstractHandlerMapping
Method: public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Line: HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request); is called once and afterwards the interceptors are added to the list in Class: HandlerExecutionChain in the method
public void addInterceptor(HandlerInterceptor interceptor) { this.interceptorList.add(interceptor); }

This is only done once in the old version.

When switching to the new version, this process is done twice for (i think) both of the delegates in the class DelegatingHandlerMapping. The delegates are from my understanding the former mentioned repositoryMapping and basePathMapping (which as mentioned above both have my custom interceptor in their adaptedInterceptors). So this results in adding the custom interceptor twice to the same list.

Whole thing is unfortunately more like searching in the dark for me.

@rstoyanchev
Copy link
Contributor

Thanks for the sample. This looks like a possible bug in Spring Data REST. Its DelegatingHandlerMapping delegates to another HandlerMapping which returns the HandlerExecutionResult with interceptors, but then the base AbstractHandlerMapping still adds (the same) interceptors again. I'll reach out to the Spring Data team to confirm.

@odrotbohm
Copy link
Member

Just a quick heads up: the issue stems from Spring Data REST's move to let DelegatingHandlerMapping extend AbstractHandlerMapping instead of only implementing HandlerMapping directly. This causes DHM to also trigger the interceptor discovery and those then invoked in addition to the ones discovered for the handler mapping ultimately invoked.

I'll move the ticket to Spring Data REST for a fix.

@odrotbohm odrotbohm transferred this issue from spring-projects/spring-framework Jan 14, 2021
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jan 14, 2021
@odrotbohm odrotbohm added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Jan 14, 2021
@odrotbohm odrotbohm self-assigned this Jan 14, 2021
odrotbohm added a commit that referenced this issue Jan 14, 2021
We actually do not want to inherit all the functionality implemented in AbstractHandlerMapping. The sole reason we did so before was to override the method to propagate the PathPatternResolver to the downstream HandlerMappings. We now just declare the method on DHM directly.

Fixes GH-1955.
@odrotbohm odrotbohm added this to the 3.4.4 (2020.0.4) milestone Jan 14, 2021
@odrotbohm
Copy link
Member

This in place. Feel free to give the snapshots a try.

@lwitzani
Copy link
Author

I just tried it with 3.4.4-SNAPSHOT of branch "3.4.x" and 3.5.0-SNAPSHOT of branch "master" and can confirm that it works in both cases.

Thanks for fixing this so quickly. Issue should be resolved with the 3.4.4 release! Nice job!

@odrotbohm odrotbohm changed the title Duplicate calls of a custom HandlerInterceptor's methods after updating spring to 5.3.1 Duplicate calls of a custom HandlerInterceptor's methods after updating to Spring Data REST 3.4 Jan 15, 2021
@orubel
Copy link

orubel commented Mar 28, 2022

I believe (from just now reading the fix) that this is also effecting SimpleUrlHandlerMapping; Noticed this hasn't been added to SimpleUrlHandlerMapping and I am seeing this error:

SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.registerHandlers(urlMap)
mapping.setUrlMap(urlMap);
mapping.setOrder(1);
mapping.setInterceptors(new Object[]{ new ApiInterceptor() })
mapping.setApplicationContext(context);
mapping.initApplicationContext()

@odrotbohm
Copy link
Member

SimpleUrlHandlerMapping is part of Spring MVC. If you think, you have identified an issue with it, please file a ticket in the Spring MVC tracker.

@orubel
Copy link

orubel commented Mar 29, 2022

will do. Thx.

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

No branches or pull requests

5 participants