Course outline

Spring Boot / Basic: composition and HTTP contracts / Lesson 3

External configuration and profiles

Bind a small typed configuration contract, explain source precedence and profile activation, and keep secrets and deployment policy outside accidental defaults.

About 5 min readContent reviewed
On this page

Lesson goals

  • Use validated ConfigurationProperties for related settings.
  • Explain effective values from layered sources.
  • Test profile and secret boundaries without printing credentials.

Treat settings as an application input API

A setting has a type, unit, requiredness, accepted range, and owner. A timeout of2 without a unit is not a complete contract. Group related application settings through @ConfigurationProperties instead of scattering unrelated @Value strings through services. Constructor-bound records make a compact immutable settings model, while validation can reject a configuration that would otherwise fail only under traffic.

Configuration is another trust boundary: a value can be syntactically bindable yet operationally unreasonable. A page-size limit of a million might be an int but violate memory and latency budgets. Validate cross-field rules explicitly where annotations do not express them. Avoid using a convenient default to hide the absence of a required deployment decision.

Register and validate one properties model

The Java fragment declares a page bound and a typed Duration, then registers the model explicitly. It requires the Boot3.5 configuration and validation dependencies, so it remains a framework illustration. Registration matters: an annotated type that is never scanned or enabled is not automatically a usable injected bean. Record constructor binding in this baseline does not require copying older setter-style patterns.

The minimum and maximum check the page limit, while @NotNull only checks timeout presence. A positive-duration rule still needs an appropriate constraint or explicit check. Validate the actual contract instead of assuming every field annotation covers every domain rule. An exception should identify the setting safely without printing secret values from the entire environment.

java An illustrative typed configuration boundary
package training.catalog;

import java.time.Duration;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.annotation.Validated;

@ConfigurationProperties("catalog")
@Validated
record CatalogProperties(@Min(1) @Max(200) int maxPageSize,
                         @NotNull Duration timeout) {}

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(CatalogProperties.class)
class CatalogConfiguration {}

The page range and timeout presence are declared; positive Duration is a separate rule. Container binding/validation was not executed.

Explain which profile document changes which value

The YAML has a base document and a training-activated overlay. When that profile is active in a correctly integrated application, the intended max-page-size is20 while timeout stays2s. This is a conditional configuration explanation, not a reported startup observation. A YAML parser can verify structure but cannot prove Boot's complete binding, source order, or bean validation.

Profiles select configuration, not authorization. A profile called production does not secure an endpoint, and an active profile can also create or remove beans. Keep activation decisions visible. Profile-specific documents have restrictions on where activation properties can be defined; do not place spring.profiles.active anywhere that happens to look convenient and assume it is always valid.

yaml A base document and explicit training overlay
catalog:
  max-page-size: 50
  timeout: 2s
---
spring:
  config:
    activate:
      on-profile: training
catalog:
  max-page-size: 20

The intended overlay changes only the page limit. Syntax parsing does not execute profile activation or verify the full Spring Environment.

Inspect effective sources without exposing secrets

Boot defines a documented property-source order. Packaged configuration, external files, environment, system properties, command-line arguments, and test overrides can supply different values; later sources in that order can override earlier ones. A checked-in file is therefore not necessarily the effective value. Tests and dynamic property sources add their own layers, so avoid an oversimplified claim that one source always wins.

Environment-variable relaxed-binding rules are specific: dots become underscores, dashes are removed, and names are uppercased. For catalog.max-page-size, the documented form is CATALOG_MAXPAGESIZE. Secrets should come through an approved distribution process and remain absent from logs and source artifacts. Do not print a complete connection string or token merely to diagnose precedence.

Test effective policy instead of only file syntax

Test defaults, overrides, absent required settings, invalid ranges, profile combinations, and secret-safe failure responses. A restricted ApplicationContextRunner or another scoped framework fixture can exercise binding without a network listener when suitable dependencies and configuration are available. Such fixtures here remain illustrative unless explicitly run; no actual service environment is loaded.

Record the resolved source origin and a redacted value category rather than sensitive content. Keep configuration versioned with the application's compatibility contract, and review changes during rollout. A well-designed settings boundary makes an invalid deployment fail early and understandably while allowing the same application artifact to run under deliberately different approved policies.

Common errors and fixes

ConfigurationPropertiesBindException

Why it happens
A required or convertible setting cannot satisfy the binding/validation contract.
How to fix it
Inspect the precise property and active source without printing all values.
Prevent it next time
Test absent, malformed, and boundary settings.

An environment override appears ignored

Why it happens
The name or effective source order differs from the assumption.
How to fix it
Use documented relaxed names and inspect source origin safely.
Prevent it next time
Test configuration through the real binding boundary.

A profile unexpectedly removed a service bean

Why it happens
Profile-based composition changed, not only a scalar setting.
How to fix it
Review active profiles and conditional registrations together.
Prevent it next time
Include profile combinations in context tests.

Check your understanding

1. Does @NotNull Duration guarantee a positive timeout?

Show worked solution

No. It checks presence. Zero or negative values need a separate supported constraint or explicit validation. Define the unit and accepted bound, and test those cases before using the value to configure an outbound client or executor.

2. A parser accepts both YAML documents. What remains unverified?

Show worked solution

Actual Spring source precedence, profile activation, properties registration, conversion, validation, and the components consuming the values. Syntax success is useful but narrower than an application-context test; do not describe it as evidence of a successful deployment.

Key takeaways

  • Configuration is typed input with units and ownership.
  • Effective values depend on documented source layering.
  • Profiles, secrets, syntax, and binding need distinct checks.

Official references