Unexpected constructor-based initialization of @ConfigurationProperties leads to inconsistent behavior
See original GitHub issueConsider the following test case:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { BindingTest.Config.class })
@EnableConfigurationProperties
@TestPropertySource
public class BindingTest {
@Autowired FooProperties fooProperties;
@Test
public void shouldInjectBar() {
assertThat(fooProperties.getBar()).isEqualTo("baz");
}
@Configuration
public static class Config {
@Bean
public FooProperties fooProperties() {
return new FooProperties();
}
}
@ConfigurationProperties("foo")
@Validated
public static class FooProperties {
@NotNull @Getter @Setter
private String bar;
public FooProperties() {}
public FooProperties(String bar) { // (1)
this.bar = bar;
}
}
}
BindingTest.properties
:
foo.bar=baz
foo=unrelated # (2)
I expected fooProperties.bar
to be populated, or, at least, @NotNull
validation error to be thrown.
However, in presence of single argument constructor (1) and conflicting property (2) (it may be, for example, a totally unrelated system environment variable), I got the following:
fooProperties.bar
isnull
- no validation error is thrown
This happens because Binder
decides to use ObjectToObjectConverter
to initialize FooProperties
using its single argument constructor (despite the fact that FooProperties
is explicitly created in @Bean
method), creates new instance of FooProperties
and applies validation to it, but ConfigurationPropertiesBindingPostProcessor
ignores that new instance.
This applies to Spring Boot 2.0.x, 2.1.x, 2.2.x.
Issue Analytics
- State:
- Created 5 years ago
- Comments:14 (14 by maintainers)
Top Results From Across the Web
The Definitive Guide to the Microsoft Enterprise Library
developer, Keenan has always been on the leading edge—sometimes ... reduce the chances of unexpected behavior, it is a good idea to put...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
@Raheela1024 As @wilkinsona mentioned here, we want to ignore any property that matches the prefix of the
@ConfigurationProperties
bean that we’re binding to. For example, we want to bindfoo.*
to something with afoo
prefix, but to ignore afoo
property if one is set. This would be a change in theBinder
class. It looks like the change is a bit more involved than we originally thought as quite a few tests would need to be updated. We really appreciate your offer to help but we’d like to tackle this one ourselves.@mbhave Sorry i was busy but now looking into will update shortly.