New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
graemerocher opened this Issue Oct 15, 2018 · 6 comments

Comments

Projects
None yet
3 participants
@graemerocher
Contributor

graemerocher commented Oct 15, 2018

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

@graemerocher

This comment has been minimized.

Contributor

graemerocher commented Oct 15, 2018

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

@wilkinsona

This comment has been minimized.

Member

wilkinsona commented Oct 15, 2018

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.

@graemerocher

This comment has been minimized.

Contributor

graemerocher commented Oct 15, 2018

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

@wilkinsona

This comment has been minimized.

Member

wilkinsona commented Oct 15, 2018

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:

@Test
public void beanDefinitionOverridingIsDisabledByDefault() {
assertThatExceptionOfType(BeanDefinitionOverrideException.class).isThrownBy(
() -> new SpringApplication(ExampleConfig.class, OverrideConfig.class)
.run());
}
@Test
public void beanDefinitionOverridingCanBeEnabled() {
assertThat(
new SpringApplication(ExampleConfig.class, OverrideConfig.class)
.run("--spring.main.allow-bean-definition-overriding=true",
"--spring.main.web-application-type=none")
.getBean("someBean")).isEqualTo("override");
}

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

@graemerocher

This comment has been minimized.

Contributor

graemerocher commented Oct 15, 2018

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

@graemerocher

This comment has been minimized.

Contributor

graemerocher commented Oct 16, 2018

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment