I've run into a weird behavior of Spring Boot (3.1.3) when using - in property names. Here's the sample code:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@SpringBootTest
class DemoApplicationTests {
@Value("${application.jokeurl}")
private String jokeUrl;
@Value("${application.joke-url}")
private String jokeDashUrl;
@Test
void contextLoads() {
System.out.println(jokeUrl);
System.out.println(jokeDashUrl);
}
}
And here's my application.yml:
application:
joke-url: url1 #pay attention to dash in property name
When I run the test it prints two lines into the console:
url1
url1
We see that Spring injects the same String into Values referencing in fact different properties, i.e. @Value("${application.jokeurl}") and @Value("${application.joke-url}").
Now if I add one more property into application.yml as
application:
joke-url: url1 #pay attention to dash in property name
jokeurl: url2 #no dash in property name
the same test prints different lines:
url2
url2
Now we see that the property application.joke-url is ignored in favor of application.jokeurl and again injects the same String into Values referencing different properties.
So my question is whether this is a bug or expected behavior?
Spring Boot follows the concept of Relaxed Binding. The concept states:
Simple properties are bound by removing any special characters and converting to lowercase.
In your case, application.joke-url property via Relaxed Binding becomes application.jokeurl. The value of joke-url property is replaced by jokeurl property because they are same property as per that concept.
That's why you are facing the issue.
FYI: Spring Boot will not throw any warnings/errors as this is an expected behavior.
Solution:
The trick is not use any special characters for simple properties.
Use camelcase. Change jokeurl to jokeUrl to fix your issue.
application.yml or application.yaml:
application:
joke-url: url1
jokeUrl: url2
Updated DemoApplicationTests:
@SpringBootTest
class DemoApplicationTests {
@Value("${application.jokeUrl}")
private String jokeUrl;
@Value("${application.joke-url}")
private String jokeDashUrl;
@Test
void contextLoads() {
System.out.println(jokeUrl);
System.out.println(jokeDashUrl);
}
}
Output :
url2
url1
Tested with JDK 21 and Spring Boot 3.1.4. It's working.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With