question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unexpected constructor-based initialization of @ConfigurationProperties leads to inconsistent behavior

See original GitHub issue

Consider 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 is null
  • 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:closed
  • Created 5 years ago
  • Comments:14 (14 by maintainers)

github_iconTop GitHub Comments

1reaction
mbhavecommented, Mar 25, 2019

@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 bind foo.* to something with a foo prefix, but to ignore a foo property if one is set. This would be a change in the Binder 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.

1reaction
Raheela1024commented, Mar 21, 2019

@mbhave Sorry i was busy but now looking into will update shortly.

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found