FilterConfig ‐ Registering Multiple Filters - Yash-777/MyWorld GitHub Wiki

spring.main.allow-bean-definition-overriding=true

FilterRegistrationBean especially useful when:

  • You have multiple filters and want to control their execution order.
  • You want fine-grained control over filter registration (like applying it only to specific URL patterns).
  • You want to configure filters without relying on annotations like @WebFilter (which require @ServletComponentScan and sometimes don’t work well with Spring-managed beans).
@Bean
public FilterRegistrationBean myFilterRegistration() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new MyFilter());
    registration.addUrlPatterns("/api/*");
    registration.setOrder(1); // lower value = higher priority
    return registration;
}

⚠️ Problem: The error you're encountering is due to duplicate bean names. Both of your configuration classes — InboundIntegrationFilterConfig and LoggerFilterConfig — define a @Bean method named servletRegistrationBean. Since Spring uses the method name as the bean name by default, it causes a conflict when Spring tries to register both beans under the same name.

Since spring.main.allow-bean-definition-overriding=false (default in Spring Boot 2.1+ and enforced in Spring Boot 3.x), Spring throws a BeanDefinitionOverrideException to avoid this ambiguous setup.

So, you're effectively doing this:

@Bean // bean name: "servletRegistrationBean"
public FilterRegistrationBean servletRegistrationBean() { ... }

Hence, Spring tries to register two beans with the same name and fails.

@Configuration
public class InboundIntegrationFilterConfig {

    @Bean
    public FilterRegistrationBean servletRegistrationBean() {
        final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        final InboundIntegrationFilter inboundIntegrationFilter = new InboundIntegrationFilter();
        registrationBean.setFilter(inboundIntegrationFilter);
        registrationBean.setOrder(3);
        return registrationBean;
    }

}
@Configuration
public class LoggerFilterConfig {

    @Bean
    public FilterRegistrationBean servletRegistrationBean() {
        final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        final LoggerFilter loggerFilter = new LoggerFilter();
        registrationBean.setFilter(loggerFilter);
        registrationBean.setOrder(2);
        return registrationBean;
    }

}
ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: 
org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'servletRegistrationBean' 
defined in class path resource [LoggerFilterConfig.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; 
lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=loggerFilterConfig; 
factoryMethodName=servletRegistrationBean; initMethodName=null; destroyMethodName=(inferred); defined in class path resource 
[LoggerFilterConfig.class]] for bean 'servletRegistrationBean': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=null; 
autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=inboundIntegrationFilterConfig; 
factoryMethodName=servletRegistrationBean; initMethodName=null; destroyMethodName=(inferred); defined in class path resource 
[InboundIntegrationFilterConfig.class]] bound.

Description:

The bean 'servletRegistrationBean', defined in class path resource [LoggerFilterConfig.class], could not be registered. 
A bean with that name has already been defined in class path resource [InboundIntegrationFilterConfig.class] and overriding is disabled.

Action:

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

🔴 However, this just masks the conflict instead of resolving it. You’ll only retain one of the beans (whichever Spring loads last), which is usually not what you want.

🔍 Root Cause Solutions:

Option 1: Rename the Beans

Give each bean a unique name using either:

  • A different method name (Spring uses it as the bean name), or
  • Specify an explicit bean name using the @Bean("customName") annotation.

Change the method name (or use @Bean(name = "...")) to give them distinct bean names.

📝 Spring will detect and register each FilterRegistrationBean inside the list automatically.

@Configuration
public class FilterConfig {

    @Bean
    public List<FilterRegistrationBean<?>> filterRegistrationBeans() {
        List<FilterRegistrationBean<?>> filters = new ArrayList<>();

        // Logger Filter
        FilterRegistrationBean<LoggerFilter> loggerFilter = new FilterRegistrationBean<>();
        loggerFilter.setFilter(new LoggerFilter());
        loggerFilter.setOrder(1); // lower value = higher priority
        loggerFilter.addUrlPatterns("/*"); // loggerFilter.addUrlPatterns("/api/*");
        filters.add(loggerFilter);

        // Inbound Integration Filter
        FilterRegistrationBean<InboundIntegrationFilter> inboundFilter = new FilterRegistrationBean<>();
        inboundFilter.setFilter(new InboundIntegrationFilter());
        inboundFilter.setOrder(2); // lower value = higher priority
        inboundFilter.addUrlPatterns("/*");
        filters.add(inboundFilter);

        return filters;
    }
}

This is the recommended approach because it's explicit and avoids hidden overrides.

Option 2: Allow Overriding (Not Recommended for Production)

You could also allow Spring to override bean definitions by adding this to your application.properties:

spring.main.allow-bean-definition-overriding=true

But this just silences the error, and whichever bean is registered last will silently overwrite the first one. This could introduce unpredictable behavior.