1
0
Files
spring-boot-demo/profiles-and-config/docs/04-why-your-profile-file-lost.md
Ankur Mhatre 86246dc860 Three new article modules: configuration binding, profiles and config data, Spring AOP
configuration-properties/  @ConfigurationProperties vs @Value on Spring Boot 4.1.1.
  The relaxed-binding matrix is generated by binding each spelling rather than
  transcribed, and re-checked against real processes -- the in-process probe was
  wrong twice before it was right. Records the three findings that came out of it:
  @Value does get relaxed resolution inside Spring Boot (Boot attaches
  ConfigurationPropertySources), the configuration processor silently stops
  generating metadata on JDK 23+ when declared as a plain dependency, and @Valid is
  not what makes nested constraints run.

profiles-and-config/       Precedence, profiles, spring.config.import and config trees.
  /precedence reports every source holding a property in rank order with file and
  line, which turns "my profile file had no effect" into a two-line answer. Also
  pins the counterintuitive one: an imported file outranks the file that imported it.

spring-aop/                Designators, proxy types, and aspects that do not fire.
  One advice per supported designator so the reference table is generated from real
  matches; all fourteen unsupported designators fed to the parser. Two corrections to
  the reference documentation: unsupported designators throw
  UnsupportedPointcutPrimitiveException (extends RuntimeException, not
  IllegalArgumentException), and spring-boot-starter-aop was renamed to
  spring-boot-starter-aspectj in Boot 4.

19 contract tests across the three modules, 15 captured transcripts, all regenerated
by scripts/run-all.sh. Verified on Spring Boot 4.1.1, Spring Framework 7.0.9,
JDK 25.0.4.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gip4srpzMwjgoba6uEfbr5
2026-09-08 16:47:48 +00:00

2.9 KiB

← Seeing precedence · Index · Config import →

4. Why your profile-specific file lost

Transcript: 02-profile-file-loses.txt.

The bug: you set a value in application-prod.yaml, deploy with prod active, and the old value is still in effect.

Two runs, one difference

--- 1. prod profile active, no environment variable ---
  effective value : jdbc:postgresql://prod-db:5432/orders
    1. jdbc:postgresql://prod-db:5432/orders   <- application-prod.yaml
    2. jdbc:h2:mem:default                     <- application.yaml

Working as intended. Now with one leftover variable in the environment:

--- 2. identical, plus one leftover environment variable ---
  effective value : jdbc:postgresql://leftover:5432/orders
    1. jdbc:postgresql://leftover:5432/orders  <- systemEnvironment
    2. jdbc:postgresql://prod-db:5432/orders   <- application-prod.yaml
    3. jdbc:h2:mem:default                     <- application.yaml

The profile file was still loaded. It still holds the right value. It is at rank 2.

Why it feels wrong

Profile-specific files do override — the mental model is not wrong, it is incomplete. They override other config data. Config data as a whole sits at item 3 in the precedence list and environment variables at item 5, so the strongest file loses to the weakest variable.

Where the leftover variables come from

Every one of these is real:

  • A Kubernetes Deployment with an env: block that predates the ConfigMap and was never removed. envFrom a ConfigMap produces environment variables, not config data.
  • A docker-compose.yml environment: entry copied from a colleague.
  • Spring Cloud Kubernetes or a service mesh injecting SPRING_DATASOURCE_URL.
  • A CI runner exporting variables for a different service.
  • SPRING_APPLICATION_JSON, which is item 10 and beats almost everything.

Diagnosing it in one step

If a property is not what the file says, look for a variable:

kubectl exec deploy/my-app -- env | grep -i datasource

or ask the running application, which reports every holder including the one you did not know about.

Living with it

Prefer environment variables in containers, files for defaults. The precedence order is designed for exactly this: the image carries defaults, the deployment overrides them. Fighting it means fighting the design.

Do not set the same key in both places. If a value is per-environment, keep it out of the profile files entirely so there is only ever one source.

Name environment variables specifically. DEMO_DATASOURCE_URL collides with nothing; SPRING_DATASOURCE_URL collides with every Spring application on the host.

Mount configuration as a config tree instead. Still config data, still below environment variables, but at least it is one mechanism rather than two — chapter 6.