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 (0)