I maintain a spring-boot-starter that customizes the error attributes returned when, for instance, an unknown endpoint is called.
This is done by overriding the org.springframework.boot.web.servlet.error.ErrorAttributes bean.
Everything worked fine with 2.0.6, but 2.1.0 disables bean overriding by default, making the starter now fail with the following message.
Invalid bean definition with name 'errorAttributes' defined in class path resource [com/mycompany/springboot/starter/config/ErrorsConfig.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=com.mycompany.springboot.starter.config.ErrorsConfig; factoryMethodName=errorAttributes; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/mycompany/springboot/starter/config/ErrorsConfig.class]] for bean 'errorAttributes': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; factoryMethodName=errorAttributes; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.class]] bound
As explained in the documentation setting the spring.main.allow-bean-definition-overriding property to true fixes the problem.
My question is how to do that in the starter (I do not want the users of my starter to have to change their application.properties file, for something that is specific to my starter)?
I tried to a @PropertySource("classpath:/com/mycompany/starter/application.properties") annotation to my @Configuration with that property defined in that file, but it doesn't work.
What am I missing? Is there any way to allow my configuration to override that bean?
Here is the (simplified) source code of the configuration:
@Configuration
@PropertySource("classpath:/com/mycompany/starter/application.properties")
public class ErrorsConfig {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    @Bean
    public ErrorAttributes errorAttributes() {
        return new DefaultErrorAttributes() {
            @SuppressWarnings("unchecked")
            @Override
            public Map<String, Object> getErrorAttributes(WebRequest request, boolean includeStackTrace) {
                Map<String, Object> errorAttributes = super.getErrorAttributes(request, includeStackTrace);
                // CustomeError is a (simplified) bean of the error attributes we should return.
                CustomError err = new CustomError("myErrorCode", (String) errorAttributes.get("error"));
                return OBJECT_MAPPER.convertValue(err, Map.class);
            }
        };
    }
}
and my resource file com/mycompany/starter/application.properties contains
spring.main.allow-bean-definition-overriding=true
                        
Spring Boot's
ErrorAttributesbean is defined byErrorMvcAutoConfiguration. It is annotated with@ConditionalOnMissingBeanso it will back off if anErrorAttributesbean has already been defined. As the bean defined by yourErrorsConfigclass is attempting to override Boot'sErrorAttributesbean rather than causing it to back off, yourErrorsConfigclass must be getting processed after Boot'sErrorMvcAutoConfigurationclass. This means that you have an ordering problem in your starter.The order in which auto-configuration classes are processed can be controlled using
@AutoConfigureBeforeand@AutoConfigureAfter. Assuming thatErrorsConfigis itself an auto-configuration class registered inspring.factories, you can fix your problem by annotating it with@AutoConfigureBefore(ErrorMvcAutoConfiguration.class). With this change in placeErrorsConfigwill define itsErrorAttributesbean beforeErrorMvcAutoConfigurationattempts to do so which will cause the auto-configuration of Boot'sErrorsAttributebean to back off.