DEV Community

Cover image for Type-safe Configuration Properties in Spring Boot 2

Type-safe Configuration Properties in Spring Boot 2

scottshipp profile image scottshipp Originally published at ・4 min read

Who this tutorial is for

This tutorial is for anyone who has used Spring Boot enough to get their feet wet with the @Value annotation and retrieving properties from files (like, environment variables, and command-line arguments. Or just learn all about that stuff in my Properties in Spring Boot 2 Tutorial first and then come back to this one.

Getting started

For this post, I have a barebones Spring Boot 2 web service set up that can take coffee orders. Clients of my service can POST a new order to /orders. Each order needs a size and product. If a customer wants a tall latte, the following request body would create the new order:

  "product": "latte",
  "size": "tall"

The response received from such a POST is:

  "orderNumber": 1,
  "customerOrder": {
    "product": "latte",
    "size": "tall"

In addition, anyone can send a GET request to retrieve an existing order. To get the above order, clients can send a GET to /orders/1 and the above response will be received.

I’ve chosen to use properties to hold the products and sizes that our coffee shop can serve. This is my file right now:


Although this is not a good use of properties for a production application, it works for illustrative purposes in this specific tutorial.

Using menu properties with @Value

With the @Value annotation, I can refer to these menu properties in a class somewhere, such as follows:

public class OrderValidator {
    private List<String> sizes;

    private List<String> products;

    public void validate(CustomerOrder order) {
        if(!sizes.contains(order.getSize().toLowerCase())) {
            throw new BadOrderException("Size is invalid. Allowable sizes are " +;
        if(!products.contains(order.getProduct().toLowerCase())) {
            throw new BadOrderException("Selected product is invalid. Allowable products are " +;

I could use the OrderValidator to validate orders that come into my controller:

public StoredOrder newOrder(@RequestBody CustomerOrder order) {
    long orderNumber = orderDb.storeOrder(order);
    return new StoredOrder(orderNumber, order);

Type-safe configuration properties

Spring Boot offers another approach for managing properties known as type-safe configuration properties. You can create a class to hold all related properties instead of adding a @Value annotation.

public class MenuProperties {
    private final List<String> sizes;
    private final List<String> products;

    public MenuProperties(List<String> sizes, List<String> products) {
        this.sizes = sizes;
        this.products = products;

    public List<String> getProducts() {
        return products;

    public List<String> getSizes() {
        return sizes;

The @ConstructorBinding annotation tells Spring Boot to use the constructor to inject the properties. You could omit this if you provide setters and remove the final declaration from the class members. It is a recommended practice to use immutable configuration properties classes, though, as shown here.

The @ConfigurationProperties annotation tells Spring Boot 2 to look in its properties sources for properties with the provided “prefix.” In this case, that simply means that it will look in and find properties with the “menu” prefix in

Note that you can also specify longer prefixes. For example, if you had “menu.items.sizes” and “menu.items.products” as your properties, you could pass “menu.items” to the @ConfigurationProperties annotation: @ConfigurationProperties("menu.items").

In order for @ConfigurationProperties-annotated classes to be found by Spring Boot and injected with the properties, add the @ConfigurationPropertiesScan to whatever class in your application is marked with the @SpringBootApplication annotation. In my example web service, this is in the root directory of my sources, which now looks like this:

public class CoffeeshopApplication {

    public static void main(String[] args) {, args);


As an alternative, you can use the @EnableConfigurationProperties annotation to specify only specific classes.

Consuming configuration properties

To consume the new properties class, just add a constructor to the OrderValidator that accepts a parameter of the new type. Spring will autowire the dependency:

public class OrderValidator {
    private final MenuProperties menuProperties;

    public OrderValidator(MenuProperties menuProperties) {
        this.menuProperties = menuProperties;

    public void validate(CustomerOrder order) {
        if(!menuProperties.getSizes().contains(order.getSize().toLowerCase())) {
            throw new BadOrderException("Size is invalid. Allowable sizes are " + getAllowableSizes());
        if(!menuProperties.getProducts().contains(order.getProduct().toLowerCase())) {
            throw new BadOrderException("Selected product is invalid. Allowable products are " + getAllowableProducts());

    private String getAllowableProducts() {
        return menuProperties.getProducts().stream().collect(Collectors.joining(", "));

    private String getAllowableSizes() {
        return menuProperties.getSizes().stream().collect(Collectors.joining(", "));


There are a number of advantages to this approach. Some of them are evident from this example, and some of them aren’t. The major ones are:

  • It makes properties available in reusable classes

  • It is much less cumbersome to use for larger groups of properties or for hierarchical properties

  • There is a feature of Spring Boot 2 that allows your IDE to autocomplete properties for you when they are exposed as type-safe configuration properties

  • There is a validation feature available for properties made available as type-safe configuration properties

Because of the advantages of type-safe configuration properties, it is a recommended practice to prefer them to the @Value annotation approach.

What you have learned

In this post, you learned how to create type-safe configuration properties in Spring Boot 2.

If you want to learn more about Spring Boot 2, please check out more of my Spring Boot 2 Tutorials.


Editor guide