Search code examples
javaspringspring-bootspring-security

corsFilter bean is not created due to BeanNotOfRequiredTypeException


I have a pretty typical method which would create a corsFilter bean in SpringBoot App, but when my server starts, I see the error saying BeanNotOfRequiredTypeException? Any help? Thanks

@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
    CorsConfiguration corsConfig = new CorsConfiguration();
    corsConfig.setAllowCredentials(true);
    corsConfig.setAllowedOrigins(delimitedStringToList(corsFilterAllowedOrigins));
    corsConfig.setAllowedHeaders(delimitedStringToList(corsFilterAllowedHeaders));
    corsConfig.setAllowedMethods(delimitedStringToList(corsFilterAllowedMethods));

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration(corsFilterAllowedPathPattern, corsConfig);


    FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
    bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return bean;`
}

Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'corsFilter' is expected to be of type 'org.springframework.web.filter.CorsFilter' but was actually of type 'org.springframework.boot.web.servlet.FilterRegistrationBean' at org.springframework.beans.factory.support.AbstractBeanFactory.adaptBeanInstance(AbstractBeanFactory.java:417) ~[spring-beans-5.3.29.jar:5.3.29]

the trace goes to SpringBoot framework and thus it is difficult to troubleshoot.Read a lot in the internet, but no luck


Solution

  • Your code register a bean named corsFilter of type FilterRegistrationBean<CorsFilter> but according to the exception message Spring searches for a bean named corsFilter of type CorsFilter.

    You could try to change your code to

    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.setAllowCredentials(true);
        corsConfig.setAllowedOrigins(delimitedStringToList(corsFilterAllowedOrigins));
        corsConfig.setAllowedHeaders(delimitedStringToList(corsFilterAllowedHeaders));
        corsConfig.setAllowedMethods(delimitedStringToList(corsFilterAllowedMethods));
    
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration(corsFilterAllowedPathPattern, corsConfig);
    
        return new CorsFilter(source);    
    }
    

    Or, if you want to register the cors filter yourself you need to rename the bean:

    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilterRegistration() {
        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.setAllowCredentials(true);
        corsConfig.setAllowedOrigins(delimitedStringToList(corsFilterAllowedOrigins));
        corsConfig.setAllowedHeaders(delimitedStringToList(corsFilterAllowedHeaders));
        corsConfig.setAllowedMethods(delimitedStringToList(corsFilterAllowedMethods));
    
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration(corsFilterAllowedPathPattern, corsConfig);
    
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }
    

    Which variant you want to implement will depend on your needs:

    • Spring usually orders their filter beans the way they think its best - if this is sufficient I would go with their default order
    • If your needs differ from that you need to go with the manual filter registration

    Is "corsFilter" some sort of "reserved word" / "reserved bean name"?

    One could call it a "reserved bean name":

    • Once you @EnableWebSecurity Spring Security uses HttpSecurity
    • HttpSecurity uses a CorsConfigurer to add a CorsFilter to the Spring Security chain
    • CorsConfigurer searches for a bean named "corsFilter". If it finds one it assumes that this is the CorsFilter it should configure and expects it to be of type CorsFilter.