0
# Configuration
1
2
Micronaut's configuration system provides type-safe property binding, environment-specific configuration loading, and hot-reload support for development with comprehensive validation and nested object support.
3
4
## Capabilities
5
6
### Configuration Properties
7
8
Bind configuration properties to typed objects with validation and nested configuration support.
9
10
```java { .api }
11
/**
12
* Basic configuration properties
13
*/
14
@ConfigurationProperties("app.database")
15
public class DatabaseConfiguration {
16
private String host = "localhost";
17
private int port = 5432;
18
private String username;
19
private String password;
20
private String database;
21
private boolean ssl = false;
22
23
// getters and setters
24
public String getHost() { return host; }
25
public void setHost(String host) { this.host = host; }
26
27
public int getPort() { return port; }
28
public void setPort(int port) { this.port = port; }
29
30
// ... other getters and setters
31
}
32
33
/**
34
* Configuration with validation
35
*/
36
@ConfigurationProperties("app.server")
37
public class ServerConfiguration {
38
39
@NotBlank
40
private String name;
41
42
@Min(1024)
43
@Max(65535)
44
private int port = 8080;
45
46
47
private String adminEmail;
48
49
@URL
50
private String baseUrl;
51
52
@Valid
53
private SslConfig ssl;
54
55
// getters and setters
56
}
57
58
/**
59
* Nested configuration
60
*/
61
public static class SslConfig {
62
private boolean enabled = false;
63
private String keyStore;
64
private String keyStorePassword;
65
private String protocol = "TLS";
66
67
// getters and setters
68
}
69
```
70
71
### Environment-Specific Configuration
72
73
Load different configurations based on the active environment.
74
75
```java { .api }
76
/**
77
* Environment-specific configuration
78
*/
79
@ConfigurationProperties("cache")
80
@Requires(env = Environment.DEVELOPMENT)
81
public class DevelopmentCacheConfiguration {
82
private String type = "caffeine";
83
private long maxSize = 100;
84
private Duration expireAfterWrite = Duration.ofMinutes(5);
85
86
// getters and setters
87
}
88
89
@ConfigurationProperties("cache")
90
@Requires(env = Environment.PRODUCTION)
91
public class ProductionCacheConfiguration {
92
private String type = "redis";
93
private String host = "redis.example.com";
94
private int port = 6379;
95
private Duration expireAfterWrite = Duration.ofHours(1);
96
97
// getters and setters
98
}
99
100
/**
101
* Conditional configuration based on properties
102
*/
103
@ConfigurationProperties("monitoring")
104
@Requires(property = "monitoring.enabled", value = "true")
105
public class MonitoringConfiguration {
106
private String endpoint;
107
private Duration interval = Duration.ofMinutes(1);
108
private List<String> metrics = new ArrayList<>();
109
110
// getters and setters
111
}
112
```
113
114
### Property Value Injection
115
116
Inject individual property values into beans and methods.
117
118
```java { .api }
119
/**
120
* Property value injection in beans
121
*/
122
@Singleton
123
public class ApiService {
124
125
@Value("${api.base-url}")
126
private String baseUrl;
127
128
@Value("${api.timeout:30s}")
129
private Duration timeout;
130
131
@Value("${api.retries:3}")
132
private int maxRetries;
133
134
@Value("${api.enabled:true}")
135
private boolean enabled;
136
137
public ApiService(@Value("${api.key}") String apiKey,
138
@Value("${api.version:v1}") String version) {
139
// Constructor injection of properties
140
}
141
}
142
143
/**
144
* Property injection in configuration methods
145
*/
146
@Factory
147
public class ServiceFactory {
148
149
@Bean
150
@Singleton
151
public ExternalService externalService(@Value("${external.service.url}") String url,
152
@Value("${external.service.token}") String token) {
153
return new ExternalService(url, token);
154
}
155
}
156
```
157
158
### Dynamic Configuration
159
160
Support for configuration that can change at runtime with refresh capabilities.
161
162
```java { .api }
163
/**
164
* Refreshable configuration
165
*/
166
@ConfigurationProperties("feature-flags")
167
@Refreshable
168
public class FeatureFlagConfiguration {
169
private Map<String, Boolean> flags = new HashMap<>();
170
private boolean debugMode = false;
171
172
public boolean isFeatureEnabled(String feature) {
173
return flags.getOrDefault(feature, false);
174
}
175
176
// getters and setters
177
}
178
179
/**
180
* Using refreshable configuration
181
*/
182
@Singleton
183
public class FeatureService {
184
private final FeatureFlagConfiguration featureConfig;
185
186
public FeatureService(FeatureFlagConfiguration featureConfig) {
187
this.featureConfig = featureConfig;
188
}
189
190
public boolean isNewUiEnabled() {
191
return featureConfig.isFeatureEnabled("new-ui");
192
}
193
}
194
195
/**
196
* Configuration refresh event handling
197
*/
198
@Singleton
199
public class ConfigurationRefreshListener {
200
201
@EventListener
202
public void onRefresh(RefreshEvent event) {
203
log.info("Configuration refreshed: {}", event.getSource());
204
// React to configuration changes
205
}
206
}
207
```
208
209
### List and Map Configuration
210
211
Configure collections and complex nested structures.
212
213
```java { .api }
214
/**
215
* List and map configuration
216
*/
217
@ConfigurationProperties("app")
218
public class ApplicationConfiguration {
219
220
private List<String> allowedOrigins = new ArrayList<>();
221
private Map<String, String> headers = new HashMap<>();
222
private List<ServerConfig> servers = new ArrayList<>();
223
224
// getters and setters
225
public List<String> getAllowedOrigins() { return allowedOrigins; }
226
public void setAllowedOrigins(List<String> allowedOrigins) {
227
this.allowedOrigins = allowedOrigins;
228
}
229
230
public Map<String, String> getHeaders() { return headers; }
231
public void setHeaders(Map<String, String> headers) {
232
this.headers = headers;
233
}
234
}
235
236
/**
237
* Nested object in lists
238
*/
239
public static class ServerConfig {
240
private String name;
241
private String host;
242
private int port;
243
private List<String> protocols = new ArrayList<>();
244
245
// getters and setters
246
}
247
248
/**
249
* Multiple configuration instances using @EachProperty
250
*/
251
@EachProperty("databases")
252
@ConfigurationProperties("databases")
253
public class DatabaseInstanceConfiguration {
254
private String name;
255
private String url;
256
private String driver;
257
private int maxConnections = 10;
258
259
// This will create separate configuration instances for:
260
// databases.primary.*, databases.secondary.*, etc.
261
262
// getters and setters
263
}
264
```
265
266
### Configuration Builders
267
268
Use builder pattern for complex configuration objects.
269
270
```java { .api }
271
/**
272
* Configuration with builder support
273
*/
274
@ConfigurationProperties("http-client")
275
public class HttpClientConfiguration {
276
277
@ConfigurationBuilder(prefixes = "")
278
private ConnectionPoolConfiguration connectionPool =
279
ConnectionPoolConfiguration.builder().build();
280
281
@ConfigurationBuilder(prefixes = "ssl")
282
private SslConfiguration ssl = SslConfiguration.builder().build();
283
284
private Duration readTimeout = Duration.ofSeconds(30);
285
private boolean followRedirects = true;
286
287
// getters and setters
288
}
289
290
/**
291
* Builder-based configuration classes
292
*/
293
public class ConnectionPoolConfiguration {
294
private int maxConnections = 10;
295
private Duration idleTimeout = Duration.ofMinutes(5);
296
private boolean keepAlive = true;
297
298
public static Builder builder() {
299
return new Builder();
300
}
301
302
public static class Builder {
303
private ConnectionPoolConfiguration config = new ConnectionPoolConfiguration();
304
305
public Builder maxConnections(int maxConnections) {
306
config.maxConnections = maxConnections;
307
return this;
308
}
309
310
public Builder idleTimeout(Duration idleTimeout) {
311
config.idleTimeout = idleTimeout;
312
return this;
313
}
314
315
// other builder methods
316
317
public ConnectionPoolConfiguration build() {
318
return config;
319
}
320
}
321
322
// getters
323
}
324
```
325
326
### Configuration Sources
327
328
Configure multiple sources for properties with precedence handling.
329
330
```java { .api }
331
/**
332
* Custom property source
333
*/
334
@Singleton
335
@Primary
336
public class DatabasePropertySource implements PropertySource {
337
338
@Override
339
public String getName() {
340
return "database-config";
341
}
342
343
@Override
344
public Object get(String key) {
345
// Load from database
346
return configRepository.findByKey(key);
347
}
348
349
@Override
350
public Iterator<String> iterator() {
351
return configRepository.findAllKeys().iterator();
352
}
353
354
@Override
355
public int getOrder() {
356
return HIGHEST_PRECEDENCE;
357
}
358
}
359
360
/**
361
* Property source loader for custom formats
362
*/
363
@Singleton
364
public class YamlPropertySourceLoader implements PropertySourceLoader {
365
366
@Override
367
public Set<String> getExtensions() {
368
return Set.of("yml", "yaml");
369
}
370
371
@Override
372
public Optional<PropertySource> load(String resourceName, InputStream inputStream) {
373
try {
374
// Parse YAML and create property source
375
Map<String, Object> properties = yamlParser.parse(inputStream);
376
return Optional.of(PropertySource.of(resourceName, properties));
377
} catch (Exception e) {
378
return Optional.empty();
379
}
380
}
381
}
382
```
383
384
### Configuration Validation
385
386
Validate configuration at startup with custom validators.
387
388
```java { .api }
389
/**
390
* Configuration with Bean Validation annotations
391
*/
392
@ConfigurationProperties("payment")
393
public class PaymentConfiguration {
394
395
@NotBlank(message = "Payment provider is required")
396
private String provider;
397
398
@Valid
399
@NotNull
400
private ProviderConfig config;
401
402
@Min(value = 1, message = "Timeout must be at least 1 second")
403
@Max(value = 300, message = "Timeout cannot exceed 5 minutes")
404
private int timeoutSeconds = 30;
405
406
@Pattern(regexp = "^[A-Z]{3}$", message = "Currency must be 3-letter ISO code")
407
private String defaultCurrency = "USD";
408
409
// getters and setters
410
}
411
412
/**
413
* Custom validator for configuration
414
*/
415
@Singleton
416
public class PaymentConfigurationValidator {
417
418
@EventListener
419
public void validateOnStartup(StartupEvent event) {
420
ApplicationContext context = event.getSource();
421
PaymentConfiguration config = context.getBean(PaymentConfiguration.class);
422
423
if (!isValidProvider(config.getProvider())) {
424
throw new ConfigurationException(
425
"Invalid payment provider: " + config.getProvider());
426
}
427
}
428
429
private boolean isValidProvider(String provider) {
430
return Set.of("stripe", "paypal", "square").contains(provider.toLowerCase());
431
}
432
}
433
```
434
435
## Types
436
437
```java { .api }
438
// Core configuration interfaces
439
public interface Environment extends PropertyResolver {
440
Set<String> getActiveNames();
441
Collection<PropertySource> getPropertySources();
442
Environment addPropertySource(PropertySource propertySource);
443
Environment removePropertySource(PropertySource propertySource);
444
445
static final String DEVELOPMENT = "dev";
446
static final String TEST = "test";
447
static final String PRODUCTION = "prod";
448
}
449
450
public interface PropertySource extends Iterable<String> {
451
String getName();
452
Object get(String key);
453
int getOrder();
454
455
static PropertySource of(String name, Map<String, Object> values);
456
static PropertySource of(Map<String, Object> values);
457
}
458
459
public interface PropertyResolver {
460
boolean containsProperty(String name);
461
boolean containsProperties(String name);
462
<T> Optional<T> getProperty(String name, Class<T> requiredType);
463
<T> T getProperty(String name, Class<T> requiredType, T defaultValue);
464
String getProperty(String name, String defaultValue);
465
Optional<String> getProperty(String name);
466
}
467
468
// Configuration binding
469
public interface PropertyPlaceholderResolver {
470
Optional<String> resolvePlaceholders(String str);
471
String resolveRequiredPlaceholders(String str);
472
}
473
474
public interface ConversionService {
475
<T> Optional<T> convert(Object object, Class<T> targetType);
476
<T> Optional<T> convert(Object object, Argument<T> targetType);
477
<T> T convert(Object object, Class<T> targetType, T defaultValue);
478
}
479
480
// Configuration events
481
public class RefreshEvent extends ApplicationEvent {
482
public RefreshEvent(Object source) {
483
super(source);
484
}
485
}
486
487
public class ConfigurationChangedEvent extends ApplicationEvent {
488
private final String propertyName;
489
private final Object oldValue;
490
private final Object newValue;
491
492
// constructors and getters
493
}
494
495
// Property source loaders
496
public interface PropertySourceLoader {
497
Set<String> getExtensions();
498
Optional<PropertySource> load(String resourceName, InputStream inputStream);
499
Map<String, PropertySourceLoader> getLoadersMap();
500
}
501
502
// Configuration exceptions
503
public class ConfigurationException extends RuntimeException {
504
public ConfigurationException(String message);
505
public ConfigurationException(String message, Throwable cause);
506
}
507
508
public class PropertyNotFoundException extends ConfigurationException {
509
public PropertyNotFoundException(String property);
510
}
511
```