Here the scenarios is - Filter1 -> filter2 -> Filter3 -> Controller

If filter 1 - (condition == true ) then skip all filters and go to controller - request.getRequestDispatcher(request.getServletPath()).forward(request, response); else go to next chain in filter filterChain.doFilter(request, response);

With spring-boot 2.3.* - Its not working as with condition-1, it always going in filter-chain but with spring-boot version till 2.2.10- its working as expected.

Please advise ?

Comment From: rstoyanchev

Could you provide a sample to work with?

Comment From: mdeinum

Since Spring Boot 2.3 all OncePerRequestFilters are attached to all dispatch types. See https://github.com/spring-projects/spring-boot/issues/18953 for the discussion on that.

Comment From: hakuna16

Could you provide a sample to work with?

https://github.com/hakuna16/Spring-Boot-Sample-Project/tree/master Here you can find out the dummy project setup for this scenario.

In the Read me you can find out how to replicate the issue.

More Information https://github.com/hakuna16/Spring-Boot-Sample-Project/blob/master/README.md

Comment From: hakuna16

@rstoyanchev please find the attached sample project.

Also Please let me know if you need direct code here instead of the sample code.

Also Please provide your sugessions.

Comment From: nitinit

Its working fine after overriding this method-shouldNotFilterAsyncDispatch from filter class.

Comment From: nitinit

I debugged this issue and found that due to this change at

org.springframework.boot.web.servlet.AbstractFilterRegistrationBean All dispatch types are attached with OncePerRequestFilter

protected void configure(FilterRegistration.Dynamic registration) {
        super.configure(registration);
        EnumSet<DispatcherType> dispatcherTypes = this.dispatcherTypes;
        if (dispatcherTypes == null) {
            T filter = getFilter();
            if (ClassUtils.isPresent("org.springframework.web.filter.OncePerRequestFilter",
                    filter.getClass().getClassLoader()) && filter instanceof OncePerRequestFilter) {
                dispatcherTypes = EnumSet.allOf(DispatcherType.class);
            }
            else {
                dispatcherTypes = EnumSet.of(DispatcherType.REQUEST);
            }
        }

so all filters execution are happening with request dispatch as forward as configured with all dispatch types as per this code-

org.apache.catalina.core.ApplicationFilterFactory.createFilterChain(ServletRequest, Wrapper, Servlet)  

As this will include all filters with request dispatch-type as forward.

Presently done changes with customising registering bean with FilterRegistrationBean and explicitly defining filter dispatcher type with request only.

Anything configurable solution ? as have to change all filter to be explicitly declared and registered as bean.

Comment From: hakuna16

@spring-issuemaster ??

Comment From: rstoyanchev

@hakuna16, the idea with the change in Boot is that a OncePerRequestFilter should know what dispatcher types it handles based on its internal protected methods and checks and therefore it can be registered for all.

You will need to encode it in your filter somehow. For example both Filter2 and Filter3 could check for the "Test" header and either participate or not. Or Filter3 could skip FORWARD dispatcher type, etc.

Comment From: hakuna16

@rstoyanchev Don't you think it's a kind of hack we are having in the code?

What if we make it somehow configurable for the dispatcher types??

Comment From: rstoyanchev

@hakuna16 in my experience whether a Filter cares about a particular dispatch type depends on the nature of what it does and not on the details of a specific request. Hence OncePerRequestFilter exposes methods to indicate whether the concrete sub-class supports ASYNC or ERROR dispatch types. In turn Boot registers all OncePerRequestFilter for all dispatcher types since such filters support all dispatch types, in the sense of being prepared to do process or skip.

I do think that your current solution is somewhat unusual. Having one Filter cause the next one to be bypassed and doing so by forwarding where that the next Filter is not involved in FORWARD dispatches. If that is indeed your goal, I think passing a hint from the first to the second filter (like a request attribute), is probably a more accurate way to model this but I don't have a full grasp of your context, and there might be other ways too to structure the code.

I would also ask does your second filter really need to extend OncePerRequestFilter? I'm not sure what you're gaining from it and Boot wouldn't automatically register your filter for all dispatcher types if it wasn't a OncePerRequestFilter for which it makes more assumptions.