- Spring Boot Configuration Properties
- Enabling Configuration Properties
- Nested Properties
- Validation of properties
- Properties Conversion
Spring Boot Configuration Properties
@ConfigurationProperties
is an annotation for externalized configuration in Spring Boot. This can be added to a class definition or a @Bean
method in a @Configuration
class, if you want to bind and validate some external Properties (e.g. from a .properties file). Binding is either performed by calling setters on the annotated class or, if @ConstructorBinding
is in use, by binding to the constructor parameters.
Enabling Configuration Properties
@ConfigurationProperties
Spring finds and registers @ConfigurationProperties
classes via classpath scanning. The classpath scanner enabled by @SpringBootApplication
finds the ApplicationProperties
class, even though we didn’t annotate this class with @Component
.
@ConfigurationProperties
public class ApplicationProperties {
private String host;
private Integer port;
//setters and getters
}
It can also be enabled via @Bean
method in a @Configuration
class
@Bean
@ConfigurationProperties(prefix = "application")
public ApplicationProperties applicationProperties() {
return new ApplicationProperties();
}
@EnableConfigurationProperties
Sometimes, classes annotated with @ConfigurationProperties
might not be suitable for scanning. In these cases, we can specify the list of types to process using the @EnableConfigurationProperties
annotation on any @Configuration
class.
@Configuration
@EnableConfigurationProperties(ApplicationProperties.class)
public class AppConfig{
}
@ConfigurationPropertiesScan
We can use the _@ConfigurationPropertiesScan
_annotation to scan custom locations for configuration property classes. Typically, it is added to the main application class that is annotated with @SpringBootApplication
but it can be added to any @Configuration
class. By default, scanning will occur from the package of the class that declares the annotation. If you want to define specific packages to scan, we can provide the package as shown below.
@SpringBootApplication
@ConfigurationPropertiesScan("com.pamesh.properties")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application .class, args);
}
}
The following properties file will set the fields in ApplicationProperties
application.host=localhost
application.port=8080
Nested Properties
We can configure nested properties using the method for lists, maps and custom classes.
public class ApplicationProperties {
private String host;
private Integer port;
//Custom Class
private final Async async = new Async();
//List
private List<String> ids;
//Map
private Map<String, String> headers;
}
@ConfigurationProperties(prefix="application.async")
public class Async {
private int corePoolSize = 2;
private int maxPoolSize = 20;
private int queueCapacity = 500;
}
The following properties file will set the fields in ApplicationProperties
:
application.host=localhost
application.port=8080
### Async Properties #####
application.async.core-pool-size= 10
application.async.max-pool-size= 50
application.async.queue-capacity= 500
#### List #######
application.ids[0]=1
application.ids[1]=2
### Map ####
application.headers.appId = id ### key=appId, value = id
application.headers.auth = authValue
Validation of properties
Spring Boot attempts to validate @ConfigurationProperties
classes whenever they are annotated with Spring’s @Validated
annotation.
import org.springframework.validation.annotation.Validated;
@Bean
@ConfigurationProperties(prefix = "application")
@Validated
public ApplicationProperties applicationProperties() {
return new ApplicationProperties();
}
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.Length;
public class ApplicationProperties {
@NotBlank
@Length(max = 4, min = 1)
private String host;
@NotNull
private Integer port;
}
To ensure that validation is always triggered for nested properties, even when no properties are found, the associated field must be annotated with @Valid
. In below example Async
has been annotated with it.
import javax.validation.Valid;
public class ApplicationProperties {
//Custom Class
@Valid
private final Async async = new Async();
}
Properties Conversion
Spring Boot attempts to coerce the external application properties to the right type when it binds to the @ConfigurationProperties
beans.
Converting durations
If you expose a java.time.Duration
property, the following formats in application properties are available:
- A regular
long
representation (using milliseconds as the default unit unless a@DurationUnit
has been specified) - A more readable format where the value and the unit are coupled (e.g.
10s
means 10 seconds)
public class ApplicationProperties{
private Duration time;
@DurationUnit(ChronoUnit.SECONDS)
private Duration timeInSeconds;
}
And properties file is
application.time=10
application.timeInSeconds=20s
As a result, the field time will have a value of 10 milliseconds, and _timeInSeconds_will have a value of 20 seconds.
The supported units are ns, us, ms, s, m, h and d for nanoseconds, microseconds, milliseconds, seconds, minutes, hours, and days, respectively.
Custom Converter
For custom type conversion, we can provide custom Converters
(with bean definitions annotated as @ConfigurationPropertiesBinding
).
Add User class
@NoArgsConstructor
@AllArgsConstructor
@Data
public class User {
private String firstName;
private String lastName;
}
Now add the class to properties class
public class ApplicationProperties {
@Valid
private User user = new User();
}
Now create a custom converter and use @ConfigurationPropertiesBinding
annotation to register our custom Converter.
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
import org.springframework.core.convert.converter.Converter;
@ConfigurationPropertiesBinding
public class UserConverter implements Converter<String,User>; {
@Override
public User convert(String source) {
String [] value = source.split(",");
return new User(value[0],value[1]);
}
}
Now set value in properties file
application.user=pamesh,bansal
Above property value will result in User [firstName=pamesh, lastName=bansal]