Spring Boot
ConfigurationProperties
Autowire Issue
Dependency Injection
Java Spring

Spring Boot can't autowire ConfigurationProperties

Object-Oriented Design practice on Codemia

Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.

Practice OOD

Introduction

When Spring Boot fails to autowire a @ConfigurationProperties bean, it is almost always because the bean was never registered in the application context. @ConfigurationProperties alone does not create a bean. You must either add @EnableConfigurationProperties, use @ConfigurationPropertiesScan, or annotate the class with @Component. Without one of these, Spring has no bean to inject and throws NoSuchBeanDefinitionException.

The Error

 
1***************************
2APPLICATION FAILED TO START
3***************************
4
5Description:
6Field appConfig in com.example.MyService required a bean of type
7'com.example.AppConfig' that could not be found.
8
9Action:
10Consider defining a bean of type 'com.example.AppConfig' in your configuration.

The Problem

java
1// This alone does NOT register a bean
2@ConfigurationProperties(prefix = "app")
3public class AppConfig {
4    private String name;
5    private int timeout;
6
7    // getters and setters
8    public String getName() { return name; }
9    public void setName(String name) { this.name = name; }
10    public int getTimeout() { return timeout; }
11    public void setTimeout(int timeout) { this.timeout = timeout; }
12}
yaml
1# application.yml
2app:
3  name: MyApplication
4  timeout: 30
java
1@Service
2public class MyService {
3    @Autowired
4    private AppConfig appConfig;  // FAILS: AppConfig is not a bean
5}

@ConfigurationProperties tells Spring how to bind properties, but it does not register the class as a Spring bean.

Add @EnableConfigurationProperties to your main class or a @Configuration class:

java
1@SpringBootApplication
2@EnableConfigurationProperties(AppConfig.class)
3public class Application {
4    public static void main(String[] args) {
5        SpringApplication.run(Application.class, args);
6    }
7}

This explicitly registers AppConfig as a bean and binds properties to it.

Fix 2: @ConfigurationPropertiesScan (Spring Boot 2.2+)

Automatically scans for @ConfigurationProperties classes:

java
1@SpringBootApplication
2@ConfigurationPropertiesScan("com.example.config")
3public class Application {
4    public static void main(String[] args) {
5        SpringApplication.run(Application.class, args);
6    }
7}

This registers every @ConfigurationProperties class in the specified package without listing each one individually.

Fix 3: @Component

Add @Component to the properties class:

java
1@Component
2@ConfigurationProperties(prefix = "app")
3public class AppConfig {
4    private String name;
5    private int timeout;
6    // getters and setters
7}

This works but is not recommended because it mixes configuration binding with component scanning. The Spring Boot team prefers @EnableConfigurationProperties.

Fix 4: @Bean Method in @Configuration

Define the bean explicitly:

java
1@Configuration
2public class AppConfiguration {
3
4    @Bean
5    @ConfigurationProperties(prefix = "app")
6    public AppConfig appConfig() {
7        return new AppConfig();
8    }
9}

This approach is useful when you need custom initialization logic or when the properties class comes from a third-party library you cannot annotate.

Constructor Binding (Spring Boot 2.2+)

Use @ConstructorBinding for immutable configuration:

java
1@ConfigurationProperties(prefix = "app")
2public class AppConfig {
3    private final String name;
4    private final int timeout;
5
6    // Spring Boot 3.x: constructor binding is automatic for single constructor
7    // Spring Boot 2.x: add @ConstructorBinding
8    public AppConfig(String name, int timeout) {
9        this.name = name;
10        this.timeout = timeout;
11    }
12
13    public String getName() { return name; }
14    public int getTimeout() { return timeout; }
15}

Constructor-bound classes cannot use @Component. They must be registered via @EnableConfigurationProperties or @ConfigurationPropertiesScan.

Nested Properties

java
1@ConfigurationProperties(prefix = "app")
2public class AppConfig {
3    private String name;
4    private Database database = new Database();
5
6    public static class Database {
7        private String url;
8        private String username;
9        private int poolSize = 10;
10        // getters and setters
11    }
12    // getters and setters
13}
yaml
1app:
2  name: MyApp
3  database:
4    url: jdbc:postgresql://localhost/mydb
5    username: admin
6    pool-size: 20

Spring Boot automatically maps kebab-case (pool-size) to camelCase (poolSize).

Validation

java
1@ConfigurationProperties(prefix = "app")
2@Validated
3public class AppConfig {
4
5    @NotBlank
6    private String name;
7
8    @Min(1)
9    @Max(300)
10    private int timeout;
11
12    // getters and setters
13}

Add spring-boot-starter-validation to your dependencies. The application fails to start if properties violate constraints, giving you immediate feedback.

Injecting the Bean

java
1// Constructor injection (recommended)
2@Service
3public class MyService {
4    private final AppConfig appConfig;
5
6    public MyService(AppConfig appConfig) {
7        this.appConfig = appConfig;
8    }
9
10    public void doWork() {
11        System.out.println("App: " + appConfig.getName());
12        System.out.println("Timeout: " + appConfig.getTimeout());
13    }
14}

Common Pitfalls

  • Missing @EnableConfigurationProperties: The most common cause. @ConfigurationProperties alone does not create a bean. You must explicitly enable it.
  • Wrong prefix: If @ConfigurationProperties(prefix = "app") does not match your YAML/properties keys, binding silently produces null values. Spring does not throw an error for missing properties unless you add @Validated with @NotNull.
  • Missing getters/setters: Property binding requires standard JavaBean setters (or constructor parameters for constructor binding). Without them, values are silently ignored.
  • @ConstructorBinding with @Component: Constructor binding is incompatible with @Component. Use @EnableConfigurationProperties or @ConfigurationPropertiesScan instead.
  • Incorrect package scanning: @ConfigurationPropertiesScan only scans the specified packages. If your properties class is in a different package, it will not be found.

Summary

  • @ConfigurationProperties binds properties but does not create a Spring bean
  • Use @EnableConfigurationProperties(YourConfig.class) to register the bean explicitly
  • Use @ConfigurationPropertiesScan to auto-detect all @ConfigurationProperties classes
  • Constructor binding creates immutable config objects but requires @EnableConfigurationProperties
  • Add @Validated with JSR-303 annotations for startup-time validation of properties
  • Prefer constructor injection when using @ConfigurationProperties beans in services

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Object-Oriented Design practice on Codemia

Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.

Practice OOD

All Rights Reserved.