@ ConfigurationProperties guide in Spring Boot

1, Introduction

Spring Boot has many useful features, including externalized configuration and easy access to properties defined in the properties file. Earlier course Various ways to do this are described.

We will now explore the * @ ConfigurationProperties * annotation in more detail.

2. Setting

This tutorial uses fairly standard settings. Let's start with POM Add [spring boot starter parent] to XML( https://search.maven.org/search?q=a:spring -boot-starter-parent AND g:org. springframework. Boot) as parent:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.0</version>
    <relativePath/>
</parent>

In order to verify the attributes defined in the file, we also need an implementation of JSR-303, [hibernate validator]( https://search.maven.org/search?q=a:hibernate -validator AND g:org. Hibernate) is one of them.

Let's also add it to our POM In XML:

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-validator</artifactId>
   <version>6.0.16.Final</version>
</dependency>

stay "Start using Hibernate authentication" It is introduced in detail.

3. Simple attributes

The official documents suggest that we isolate the configuration properties into a separate POJO**

So let's start by doing this:

@Configuration
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
    
    private String hostName;
    private int port;
    private String from;

    // standard getters and setters
}

We use * @ Configuration * to create a Spring bean in the application context.

*@ConfigurationProperties * is most applicable to all hierarchical properties with the same prefix** So we added a mail prefix.

The Spring framework uses standard Java Bean setters, so we must declare setters for each property.

Note: if we do not use * @ Configuration * in the POJO, we need to add * @ EnableConfigurationProperties(ConfigProperties.class) * in the Spring application main class to bind the properties to the POJO:

@SpringBootApplication
@EnableConfigurationProperties(ConfigProperties.class)
public class EnableConfigurationDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(EnableConfigurationDemoApplication.class, args);
    }
}

this is it! Spring will automatically bind any properties defined in our properties file that have the prefix * mail * and have the same name as one of the fields in the * ConfigProperties * class.

Spring uses some loose rules to bind properties. Therefore, the following variants are bound to the property hostName:

mail.hostName
mail.hostname
mail.host_name
mail.host-name
mail.HOST_NAME

Therefore, we can use the following properties file to set all fields:

#Simple properties
mail.hostname=host@mail.com
mail.port=9000
mail.from=mailer@mail.com

3.1. Spring shoe 2.2

from Spring Boot 2.2 start , Spring finds and registers the @ ConfigurationProperties * class * through classpath scanning. Therefore, there is no need to annotate this class * with @ Component * * (and other meta annotations, such as @ Configuration), or even @ EnableConfigurationProperties:***

@ConfigurationProperties(prefix = "mail") 
public class ConfigProperties { 

    private String hostName; 
    private int port; 
    private String from; 

    // standard getters and setters 
}

@The classpath scanner enabled by SpringBootApplication found the ConfigProperties class, even if we didn't annotate it with * @ Component*

In addition, we can use* @ConfigurationPropertiesScan *Custom location of annotation scanning configuration attribute class:

@SpringBootApplication
@ConfigurationPropertiesScan("com.baeldung.configurationproperties")
public class EnableConfigurationDemoApplication { 

    public static void main(String[] args) {   
        SpringApplication.run(EnableConfigurationDemoApplication.class, args); 
    } 
}

In this way, Spring will only be on COM baeldung. Find the configuration property class in the properties package.

4. Nested attributes

We can nest properties in lists, maps, and classes**

Let's create a new Credentials class for some nested properties:

public class Credentials {
    private String authMethod;
    private String username;
    private String password;

    // standard getters and setters
}

We also need to update the use list of ConfigProperties class, a map and credential class:

public class ConfigProperties {

    private String host;
    private int port;
    private String from;
    private List<String> defaultRecipients;
    private Map<String, String> additionalHeaders;
    private Credentials credentials;
 
    // standard getters and setters
}

The following properties file sets all fields:

#Simple properties
mail.hostname=mailer@mail.com
mail.port=9000
mail.from=mailer@mail.com

#List properties
mail.defaultRecipients[0]=admin@mail.com
mail.defaultRecipients[1]=owner@mail.com

#Map Properties
mail.additionalHeaders.redelivery=true
mail.additionalHeaders.secure=true

#Object properties
mail.credentials.username=john
mail.credentials.password=password
mail.credentials.authMethod=SHA1

5. Use @ ConfigurationProperties on the @ Bean * method***

We can also use the @ ConfigurationProperties * annotation on the @ Bean * annotation method**

This approach can be particularly useful when we want to bind properties to third-party components that we cannot control.

Let's create a simple Item class, which we will use in the next example:

public class Item {
    private String name;
    private int size;

    // standard getters and setters
}

Now let's see how to use @ ConfigurationProperties on the * @ Bean method to bind the externalized property to the Item * instance:

@Configuration
public class ConfigProperties {

    @Bean
    @ConfigurationProperties(prefix = "item")
    public Item item() {
        return new Item();
    }
}

Therefore, any attribute prefixed with Item will be mapped to the Item instance managed by the Spring context.

6. Property verification

***@ConfigurationProperties * provides property validation using JSR-303 format** This allows all kinds of neat things.

For example, let's force the hostName property:

@NotBlank
private String hostName;

Next, let the authMethod attribute be 1 to 4 characters long:

@Length(max = 4, min = 1)
private String authMethod;

Then, the port attributes range from 1025 to 65536:

@Min(1025)
@Max(65536)
private int port;

Finally, the from attribute must match the e-mail address format:

@Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$")
private String from;

This helps us reduce the large number of if else conditions in our code and make it look more concise and concise.

**If any of these validations fails, the main application cannot start with * IllegalStateException * * *.

The Hibernate Validation framework uses standard Java Bean getters and setters, so it is important to declare getters and setters for each property.

7. Property conversion

@ConfigurationProperties supports multiple types of transformations, binding properties to corresponding bean s.

7.1. period

We will first look at converting attributes to Duration objects **

Here we have two fields of Duration type:

@ConfigurationProperties(prefix = "conversion")
public class PropertyConversion {

    private Duration timeInDefaultUnit;
    private Duration timeInNano;
    ...
}

This is our properties file:

conversion.timeInDefaultUnit=10
conversion.timeInNano=9ns

Therefore, the value of the field timeInDefaultUnit is 10 milliseconds, while the value of timeInNano is 9 nanoseconds.

The supported units are * ns, us, ms, s, m, h and d, which represent nanosecond, microsecond, millisecond, second, minute, hour and day respectively*

The default unit is milliseconds, which means that if we don't specify the unit next to the value, Spring will convert the value to milliseconds.

We can also override the default units with * @ DurationUnit:*

@DurationUnit(ChronoUnit.DAYS)
private Duration timeInDays;

This is the corresponding attribute:

conversion.timeInDays=2

7.2. data size

*Similarly, Spring Boot @ConfigurationProperties * supports * DataSize * type conversion.

Let's add three fields of type DataSize:

private DataSize sizeInDefaultUnit;

private DataSize sizeInGB;

@DataSizeUnit(DataUnit.TERABYTES)
private DataSize sizeInTB;

These are the corresponding attributes:

conversion.sizeInDefaultUnit=300conversion.sizeInGB=2GBconversion.sizeInTB=4

In this case, * sizeInDefaultUnit * will be 300 bytes because the default unit is bytes.

The supported units are B, KB, MB, GB and TB. We can also use @ DataSizeUnit to override the default unit **

7.3. Custom converter

We can also add our own custom converters to support the conversion of properties to specific class types.

Let's add a simple class Employee:

public class Employee {    private String name;    private double salary;}

We will then create a custom converter to convert this property:

conversion.employee=john,2000

We convert it to a file of type Employee:

private Employee employee;

We need to implement the Converter interface, and then use the * @ ConfigurationPropertiesBinding * annotation to register our custom * Converter:*

@Component@ConfigurationPropertiesBindingpublic class EmployeeConverter implements Converter<String, Employee> {    @Override    public Employee convert(String from) {        String[] data = from.split(",");        return new Employee(data[0], Double.parseDouble(data[1]));    }}

8. Immutable * @ ConfigurationProperties * binding

Starting with Spring Boot 2.2, we can use the @ ConstructorBinding * annotation to bind our configuration properties *.

This essentially means that the class annotated with * @ ConfigurationProperties * may now be Immutable.

@ConfigurationProperties(prefix = "mail.credentials")@ConstructorBindingpublic class ImmutableCredentials {    private final String authMethod;    private final String username;    private final String password;    public ImmutableCredentials(String authMethod, String username, String password) {        this.authMethod = authMethod;        this.username = username;        this.password = password;    }    public String getAuthMethod() {        return authMethod;    }    public String getUsername() {        return username;    }    public String getPassword() {        return password;    }}

As we can see, when using * @ ConstructorBinding, * we need to provide the constructor with all the parameters we want to bind.

Note that all fields of ImmutableCredentials are final. In addition, there is no setter method.

In addition, it should be emphasized that * to use constructor binding, we need to explicitly enable our configuration class using @ EnableConfigurationProperties * or * @ ConfigurationPropertiesScan * * *.

9. Conclusion

In this article, we explored the * @ ConfigurationProperties * annotation and highlighted some of the useful features it provides, such as easy binding and Bean validation.

As usual, the code can Found on Github.

Keywords: Spring Spring Boot properties

Added by tsilenzio on Fri, 28 Jan 2022 07:37:08 +0200