Skip to content

Lab 14: Configuration

Continue with Profiles and ConfigurationProperties immutable classes validation

Description

To make it easier to organize and test configuration properties, it's useful to group them together in an immutable object that can be validation.

Goals

  • Use @ConfigurationProperties to group together related properties
  • See how @ConstructorBinding helps you build immutable configuration objects
  • Understand how @Validated is used to validate properties

a. Property Object

We'll move the currency conversion service URI template into a single configuration object to make it easily injectable.

  1. Add the following entry to the application.properties file:

    currency.uri-template=http://jitterted-currency-conversion.herokuapp.com/convert?from={from}&to={to}&amount={amount}
    

    Relaxed Binding

    Property files should use "kebab-case" for property names and these are translated into "camel case" for you. See: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-relaxed-binding

  2. Create a test class named CurrencyConfigTest in the com.welltestedlearning.coffeekiosk package and insert the following code:

    package com.welltestedlearning.coffeekiosk;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    @ConfigurationProperties(prefix = "currency")
    public class CurrencyConfig {
    
        private String uriTemplate;
    
        public setUriTemplate(String uriTemplate) {
            this.uriTemplate = uriTemplate;
        }
    
        public String getUriTemplate() {
            return uriTemplate;
        }
    }
    
  3. Add the annotation @ConfigurationPropertiesScan to the Application class (where @SpringBootApplication is used).

  4. Add the following test class named CurrencyConfigTest for testing the configuration:

    package com.welltestedlearning.coffeekiosk;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import static org.assertj.core.api.Assertions.assertThat;
    
    @SpringBootTest
    class CurrencyConfigTest {
    
        @Autowired
        private CurrencyConfig currencyConfig;
    
        @Test
        void configLoadedWithTemplate() {
            assertThat(currencyConfig.getUriTemplate())
                .isNotBlank();            
        }
    }
    
  5. Run the test, and it should pass if everything is configured correctly.

b. Add Validation

  1. The use of @ConfigurationProperties supports the Bean Validation (JSR-303) standard, so we can make sure that the properties are valid before starting.

  2. Add @Validated to the class

  3. Add @NotBlank to the uriTemplate instance variable

  4. Try adding @Size(max=10) and see what happens

c. Immutable Configuration

Since configuration is only loaded from properties during start, we can make the configuration object immutable by adding an "all argument" constructor and the annotation @ConstructorBinding.

  1. Add @ConstructorBinding to the config class

  2. Change all of the private variables to be final

  3. Remove the setter method

  4. Create a constructor that takes the uriTemplate as a parameter

  5. Run the configuration test and it should still pass.