java yaml 90 lines · 4 tabs

Type-Safe Spring Boot Config with @ConfigurationProperties Records and Validation

Shared by codesnips Aug 2026
4 tabs
package com.example.billing.config;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(PaymentProperties.class)
public class AppConfig {
}
4 files · java, yaml Explain with highlit

This snippet shows how a modern Spring Boot application binds external configuration into an immutable Java record and validates it at startup rather than discovering bad values deep in a request path. The core idea behind @ConfigurationProperties is to group related settings under a common prefix and let Spring's relaxed binding map keys like payment.default-currency onto strongly typed fields, replacing scattered @Value("${...}") injections with a single cohesive object.

In PaymentProperties, the configuration is declared as a record annotated with @ConfigurationProperties(prefix = "payment") and @Validated. Using a record makes the bound object immutable and gives constructor binding for free: Spring calls the canonical constructor with resolved values. Nested settings are modelled with a nested Retry record, so payment.retry.max-attempts binds cleanly and stays type-safe. Bean Validation constraints (@NotBlank, @Positive, @Min, @Max, @NotNull, @Valid) live right on the components, so the schema of valid configuration is documented in code. A compact constructor supplies a sensible default Duration when the property is absent, showing how defaults coexist with validation.

Because the class carries @Validated, any constraint violation is thrown during context startup as a BindValidationException, which fails fast — a misconfigured deployment never reaches production traffic. The @Valid on the nested field is what makes Spring cascade validation into Retry; without it the inner constraints would be silently skipped, a common pitfall.

In AppConfig, @EnableConfigurationProperties(PaymentProperties.class) registers the record as a bean so it can be injected anywhere. This is the recommended alternative to @Component scanning for records and keeps the properties type free of Spring stereotypes.

In PaymentService, the validated PaymentProperties is injected through the constructor and its fields are read directly, with no null checks or parsing — the type system and startup validation already guarantee the values are present and sane. The application.yml tab shows the matching source, including kebab-case keys and the nested retry block. The trade-off is that all validation is startup-time and static; values that must change at runtime need @RefreshScope or a different mechanism. For the common case of fixed deployment config, this pattern yields safer, self-documenting, and easily testable settings.


Related snips

Share this code

Here's the card — post it anywhere.

Type-Safe Spring Boot Config with @ConfigurationProperties Records and Validation — share card
Link copied