DEV Community

Cover image for Spring Boot: Stop Using @Value Everywhere! Discover @ConfigurationProperties
Rachid
Rachid

Posted on

Spring Boot: Stop Using @Value Everywhere! Discover @ConfigurationProperties

Hey dev community!

When working on Spring Boot projects, we all need to read values from our application.properties or application.yml files.

Most of us start by using the @Value annotation to inject each property one by one.

The Problem (The "Old Way")
As your application grows, your service or configuration class starts to look like this:

@Service
public class MyOldService {

    @Value("${app.api.url}")
    private String apiUrl;

    @Value("${app.api.key}")
    private String apiKey;

    @Value("${app.feature.toggle.new-feature}")
    private boolean featureToggle;

    @Value("${app.thread-pool-size}")
    private int poolSize;

    // ... and it goes on and on
}
Enter fullscreen mode Exit fullscreen mode

This is verbose, hard to maintain, and not type-safe (just Strings and primitives). If you mistype a prefix, everything breaks at runtime.

The Solution: @ConfigurationProperties
Spring Boot offers a much cleaner, safer, and more organized way to manage your configuration: the @ConfigurationProperties annotation.

The idea is simple: map an entire block of your configuration file to a single Java object (a POJO or a Record).

Let's see how.

Step 1: Your application.yml file
Structure your properties logically. It's much more readable!

app:
  name: "My Awesome Service"
  feature-toggle:
    new-feature: true
    beta-access: false
  api:
    url: "https://api.example.com"
    key: "your-secret-api-key"

Enter fullscreen mode Exit fullscreen mode

Step 2: Create the Configuration Class
We'll create a class (or even better, a Java 17+ record) that represents this structure.

Note: For this to work with records (constructor binding), you need a recent version of Spring Boot (3+). Otherwise, use a classic class with getters and setters.

import org.springframework.boot.context.properties.ConfigurationProperties;

// The "app" prefix matches the root of our config
@ConfigurationProperties(prefix = "app")
public record AppProperties(
    String name, 
    ApiConfig api,
    FeatureToggle featureToggle
) {

    // We can even have nested objects!
    public record ApiConfig(String url, String key) {}

    public record FeatureToggle(boolean newFeature, boolean betaAccess) {}
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Enable the Configuration
We need to tell Spring to scan and activate this class. The easiest way is on your main application class:

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableConfigurationProperties(AppProperties.class) // <-- The key step!
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Use Your Configuration (The Clean Way!)
Now, instead of injecting 10 @Value fields, you just inject one single bean, perfectly typed:

@Service
public class MyNewService {

    private final AppProperties appProperties;

    // Constructor injection (always a good practice!)
    public MyNewService(AppProperties appProperties) {
        this.appProperties = appProperties;
    }

    public void doSomething() {
        String url = appProperties.api().url(); // Clean!
        String key = appProperties.api().key(); // Type-safe!

        if (appProperties.featureToggle().newFeature()) {
            // ... new feature logic
        }

        System.out.println("App name: " + appProperties.name());
    }
}
Enter fullscreen mode Exit fullscreen mode

Why This is 100x Better
Type-Safe: No more 'String' vs. 'int' errors. You're handling a real Java object.

Centralized: All 'app'-related configuration is in one single class.

Validation: You can add validation annotations (@Validated, @min, @NotEmpty) directly to the fields of your AppProperties class!

Auto-completion (The Pro-Tip):
If you add this dependency to your pom.xml (or Gradle), your IDE will give you auto-completion right in your .yml or .properties file!

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Conclusion
Stop fighting with @Value. For any configuration that's more than two or three keys, switch to @ConfigurationProperties. It's cleaner, more robust, and much more maintainable.

What's your favorite Spring Boot tip? Let me know in the comments! 👇

Happy coding!

Top comments (2)

Collapse
 
abouziani profile image
ABouziani

Sounds interresting, thanks for the share.

Collapse
 
icanitam profile image
Ikhsan

the leveraging of record class is way cleaner than pojo
thanks for sharing