@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.