The written value is not necessarily the used value
Spring Boot combines sources such as files, environment variables and arguments. Among these sources under normal configuration, command-line arguments can override environment variables, which can override configuration data. A question bounded to that set should state that no additional sources or code change ordering.
If delivery.batch-size remains 60 despite its variable changing to 25, look for an old argument before rebuilding the jar. Record origin and effective value while avoiding disclosure of secrets in evidence. Do not assume the most recently edited file has higher precedence; editing time is not the resolution rule.
A property type needs registration
@ConfigurationProperties groups properties under a prefix and binds them into a structure. A record with its canonical constructor can use constructor binding. The type must be registered through EnableConfigurationProperties or appropriate property scanning. Annotating the prefix does not replace that composition decision.
Property constructor binding is also not the same operation as injecting business beans into a Component. Keep configuration focused on environment values and pass it to services using it. @DefaultValue supplies a converted textual value when a property is missing; it must not be interpreted as permission to ignore an explicitly invalid value.
Names and units belong to the contract
To transform canonical delivery.batch-size into an environment variable under the documented rule, the dot becomes an underscore, the dash is removed and letters become uppercase: DELIVERY_BATCHSIZE. Do not add a separator where the rule removes the dash. A plausible-looking variable may not represent the property you intended to change.
When binding to Duration, a unitless number defaults to milliseconds unless DurationUnit specifies another unit. Text 5s communicates five seconds; PT5S also represents an explicit duration. Choosing Duration improves the contract, but policy still needs to define which durations the operation accepts.
Conversion and validation are different decisions
Converting text to int establishes that its representation can be interpreted as that type. It does not establish that 0 is a valid batch size. In the example, Min and Max bound batchSize, while NotBlank constrains destination. Validated activates property validation with a compatible Jakarta Validation implementation present.
A violation should prevent accepting configuration the service cannot use. Removing the annotation to permit startup does not repair the value. Nor is destination text sufficient: NotBlank checks neither networking, authorization nor availability. Each rule should retain its scope, and application effects should start only after necessary conditions are satisfied.
Profiles select configuration without replacing precedence
A profile can bound configuration parts or component inclusion. spring.profiles.active follows normal source ordering and can be overridden by a higher-priority source. A packaged file declaring dev does not itself prove dev is effectively active.
spring.profiles.active belongs in a non-profile-specific document; it cannot be placed inside a document already activated by spring.config.activate.on-profile. A group declared in non-profile-specific configuration can represent an intention to activate related profiles together. Activating a profile does not establish that the environment’s credentials and destinations are valid.
Lists and imported files have their own rules
A list supplied by a higher-priority source replaces the earlier list. If a profile defines only the first element’s name, do not assume it inherits that element’s url or remaining elements. For a complete operational list, supply data required by policy or deliberately choose another configuration model.
A file imported through spring.config.import can override values in its importing document regardless of the import line’s position inside that document. optional permits a location to be missing; it does not establish availability of essential values. If a file is required, make that requirement observable at startup and validate its content as well.
Guided reading of delivery configuration
DeliveryConfiguration explicitly registers DeliveryProperties. The record binds delivery.batch-size and delivery.destination through its constructor, using defaults only for absence. Trace three cases: missing batch-size produces 20; zero fails the minimum; 25 satisfies the bounds. These outcomes assume an already identified effective source and the validation provider’s presence.
The default archive destination is an illustrative logical identifier. The example initiates no deliveries and establishes no external-service access. A complete review retains the distinction between well-formed configuration, authorized configuration and successful operation. Here learning focuses on the first boundary and the ability to justify accepting or rejecting values.
// Separate files under the application's component-scan root.
// Spring Boot 4.1.1 / Java 25; compatible Jakarta Validation provider present.
// DeliveryProperties.java
package com.acme.dispatch;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.NotBlank;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.validation.annotation.Validated;
@ConfigurationProperties("delivery")
@Validated
public record DeliveryProperties(
@DefaultValue("20") @Min(1) @Max(100) int batchSize,
@DefaultValue("archive") @NotBlank String destination) { }
// DeliveryConfiguration.java
package com.acme.dispatch;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(DeliveryProperties.class)
public class DeliveryConfiguration { }Read outcomes for absent batch-size, 0 and 25 with a known effective source. The default only handles absence; zero violates the bound. destination requires nonblank text but does not establish existence or authorization of an external destination.
Common pitfalls
Confusing defaults with replacement of invalid values; assuming list merging; placing activation inside a profile document; allowing absence of a contractually required file.
Related topics: Application context and dependencies · Validation, errors and response contracts · Health, observability and diagnosis
Accepted configuration requires known origin, appropriate conversion and valid rules. Precedence explains the observed value; validation determines whether it may be used.
Reference: External configuration ordering · Spring Boot 4.1.1 / Spring Framework 7.0.9 / Java 25