Alex Pritchard
Alex Pritchard

Reputation: 4250

Cannot override or disable spring boot-instantiated Filter, resulting in duplicate entries in filter chain

I have a component class:

public class FooFilter implements Filter {
    private FooService fooService; //spring-injected dependency
    @Override public void init(FilterConfig filterConfig) {}
    @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain){}
    @Override public void destroy() {}
}

Defined in a springConfigured.xml:

<context:spring-configured />
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <bean class="com.foo.filter.FooFilter" scope="prototype" autowire="byType"/>

</beans>

The filter is configured in our filter chain using a FilterRegistrationBean:

@Configuration
public class FooFilterRegistrationConfig {
    private List<String> URL_PATTERNS = Arrays.asList("foo", "bar");
    @Bean
    public FilterRegistrationBean fooFilter(FooFilter filter) {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(filter);
        registration.setName("FooFilter");
        registration.setUrlPatterns(URL_PATTERNS);
        registration.setOrder(4);
        return registration;
    }

    //and some more
}

Using this set up, we end up with two FooFilters in our filter chain. Log:

//a bunch of filters
2017-10-16 16:34:37,468 [RMI TCP Connection(3)-127.0.0.1] INFO  servlet.FilterRegistrationBean - Mapping filter: 'FooFilter' to urls: [*.jsp, *.do, *.faces, *.action, /mvc/*]
//some more filters
2017-10-16 16:34:37,468 [RMI TCP Connection(3)-127.0.0.1] INFO  servlet.FilterRegistrationBean - Mapping filter: 'com.foo.web.filter.FooFilter#0' to: [/*]

Some other answers to questions like this one suggest disabling the filter using a RegistrationConfig. If I try to disable the filter in the FilterRegistrationConfig using registration.setEnabled(false), I still get the additional filter at the end.

2017-10-16 16:22:46,078 [RMI TCP Connection(3)-127.0.0.1] INFO  servlet.FilterRegistrationBean - Filter FooFilter was not registered (disabled)
...
2017-10-16 16:22:46,079 [RMI TCP Connection(3)-127.0.0.1] INFO  servlet.FilterRegistrationBean - Mapping filter: 'com.foo.filter.FooFilter#0' to: [/*]

I've tried removing the reference to this filter in our FilterRegistrationConfig entirely and just using the @Orderannotation on the FooFilter class directly, but because we're specifying this bean in our xml and not using component scan, I can't seem to get @WebFilterannotation to correctly apply Url Patterns.

Any tips on how to get rid of this spring boot-created FooFilter#0 from my filter chain would be much appreciated!

Edit:

I've tried removing the bean definition from the xml. Now I cannot inject it into the FilterRegistrationBean method, since that gives me the "no beans of 'FooFilter' type found" error.

@Bean
public FilterRegistrationBean fooFilter(FooFilter filter) { //no beans of 'FooFilter' type found
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(filter);
    registration.setName("FooFilter");
    registration.setUrlPatterns(URL_PATTERNS);
    registration.setOrder(4);
    return registration;
}

If I manually instantiate a FooFilter here, however, I run into problems later because FooFilter contains a number of spring-managed dependencies which aren't being injected:

@Bean
public FilterRegistrationBean fooFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new FooFilter()); //works fine here, but Spring does not inject dependencies into this object I created, so null pointers later
    registration.setName("FooFilter");
    registration.setUrlPatterns(URL_PATTERNS);
    registration.setOrder(4);
    return registration;
}

Upvotes: 0

Views: 2155

Answers (1)

surya
surya

Reputation: 2749

FilterRegistrationBean creates your FooFilter bean, you dont have to create it separately, Remove bean for FooFilter ( following line )

<bean class="com.foo.filter.FooFilter" scope="prototype" autowire="byType"/>

Note : When spring container creates the bean FilterRegistrationBean, it also creates a bean FooFilter as you have mentioned.
registration.setName("FooFilter"); // FooFilter is the name of the bean

Upvotes: 1

Related Questions