Java 16 introduced Records, which help to reduce boilerplate code when writing classes that carry immutable data. When I try to use a Record as @ConfigurationProperties
bean as follows I get the following error message:
@ConfigurationProperties("demo")
public record MyConfigurationProperties(
String myProperty
) {
}
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.demo.MyConfigurationProperties required a bean of type 'java.lang.String' that could not be found.
How can I use Records as @ConfigurationProperties
?
Spring @Configuration annotation is part of the spring core framework. Spring Configuration annotation indicates that the class has @Bean definition methods. So Spring container can process the class and generate Spring Beans to be used in the application.
Another method to access values defined in Spring Boot is by autowiring the Environment object and calling the getProperty() method to access the value of a property file.
Answering my own question.
The above error raises from Spring Boot not being able to construct the bean because of the lack of a no-argument constructor. Records implicitly declare a constructor with a parameter for every member.
Spring Boot allows us to use the @ConstructorBinding
annotation to enable property binding by constructor instead of setter methods (as stated in the docs and the answer to this question). This also works for records, so this works:
@ConfigurationProperties("demo")
@ConstructorBinding
public record MyConfigurationProperties(
String myProperty
) {
}
Update: As of Spring Boot 2.6, using records works out of the box and @ConstructorBinding
is not required anymore when the record has a single constructor. See the release notes.
If you need to declare default values programatically:
@ConfigurationProperties("demo")
public record MyConfigurationProperties(String myProperty) {
@ConstructorBinding
public MyConfigurationProperties(String myProperty) {
this.myProperty = Optional.ofNullable(myProperty).orElse("default");
}
}
java.util.Optional
properties:
@ConfigurationProperties("demo")
public record MyConfigurationProperties(Optional<String> myProperty) {
@ConstructorBinding
public MyConfigurationProperties(String myProperty) {
this(Optional.ofNullable(myProperty));
}
}
@Validated
and java.util.Optional
in combination:
@Validated
@ConfigurationProperties("demo")
public record MyConfigurationProperties(@NotBlank String myRequiredProperty,
Optional<String> myProperty) {
@ConstructorBinding
public MyConfigurationProperties(String myRequiredProperty,
String myProperty) {
this(myRequiredProperty, Optional.ofNullable(myProperty));
}
}
Based on this Spring Boot issue.
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