-
Notifications
You must be signed in to change notification settings - Fork 40.9k
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
@ConfigurationProperties on a @Bean method does not work when the bean has a constructor that is eligible for constructor binding #33710
Comments
Minimal repro: package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@EnableConfigurationProperties
public class Gh33710Application {
@Bean
@ConfigurationProperties("testprop")
TestProperties testProperties() {
return new TestProperties("1", "2");
}
public static void main(String[] args) {
String prop1 = SpringApplication.run(Gh33710Application.class, "--testprop.prop1=something").getBean(TestProperties.class).getProp1();
System.out.println(prop1);
}
static class TestProperties {
private String prop1;
private String prop2;
public TestProperties(String prop1, String prop2) {
this.prop1 = prop1;
this.prop2 = prop2;
}
public String getProp1() {
return prop1;
}
public void setProp1(String prop1) {
this.prop1 = prop1;
}
public String getProp2() {
return prop2;
}
public void setProp2(String prop2) {
this.prop2 = prop2;
}
}
} The The problem can be worked around by adding |
Thank you for the workaround. Unfortunately, in my case TestProperties is a third party class which I cannot change. I've removed the use of ConfigurationProperties alltogether for now. |
Update `DefaultBindConstructorProvider` so that deduced constructors are not used if there is an existing value. Prior to this commit, constructor detection logic was not compatible with earlier versions of Spring Boot. With Spring Boot 3.0.1, given a class of the following form: @ConfigurationProperties(prefix = "example") public class ExampleProperties { @NestedConfigurationProperty private final NestedProperty nested = new NestedProperty( "Default", "default"); public NestedProperty getNested() { return nested; } } If `NestedProperty` has a single constructor with arguments, constructor binding would be used. In Spring Boot 2.x, setter injection would have been used. The updated code now only uses constructor injection if an explicit `@ConstructorBinding` annotation is present, or if there is no existing value. Fixes gh-33409 See gh-33710
Using Spring Boot 3.0.1, I have the following POJO on which I wish to bind a certain property:
Note that this is a class from a third-party library not under my control. I need to make this available as a Bean, and I wish to set a property on it:
The previous code fails silently, and my property is not set.
It seems as if the new Spring Boot 3 rules regarding automatic ConstructorBinding have something to do with this. If I remove the parameterized constructor from the
TestProperties
class, or if I add a second constructor, the problem goes away and my property is set correctly. However, since I return an already constructed object from the Bean method, I would expect Spring Boot to always use setter binding instead of constructor binding.(This is a simplified example. In reality,
TestProperties
is constructed using a builder, and the parameterized constructor is package private, intended to be used only by that builder.)The text was updated successfully, but these errors were encountered: