1
0
Files
spring-boot-demo/profiles-and-config/docs/06-config-trees-and-configmaps.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

← Config import · Index

6. Config trees and Kubernetes ConfigMaps

Transcript: 03-config-tree.txt.

What Kubernetes actually mounts

A ConfigMap mounted as a volume is not a properties file. Kubernetes writes one file per key, named after the key, containing only the value with no trailing newline:

<configmap-mount>/demo.datasource-url
<configmap-mount>/demo.greeting
<configmap-mount>/demo.pool-size
<configmap-mount>/demo/nested/value
<secret-mount>/demo.api-key
$ cat <configmap-mount>/demo.greeting
from-configmap-volume

There is no syntax to parse. The filename is the key.

Reading it

--spring.config.import=configtree:/etc/config/,configtree:/etc/secrets/

A trailing / is required — the location is a directory. Values arrive as properties:

  demo.pool-size      = 25
  demo.nested.value   = from-nested-directory
  demo.api-key        = sk_live_not_a_real_key

A directory under the mount becomes a nested property, so demo/nested/value is demo.nested.value. That is how a ConfigMap whose keys contain slashes arrives.

Secrets mount identically. The only difference is file permissions, which is why the same mechanism reads both and why nothing in your application needs to know which it got.

Why this beats mounting a properties file

  • Per-key updates. Changing one key rewrites one file. Kubernetes propagates it to the volume without a restart, and spring.config.import supports configtree reloading through Spring Cloud Kubernetes if you want to act on it.
  • No parse step, so no chance of one malformed line taking out the whole file.
  • Secrets and config read the same way.
  • Values can contain anything. No escaping, no quoting, no YAML surprises — a value of yes stays the string yes.

Wildcards

--spring.config.import=optional:configtree:/etc/config/*/

Reads every immediate subdirectory, which is the shape you get when several ConfigMaps are mounted under one parent. Useful for "one ConfigMap per component" layouts.

It is still config data

An imported config tree outranks application.yaml — and still loses to an environment variable:

  effective value : from-environment-variable
    1. from-environment-variable   <- systemEnvironment
    2. from-configmap-volume       <- ConfigTreePropertySource
    3. from-application-yaml       <- application.yaml

If you mount a ConfigMap and set envFrom on the same Deployment — which is a common way to migrate from one to the other — the environment variables win and the ConfigMap looks broken.

There is no profile-specific config tree

No <mount>-prod convention exists. Per-environment configuration is a different ConfigMap chosen by the Deployment, not by spring.profiles.active. This is a feature: the environment is decided by what you deploy, not by a string inside the image.