DEV Community

Erik Santana
Erik Santana

Posted on

Reading configuration like a pro on Spring

Introduction

As we already know, Spring provides many ways to achieve the same thing, and one of them is how to retrieve the values registered in your configuration file.

If you're new to Spring, you might come across code that uses the @Value annotation to retrieve values from your application.properties or application.yml file. If you're using this approach, know that it's not wrong; however, you might be introducing unnecessary complexity into your application.

The Problem with @Value

The main issue with using @Value arises when we deal with values that contain other values. Does that make sense? No? Let's look at an example:

Suppose you have the following configuration file:

mail.user=dev@locahost
mail.password=123
mail.headers.x-from=Ekerdev
mail.headers.x-custom=custom
Enter fullscreen mode Exit fullscreen mode

You would need to do it like this:

@Service
public class CustomService {
 @Value("mail.user")
 private String user;

 @Value("mail.password")
 private String password;

 @Value("mail.headers.x-from")
 private String xFrom;

 @Value("mail.headers.x-custom")
 private String xCustom;
}
Enter fullscreen mode Exit fullscreen mode

So far, no problem. But now imagine a scenario where your application needs to use these same values in multiple places in the code. Think of how much duplicated code we’d end up with, right?

The Solution

The best solution, then, is to use the @ConfigurationProperties annotation. This makes it easier for our application to inject variables into a class, and we can use it just like any other dependency in Spring, injecting it as shown in the example below:

Alternative 1 using Spring 3.x:

@Configuration
@ConfigurationProperties("mail")
public record MailProperties(
 String user,
 String password,
 Map<String, String> headers
) {}
Enter fullscreen mode Exit fullscreen mode

Alternative 2 using Spring 3.x:

@Configuration
@ConfigurationProperties("mail.headers")
public record MailHeadersProperties(
 String xFrom,
 String xCustom,
) {}

@Configuration
@ConfigurationProperties("mail")
public record MailProperties(
 String user,
 String password,
 MailHeadersProperties headers,
) {}
Enter fullscreen mode Exit fullscreen mode

Alternative 1 using Spring 2.x:

@Data
@AllArgsConstructor
@ConfigurationPropertiesScan
@ConfigurationProperties("mail")
public class MailProperties {
 private String user;
 private String password;
 private Map<String, String> headers;
}
Enter fullscreen mode Exit fullscreen mode
@SpringBootApplication
@ConfigurationPropertiesScan("your.package.mailproperties")
public class ExampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

And your service use properties like this:

@Service
@RequiredArgsConstructor
public class CustomService {
 private final MailProperties mailProperties;
}
Enter fullscreen mode Exit fullscreen mode

The Advantage

The major advantage of using @ConfigurationProperties is that we don't have to hunt for @Value annotations in our code, which makes the code much more readable.

Top comments (1)

Collapse
 
vialc profile image
Vitor Alcântara

Very useful. Thanks for sharing