spring.main.allow-bean-definition-overriding=true is ignored and ConflictingBeanException is thrown

Viewed 3283

I am working on a spring-boot application with version 2.2.0.

I wanted to override a bean, which spring-boot provides by default. So I tried spring.main.allow-bean-definition-overriding=true in my workflow.properties file.

The code is same in both java files, one whose bean is provided by default and the one which I have created. The only difference is, the java file that I have created will load the resource which I provide it, instead of loading the default resource by default bean(from spring-boot).

I am loading workflow.properties like this in my main Application which extends org.springframework.boot.web.servlet.support.SpringBootServletInitializer:

@Override
protected SpringApplicationBuilder configure( SpringApplicationBuilder application )
{
    application.application().setDefaultProperties( getProperties() );
    return application.sources( WorkflowServiceApplication.class );
}

public static void main( String[] args )
    {
        // SpringApplication.run( WorkflowServiceApplication.class, args );
        new SpringApplicationBuilder( WorkflowServiceApplication.class ).properties( "spring.config.name:workflow" )
                                                                        .build()
                                                                        .run( args );
    }

static Properties getProperties()
{
    Properties props = new Properties();

    props.put( "spring.config.name", "workflow" );

    props.put( "spring.config.location", "../conf/" );
    return props;
}

But I'm still getting the same ConflictingBeanException

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'stencilSetResource' for bean class [org.flowable.ui.modeler.rest.app.StencilSetResource] conflicts with existing, non-compatible bean definition of same name and class [com.myApplication.workflow.workflowservice.controllers.StencilSetResource]
    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:349) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:287) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:290) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:245) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:587) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    ... 15 common frames omitted

After checking in spring-boot documentation, I think that by default bean definition overriding is false, but why does the overriding not work even if I set it to true in my properties file?

Edit: After going through this documentation, it looks like the configuration that tells Environment to read properties from workflow.properties instead of application.properties happens after ApplicationContext is refreshed. Also a couple of properties like spring.main.* are read and loaded to Environment before ApplicationContext refresh happens. The link suggests to load property source into Environment by implementing EnvironmentPostProcessor, so I'll try that and see how it goes.

Edit 2: Okay so I tried the approach given in documentation link in above edit:

@Order( Ordered.LOWEST_PRECEDENCE )
public class CustomEvironmentPostProcesor implements EnvironmentPostProcessor
{
    private static final String DEFAULT_MY_FRAMEWORK_PROPERTIES = "workflowProperties";
    private static final String DEFAULT_MY_FRAMEWORK_PROPERTIES_LOCATION = "/workflow.properties";

    private PropertiesPropertySourceLoader propertySourceLoader = new PropertiesPropertySourceLoader();

    @Override
    public void postProcessEnvironment( ConfigurableEnvironment environment,
                                        SpringApplication application )
    {
        Resource workflowProperties = new ClassPathResource( DEFAULT_MY_FRAMEWORK_PROPERTIES_LOCATION );
        List<PropertySource<?>> propertySource;
        try
        {
            propertySource = propertySourceLoader.load( DEFAULT_MY_FRAMEWORK_PROPERTIES, workflowProperties );
            if( propertySource != null )
            {
                environment.getPropertySources().addLast( propertySource.get( 0 ) );
            }
        }
        catch( IOException e )
        {
            e.printStackTrace();
        }
    }
}

I can see my workflow.properties getting loaded in Environment instance passed in postProcessEnvironment method.

But still, I get the same exception.

0 Answers
Related