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
FilterRegistrationBeaninside 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.