@SpringBootApplication
@EnableConfigurationProperties(DemoProperties.class)
public class DemoApplication implements CommandLineRunner {
    @Value("${demo.itemPrice:3}")
    private int itemPrice = 2;
    @Autowired
    private DemoProperties demoProperties;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) {
        System.out.printf("Item price from @Value: %d%n", itemPrice);
        System.out.printf("Item price from @ConfigurationProperties: %d%n", demoProperties.getItemPrice());
    }
}
@ConfigurationProperties(prefix = "demo")
public class DemoProperties {
    private int itemPrice = 1;

    public int getItemPrice() {
        return itemPrice;
    }

    public void setItemPrice(int itemPrice) {
        this.itemPrice = itemPrice;
    }
}

If an environment variable DEMO_ITEM_PRICE=4 is set, we get:

Item price from @Value: 3
Item price from @ConfigurationProperties: 4

If an environment variable DEMO_ITEMPRICE=4 is set, (disregarding Camel case) we get:

Item price from @Value: 4
Item price from @ConfigurationProperties: 4

Verified with 2.1.2.RELEASE. See attached demo app. demo.zip

Comment From: spencergibb

What if you do this?

@Value("${demo.item-price:3}")

Comment From: asarkar

@spencergibb @Value("${demo.item-price:3}") seems to work as expected.

Comment From: spencergibb

That's because boot now translates external configuration into a canonical format, in this case, demo.item-price. Applications need to use that form in places like the value annotations or conditional on property. External configuration can use relaxed forms. Pretty sure this is documented

Comment From: asarkar

@spencergibb Perhaps you're referring to this part of the docs 24.7.5 @ConfigurationProperties vs. @Value.

I believe it's misleading in the sense that it states @Value doesn't support relaxed binding, but as we can see, it does, but only limited to the dashed notation. I think it'll help to provide some examples to avoid this sort of confusion, or recommend in the docs that people strictly use underscores in env var only to replace a ..

Comment From: wilkinsona

The section of the documentation to which you have linked advises against using @Value with environment variables:

Please also be aware that since @Value does not support relaxed binding, it isn’t a great candidate if you need to provide the value using environment variables.

Relaxed binding is a featured of Spring Boot's binder which is only using with @ConfigurationProperties and isn't involved at all when @Value is used. It works with demo.item-price not because of relaxed binding but because of the translation to the canonical form that @spencergibb has described above. In short, the statement that @Value does not supported relaxed binding is technically accurate although I can see where the confusion has arisen.

Let's use this issue to see if we can clarify the documentation a bit.