In order to customise Spring Boot for Grails users, Grails overrides a few Spring Boot beans. This is seemingly disallowed in newer versions of Spring Boot.

To resolve this I attempted to add:

spring:
    main:
        allow-bean-definition-overriding: true

However this leads to:

Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.springframework.boot.origin.OriginTrackedValue] to type [boolean]
        at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321)
        at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194)
        at org.springframework.boot.context.properties.bind.BindConverter$CompositeConversionService.convert(BindConverter.java:179)

This is currently blocking me from upgrading Grails 4.x to Spring Boot 2.1.x

Comment From: graemerocher

I have found a workaround by calling setAllowBeanDefinitionOverriding directly, however the issue still stands for existing users

Comment From: wilkinsona

This sounds like a bug that we should fix, but I'd take a different approach to overriding beans if you can. We have a few places in Boot where we still need to override a bean, and we now do so by removing the old definition before adding a new one. I'd recommend taking the same approach in Grails so that the behaviour of the whole application context does not need to be changed.

Comment From: graemerocher

We will see how we can minimise overriding. Thanks for the feedback.

Comment From: wilkinsona

I can't reproduce the behaviour you've described with a minimal application:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
public class Gh14831Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Gh14831Application.class, args);
        System.out.println(context.getBean("one"));
    }


    @Configuration
    public class ConfigurationOne {

        @Bean
        public String one() {
            return "one";
        }
    }

    @Configuration
    public class ConfigurationTwo {

        @Bean
        public String one() {
            return "one-again";
        }
    }

}

It fails to start without the property set:


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::             (v2.1.0.M4)

2018-10-15 16:46:09.729  INFO 15172 --- [           main] com.example.demo.Gh14831Application      : Starting Gh14831Application on Andys-MacBook-Pro.local with PID 15172 (/Users/awilkinson/dev/workspaces/spring-projects/spring-boot/master/gh-14831/target/classes started by awilkinson in /Users/awilkinson/dev/workspaces/spring-projects/spring-boot/master/gh-14831)
2018-10-15 16:46:09.732  INFO 15172 --- [           main] com.example.demo.Gh14831Application      : No active profile set, falling back to default profiles: default
2018-10-15 16:46:09.914  WARN 15172 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'one' defined in com.example.demo.Gh14831Application$ConfigurationTwo: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=com.example.demo.Gh14831Application$ConfigurationTwo; factoryMethodName=one; initMethodName=null; destroyMethodName=(inferred); defined in com.example.demo.Gh14831Application$ConfigurationTwo] for bean 'one': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=com.example.demo.Gh14831Application$ConfigurationOne; factoryMethodName=one; initMethodName=null; destroyMethodName=(inferred); defined in com.example.demo.Gh14831Application$ConfigurationOne] bound.
2018-10-15 16:46:09.922  INFO 15172 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-10-15 16:46:09.924 ERROR 15172 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

The bean 'one', defined in com.example.demo.Gh14831Application$ConfigurationTwo, could not be registered. A bean with that name has already been defined in com.example.demo.Gh14831Application$ConfigurationOne and overriding is disabled.

Action:

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

And starts as expected when it is set:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::             (v2.1.0.M4)

2018-10-15 16:46:54.617  INFO 15197 --- [           main] com.example.demo.Gh14831Application      : Starting Gh14831Application on Andys-MacBook-Pro.local with PID 15197 (/Users/awilkinson/dev/workspaces/spring-projects/spring-boot/master/gh-14831/target/classes started by awilkinson in /Users/awilkinson/dev/workspaces/spring-projects/spring-boot/master/gh-14831)
2018-10-15 16:46:54.620  INFO 15197 --- [           main] com.example.demo.Gh14831Application      : No active profile set, falling back to default profiles: default
2018-10-15 16:46:54.992  INFO 15197 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2018-10-15 16:46:55.016  INFO 15197 --- [           main] com.example.demo.Gh14831Application      : Started Gh14831Application in 0.631 seconds (JVM running for 0.909)
one-again
2018-10-15 16:46:55.018  INFO 15197 --- [       Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

We also have a pair of tests that verify the behaviour: https://github.com/spring-projects/spring-boot/blob/ffe5e88d8e5de245b8e040190e90a22eb47fe379/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java#L1209-L1223

Can you please provide a minimal sample that reproduces the behaviour you've described?

Comment From: graemerocher

Will track it down.. maybe it is something related to how we handle property sources.

Comment From: graemerocher

Ok turns out this was a custom GroovyPropertySourceLoader that was leaking OriginTrackedValues

Comment From: ghost

I am trying to track down a similar issue in our application.

@graemerocher could you provide a bit more detail as to how you defined/created GroovyPropertySourceLoader for it to cause the issue? This would help me track down which one of our SourceLoaders is messing with the startup.

Thank you.

Comment From: mikebell90

I've been trying to get your example @wilkinsona working, and can't. Debug shows the postprocessor is never called.

Here's the sample class. The motivation (maybe wrongly) has been for a long time people that had tests with mixed contexts could Import this class to clear out their JMX beans, to avoid the mbean already registered error (RegistrationPolicy other than default isn't an option - we feel most of the time this SHOULD fail) but as of Spring Boot 2.1 this fails with mbeanExporter being a duplicate bean.

Note: Moving @Bean of foo to outer class makes no difference.

@Configuration
@EnableMBeanExport
@Import(TestMBeanServerConfiguration.InnerTestMBeanServerConfiguration.class)
public class TestMBeanServerConfiguration {
    @Configuration
    public static class InnerTestMBeanServerConfiguration extends MBeanExportConfiguration {
        private final MBeanServer mbs = MBeanServerFactory.createMBeanServer();

        @Bean
        public static Foo foo() {
            return new Foo();
        }
        @Bean
        @Primary
        public MBeanServer getTestMBeanServer() {
            return mbs;
        }

        @Override // This makes Spring Boot 2.1 unhappy and was always fragile
        public AnnotationMBeanExporter mbeanExporter() {
            final AnnotationMBeanExporter amber = super.mbeanExporter();
            amber.setServer(mbs);
            return amber;
        }
    }

    @Order(Ordered.LOWEST_PRECEDENCE)
    public static class Foo implements BeanDefinitionRegistryPostProcessor {

        @Override
        public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry registry) throws BeansException {
            System.err.println("hi"); // will never be called
        }

        @Override
        public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.err.println("hi"); // will never be called
        }
    }
}

Comment From: snicoll

@mikebell90 I am don't understand how the changes with MBeans export is related to this issue. If you have a sample that reproduces the issue (i.e. works with 2.0.x and breaks with 2.1.x), please create a separate issue with a reference to the sample we can clone or unzip and run ourselves. Thanks!

Comment From: kepha-korbit

`


APPLICATION FAILED TO START


Description:

The bean 'documentationPluginsManager', defined in class path resource [kr/co/korbit/gia/config/SwaggerConfig.class], could not be registered. A bean with that name has already been defined in URL [jar:file:/Users/kepha_local/.gradle/caches/modules-2/files-2.1/io.springfox/springfox-spring-web/2.9.2/ed2ed714a6cba8804d00f80f0534901e4c7a3211/springfox-spring-web-2.9.2.jar!/springfox/documentation/spring/web/plugins/DocumentationPluginsManager.class] and overriding is disabled.

Action:

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

Process finished with exit code 1`

I have same error even though adding spring.main.allow-bean-definition-overriding=true into application.yml

Comment From: stopme

Environment variables : spring.main.allow-bean-definition-overriding=true

System.getenv() System.getProperties()

Comment From: leomont

@wilkinsona I could replicate the issue long time after you requested: The bean 'XXXXX', defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled.

Once I tried to add spring.main.allow-bean-definition-overriding=truetoapplication.ymlfile

SpringBoot Impossible to set spring.main.allow-bean-definition-overriding=true in v2.1.0.M4

It effectively was not allowed. So then I found I was using JPA and JDBC dependencies on pom.xml in a concurrent way, overlapping base packages. I Solved the issue just leaving one of those, as it follows for my particular case:

SpringBoot Impossible to set spring.main.allow-bean-definition-overriding=true in v2.1.0.M4

I could inferred this from a previous forum https://coderanch.com/t/747155/java/bean-defined-myRepository