skip to content

Explain relaxed binding: what property-name forms map to the same field?

level: middleimportance: must knowfreq 70%

answer

  1. kebab / camel / underscore / UPPER
  2. canonical = lowercase kebab
  3. env vars: UPPER + underscores, no dots/dashes
  4. only @ConfigurationProperties
  5. enums case-insensitive

basics

~10 s

Relaxed binding lets one bean field be filled from several property-name spellings — kebab-case, camelCase, snake_case, and UPPER underscore. So app.my-prop, app.myProp, app.my_prop and APP_MYPROP all bind to the same field.

solid answer

~40 s

Relaxed binding is Spring Boot's rule that a single @ConfigurationProperties field can be matched by multiple property-name formats, so you don't have to spell keys exactly like Java identifiers. For a field firstName under prefix app, all of app.first-name (kebab), app.firstName (camel), app.first_name (underscore) and APP_FIRSTNAME (upper-case env style) bind to it. The canonical recommended form is lowercase kebab-case. Crucially, relaxed binding applies per source with limits: environment variables must use uppercase with underscores replacing dots and dashes (APP_FIRST_NAME), because many shells forbid dots/dashes in var names. Relaxed binding only works for @ConfigurationProperties, not @Value. It also drives list/index binding and enum matching (case-insensitive). This is why the same setting works whether it comes from YAML, a .properties file, or a container env var.

code

java · 13 lines
java
@ConfigurationProperties(prefix = "app.connection")
public class ConnectionProps {
    private String remoteAddress;  // field name
    private int maxRetries;
    // getters/setters omitted
}

// ALL of these bind remoteAddress -> the same field:
//   application.yml     : app.connection.remote-address: 10.0.0.1
//   application.yml     : app.connection.remoteAddress: 10.0.0.1
//   application.properties: app.connection.remote_address=10.0.0.1
//   env var             : APP_CONNECTION_REMOTEADDRESS=10.0.0.1
//   command line        : --app.connection.remote-address=10.0.0.1

go deeper

for a junior

Name the four spellings and that kebab-case is canonical.

for a middle

Explain the per-source env-var rule (UPPER + underscores) and that it's @ConfigurationProperties-only.

for a senior

Tie it to 12-factor config: same setting from YAML or K8s env without code changes; enum/list handling.

for a principal

Set org conventions: kebab in files, document env-var mapping, avoid mixed spellings that confuse audits.

## What relaxed binding is A Java field name is a strict identifier (`firstName`). External configuration comes from many sources with different naming conventions. **Relaxed binding** is the algorithm the Spring Boot `Binder` uses to treat several property-name spellings as equivalent, so any of them binds to the same target field. This applies **only to `@ConfigurationProperties`** (and the programmatic `Binder`), never to `@Value`. ## The accepted forms For a property `app.first-name`, all of these are equivalent and bind to field `firstName` (prefix `app`): - `app.first-name` — **kebab-case** (recommended canonical form) - `app.firstName` — camelCase - `app.first_name` — underscore - `APP_FIRSTNAME` / `APP_FIRST_NAME` — upper-case (for system environment variables) The canonical form Spring recommends storing config in is **lowercase kebab-case**. ## Per-source rules (the key gotcha) Which forms are actually usable depends on the property *source*: - **`.properties` / `.yml`**: all of kebab, camel, underscore work; use kebab. - **System environment variables**: must be **UPPERCASE**, with `.` and `-` replaced by `_`. So `spring.datasource.url` becomes `SPRING_DATASOURCE_URL`; `app.first-name` becomes `APP_FIRSTNAME` (dashes removed) or `APP_FIRST_NAME`. This is because POSIX shells disallow `.` and `-` in variable names. - **System properties / command line** (`-Dapp.first-name=...` / `--app.first-name=...`): use the dotted form. ## Lists, maps, enums - Lists: `app.servers[0]=a` (indexed) or comma-separated `app.servers=a,b` for simple types. - Maps: `app.limits.gold=10`, `app.limits.silver=5`. - Enums: matched **case-insensitively** and with relaxed rules, so `mode: FULL`, `mode: full`, `mode: full-scan` all resolve reasonably. ## Why it exists It decouples where config lives (YAML file vs Kubernetes env var vs command line) from how the code names its fields, letting the *same* logical setting be supplied from any source without renaming. ## Common gotchas - Trying relaxed binding with `@Value` — it won't work; the placeholder must be exact. - Expecting `app.first-name` to work as an env var literally — you must use `APP_FIRSTNAME`. - Assuming camelCase in YAML is 'wrong' — it binds, but kebab-case is the recommended style. - Prefix itself must be kebab-case and start/end without dashes.

  • How do you express spring.datasource.url as an environment variable?
    SPRING_DATASOURCE_URL — uppercase, dots replaced by underscores. Dashes are removed or become underscores; env vars can't contain dots or dashes.
  • Does relaxed binding work with @Value?
    No. @Value requires the exact property name in the placeholder; relaxed binding is a feature of the @ConfigurationProperties Binder only.

saying these in an interview costs you the question

  • Claiming APP.FIRST-NAME works as an env var (dots/dashes aren't allowed in env var names)
  • Saying relaxed binding also covers @Value
  • Believing only kebab-case binds and camelCase in YAML fails

context