0
# Configuration Properties
1
2
Type-safe configuration property binding system with validation support, enabling external configuration management for Spring Boot applications.
3
4
## Capabilities
5
6
### Configuration Properties Binding
7
8
Bind external configuration properties to Java objects with type safety and validation.
9
10
```java { .api }
11
/**
12
* Annotation for externalized configuration. Add this to a class definition or a
13
* @Bean method in a @Configuration class if you want to bind and validate some
14
* external Properties (e.g. from a .properties file)
15
*/
16
@Target({ElementType.TYPE, ElementType.METHOD})
17
@Retention(RetentionPolicy.RUNTIME)
18
@interface ConfigurationProperties {
19
/**
20
* The name prefix of the properties that are valid to bind to this object
21
* @return the name prefix of the properties to bind
22
*/
23
String value() default "";
24
25
/**
26
* The name prefix of the properties that are valid to bind to this object
27
* @return the name prefix of the properties to bind
28
*/
29
String prefix() default "";
30
31
/**
32
* Flag to indicate that when binding to this object invalid fields should be ignored
33
* @return whether to ignore invalid fields
34
*/
35
boolean ignoreInvalidFields() default false;
36
37
/**
38
* Flag to indicate that when binding to this object unknown fields should be ignored
39
* @return whether to ignore unknown fields
40
*/
41
boolean ignoreUnknownFields() default true;
42
}
43
44
/**
45
* Enable support for ConfigurationProperties annotated classes
46
*/
47
@Target(ElementType.TYPE)
48
@Retention(RetentionPolicy.RUNTIME)
49
@interface EnableConfigurationProperties {
50
/**
51
* The configuration properties classes to register
52
* @return the classes to register
53
*/
54
Class<?>[] value() default {};
55
}
56
57
/**
58
* Scan for configuration properties classes in the specified packages
59
*/
60
@Target(ElementType.TYPE)
61
@Retention(RetentionPolicy.RUNTIME)
62
@interface ConfigurationPropertiesScan {
63
/**
64
* Alias for basePackages()
65
* @return the base packages
66
*/
67
String[] value() default {};
68
69
/**
70
* Base packages to scan for configuration properties classes
71
* @return the base packages
72
*/
73
String[] basePackages() default {};
74
75
/**
76
* Type-safe alternative to basePackages() for specifying packages to scan
77
* @return the base package classes
78
*/
79
Class<?>[] basePackageClasses() default {};
80
}
81
```
82
83
**Usage Examples:**
84
85
```java
86
// Basic configuration properties class
87
@ConfigurationProperties(prefix = "app.database")
88
public class DatabaseProperties {
89
private String url;
90
private String username;
91
private String password;
92
private int maxConnections = 10;
93
94
// Getters and setters
95
public String getUrl() { return url; }
96
public void setUrl(String url) { this.url = url; }
97
98
public String getUsername() { return username; }
99
public void setUsername(String username) { this.username = username; }
100
101
public String getPassword() { return password; }
102
public void setPassword(String password) { this.password = password; }
103
104
public int getMaxConnections() { return maxConnections; }
105
public void setMaxConnections(int maxConnections) { this.maxConnections = maxConnections; }
106
}
107
108
// Enable configuration properties in main class
109
@SpringBootApplication
110
@EnableConfigurationProperties(DatabaseProperties.class)
111
public class Application {
112
public static void main(String[] args) {
113
SpringApplication.run(Application.class, args);
114
}
115
}
116
117
// Use configuration properties in a service
118
@Service
119
public class DatabaseService {
120
private final DatabaseProperties databaseProperties;
121
122
public DatabaseService(DatabaseProperties databaseProperties) {
123
this.databaseProperties = databaseProperties;
124
}
125
126
public void connect() {
127
System.out.println("Connecting to: " + databaseProperties.getUrl());
128
}
129
}
130
```
131
132
### Property Binding Annotations
133
134
Control how properties are bound to Java objects.
135
136
```java { .api }
137
/**
138
* Annotation that can be used to indicate that configuration properties should
139
* be bound using constructor arguments rather than by calling setters
140
*/
141
@Target({ElementType.CONSTRUCTOR, ElementType.ANNOTATION_TYPE})
142
@Retention(RetentionPolicy.RUNTIME)
143
@interface ConstructorBinding {
144
}
145
146
/**
147
* Annotation that can be used to specify a default value when binding configuration properties
148
*/
149
@Target(ElementType.PARAMETER)
150
@Retention(RetentionPolicy.RUNTIME)
151
@interface DefaultValue {
152
/**
153
* The default value to use if no property is found
154
* @return the default value
155
*/
156
String[] value() default {};
157
}
158
159
/**
160
* Annotation that can be used to indicate that a field in a ConfigurationProperties
161
* object should be treated as if it were a nested type
162
*/
163
@Target({ElementType.FIELD, ElementType.METHOD})
164
@Retention(RetentionPolicy.RUNTIME)
165
@interface NestedConfigurationProperty {
166
}
167
168
/**
169
* Annotation that can be used to indicate that a ConfigurationProperties field is deprecated
170
*/
171
@Target({ElementType.FIELD, ElementType.METHOD})
172
@Retention(RetentionPolicy.RUNTIME)
173
@interface DeprecatedConfigurationProperty {
174
/**
175
* The reason for the deprecation
176
* @return the deprecation reason
177
*/
178
String reason() default "";
179
180
/**
181
* The replacement property that should be used instead
182
* @return the replacement property
183
*/
184
String replacement() default "";
185
}
186
```
187
188
**Usage Examples:**
189
190
```java
191
// Constructor binding example
192
@ConfigurationProperties(prefix = "app.server")
193
@ConstructorBinding
194
public class ServerProperties {
195
private final String host;
196
private final int port;
197
private final boolean ssl;
198
199
public ServerProperties(
200
@DefaultValue("localhost") String host,
201
@DefaultValue("8080") int port,
202
@DefaultValue("false") boolean ssl) {
203
this.host = host;
204
this.port = port;
205
this.ssl = ssl;
206
}
207
208
public String getHost() { return host; }
209
public int getPort() { return port; }
210
public boolean isSsl() { return ssl; }
211
}
212
213
// Nested configuration properties example
214
@ConfigurationProperties(prefix = "app")
215
public class ApplicationProperties {
216
@NestedConfigurationProperty
217
private final DatabaseConfig database = new DatabaseConfig();
218
219
@NestedConfigurationProperty
220
private final SecurityConfig security = new SecurityConfig();
221
222
public DatabaseConfig getDatabase() { return database; }
223
public SecurityConfig getSecurity() { return security; }
224
225
public static class DatabaseConfig {
226
private String url;
227
private String username;
228
229
// getters and setters
230
}
231
232
public static class SecurityConfig {
233
private boolean enabled = true;
234
235
// getters and setters
236
}
237
}
238
239
// Deprecated property example
240
@ConfigurationProperties(prefix = "app.legacy")
241
public class LegacyProperties {
242
@DeprecatedConfigurationProperty(
243
reason = "Use 'app.new.timeout' instead",
244
replacement = "app.new.timeout"
245
)
246
private Duration oldTimeout;
247
248
// getters and setters
249
}
250
```
251
252
### Property Mapping and Utilities
253
254
Utilities for mapping and validating configuration properties.
255
256
```java { .api }
257
/**
258
* Utility that can be used to map values from a supplied source to a destination
259
*/
260
public final class PropertyMapper {
261
/**
262
* Return a new PropertyMapper instance
263
* @return a new property mapper
264
*/
265
public static PropertyMapper get();
266
267
/**
268
* Return a new Source from the specified value supplier that can be used to
269
* perform the mapping
270
* @param value the value supplier
271
* @return a property source
272
*/
273
public <T> Source<T> from(T value);
274
275
/**
276
* Return a new Source from the specified value supplier that can be used to
277
* perform the mapping
278
* @param supplier the value supplier
279
* @return a property source
280
*/
281
public <T> Source<T> from(Supplier<T> supplier);
282
283
/**
284
* Return a new PropertyMapper that won't map null values
285
* @return a property mapper that ignores null values
286
*/
287
public PropertyMapper alwaysApplyingWhenNonNull();
288
289
/**
290
* A source that is in the process of being mapped
291
*/
292
public final class Source<T> {
293
/**
294
* Return an adapted version of the source with the specified type
295
* @param adapter the adapter to use
296
* @return a new adapted source
297
*/
298
public <R> Source<R> as(Function<T, R> adapter);
299
300
/**
301
* Return a filtered version of the source that won't map non-null values or values that don't match the specified predicate
302
* @param predicate the predicate to use to test the value
303
* @return a new filtered source
304
*/
305
public Source<T> when(Predicate<T> predicate);
306
307
/**
308
* Return a filtered version of the source that will only map values that are not equal to the specified value
309
* @param value the value to check
310
* @return a new filtered source
311
*/
312
public Source<T> whenNot(T value);
313
314
/**
315
* Complete the mapping by passing the current value to the specified consumer
316
* @param consumer the consumer that should accept the value
317
*/
318
public void to(Consumer<T> consumer);
319
320
/**
321
* Complete the mapping for any non-null value by passing it to the specified consumer
322
* @param consumer the consumer that should accept the value
323
*/
324
public void toCall(Runnable consumer);
325
}
326
}
327
```
328
329
**Usage Examples:**
330
331
```java
332
// Property mapping example
333
@ConfigurationProperties(prefix = "app.server")
334
public class ServerProperties {
335
private String host;
336
private int port;
337
private Duration timeout;
338
339
// Constructor using PropertyMapper
340
public void configureServer(ServerConfigurer configurer) {
341
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
342
map.from(this::getHost).to(configurer::setHost);
343
map.from(this::getPort).to(configurer::setPort);
344
map.from(this::getTimeout).as(Duration::toMillis).to(configurer::setTimeoutMillis);
345
}
346
347
// getters and setters
348
}
349
350
// Advanced property mapping with conditions
351
public void configureTomcat(TomcatServletWebServerFactory factory) {
352
PropertyMapper propertyMapper = PropertyMapper.get();
353
354
propertyMapper.from(properties::getMaxThreads)
355
.when(maxThreads -> maxThreads > 0)
356
.to(factory::setMaxThreads);
357
358
propertyMapper.from(properties::getMinSpareThreads)
359
.whenNot(0)
360
.to(factory::setMinSpareThreads);
361
362
propertyMapper.from(properties::getConnectionTimeout)
363
.as(Duration::toMillis)
364
.as(Math::toIntExact)
365
.to(factory::setConnectionTimeout);
366
}
367
```
368
369
### Configuration Metadata
370
371
Support for generating and processing configuration metadata.
372
373
```java { .api }
374
/**
375
* Annotation that marks a field or method as being related to configuration metadata
376
*/
377
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
378
@Retention(RetentionPolicy.RUNTIME)
379
@interface ConfigurationMetadata {
380
/**
381
* A description of the configuration item
382
* @return the description
383
*/
384
String description() default "";
385
386
/**
387
* The default value of the configuration item
388
* @return the default value
389
*/
390
String defaultValue() default "";
391
392
/**
393
* Whether the configuration item is deprecated
394
* @return true if deprecated
395
*/
396
boolean deprecated() default false;
397
}
398
```
399
400
### Validation Support
401
402
Integration with Bean Validation (JSR-303) for configuration properties validation.
403
404
```java { .api }
405
/**
406
* Configuration properties can be validated using standard Bean Validation annotations
407
* when javax.validation is on the classpath
408
*/
409
410
// Example validated configuration properties class
411
@ConfigurationProperties(prefix = "app.mail")
412
@Validated
413
public class MailProperties {
414
415
@NotBlank
416
private String host;
417
418
@Range(min = 1, max = 65535)
419
private int port = 587;
420
421
422
private String username;
423
424
@Valid
425
@NestedConfigurationProperty
426
private final Smtp smtp = new Smtp();
427
428
public static class Smtp {
429
@NotNull
430
private Duration timeout = Duration.ofSeconds(30);
431
432
@Min(1)
433
@Max(10)
434
private int retries = 3;
435
436
// getters and setters
437
}
438
439
// getters and setters
440
}
441
```