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 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; } 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 headers ) {} 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, ) {} Alternative 1 using Spring 2.x: @Data @AllArgsConstructor @ConfigurationPropertiesScan @ConfigurationProperties("mail") public class MailProperties { private String user; private String password; private Map headers; } @SpringBootApplication @ConfigurationPropertiesScan("your.package.mailproperties") public class ExampleApplication { public static void main(String[] args) { SpringApplication.run(ExampleApplication.class, args); } } And your service use properties like this: @Service @RequiredArgsConstructor public class CustomService { private final MailProperties mailProperties; } 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.

Jan 23, 2025 - 03:09
 0
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

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;
}

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
) {}

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,
) {}

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;
}
@SpringBootApplication
@ConfigurationPropertiesScan("your.package.mailproperties")
public class ExampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }
}

And your service use properties like this:

@Service
@RequiredArgsConstructor
public class CustomService {
 private final MailProperties mailProperties;
}

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.

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow