Spring Boot path · The container · Topic 4 of 12

Configuration, profiles and externalised config

Not started

Spring Boot reads configuration from many places and merges them into a single Environment: application.properties or application.yml inside the jar, files next to the jar, profile-specific variants, OS environment variables, Java system properties and command-line arguments. Each source can override the ones considered before it, so a default written in the jar can be changed at deploy time without rebuilding.

Why it matters: The same jar should run on a laptop, in staging and in production; only the configuration around it should change, and you should know which value wins.

  1. 1Many sources, one Environment

    Files, environment variables, system properties and command-line arguments are layered into one set of properties.

  2. 2Later sources win

    Command-line arguments beat environment variables, which beat application.properties inside the jar.

  3. 3Profiles add a layer

    application-prod.yml is read on top of application.yml when the prod profile is active.

  4. 4Bind to types

    @ConfigurationProperties turns a prefix into a validated, immutable object instead of scattered @Value strings.

1

How it works

The explanation, with examples you can run.

Who wins

From weaker to stronger, the sources you will use most are:

  1. application.yml packaged in the jar
  2. application-{profile}.yml packaged in the jar
  3. The same two files outside the jar (for example in ./config/)
  4. OS environment variables
  5. Java system properties (-Dserver.port=9000)
  6. Command-line arguments (--server.port=9000)

Test annotations such as @SpringBootTest(properties = ...) and @DynamicPropertySource sit higher still. Environment variables use relaxed binding: SPRING_DATASOURCE_URL sets spring.datasource.url, because most shells don't allow dots in variable names.

Profiles

A profile is a named set of extra configuration. Activate it with spring.profiles.active (in any source, often SPRING_PROFILES_ACTIVE=prod), and Boot reads application-prod.yml on top of the base file. A single YAML file can hold several documents, each tied to a profile:

server:  port: 8080app:  payments:    base-url: https://sandbox.example.com    timeout: 2s---spring:  config:    activate:      on-profile: prodapp:  payments:    base-url: https://api.example.com

Beans can be limited to a profile with @Profile("dev"), but use that sparingly. Each profile-only bean is a code path that your tests may never take. Prefer the same beans everywhere with different property values.

Typed configuration

@Value("${app.payments.timeout}") works, but scatters string keys through the code. @ConfigurationProperties binds a whole prefix to one type, converts values (2s becomes a Duration) and can validate them at start-up:

@ConfigurationProperties(prefix = "app.payments")@Validatedpublic record PaymentProperties(    @NotNull URI baseUrl,    @DefaultValue("2s") Duration timeout) { } @SpringBootApplication@ConfigurationPropertiesScanpublic class App { }

A record makes the settings immutable, and a missing or malformed value fails the start-up instead of the first payment.

Secrets

Keep secrets out of the jar and out of Git. Boot reads them from environment variables, from a config tree (a directory where each file name is a key, which is how Kubernetes mounts secrets: spring.config.import=optional:configtree:/run/secrets/), or from an external store through a library. The property names stay the same, so the code never knows where a value came from.

2

Check yourself

3 questions. Get them all right to finish this topic.

  1. 1.application.yml in the jar sets server.port=8080 and the container sets SERVER_PORT=9000. Which port is used?
  2. 2.Which is the safest way to give the application a database password in production?
  3. 3.No profile is activated. Which profile files does Boot read?

0 of 3 right so far. Get all three to finish this topic.