# @ConfigurationProperties vs @Value Companion project for [**@ConfigurationProperties vs @Value in Spring Boot 4**](https://ankurm.com/) on ankurm.com. Every table and transcript quoted in that article was produced by running something here. Three of them were produced twice, because the first answer was wrong — see [chapter 2](docs/02-relaxed-binding.md). ## Versions | | | |---|---| | Spring Boot | 4.1.1 | | Spring Framework | 7.0.9 | | JDK | Eclipse Temurin 25.0.4.1 (LTS) | | Validation | Hibernate Validator via `spring-boot-starter-validation` | ## Quickstart ```bash export JAVA_HOME=/path/to/jdk-25 mvn -DskipTests package ./scripts/run-all.sh # regenerate every transcript in docs/output/ mvn test # 7 contract tests ``` ## Profiles | Profile | What it does | |---|---| | *(none)* | binds `demo.*` from `application.yaml` | | `probe` | runs the relaxed-binding matrix and exits | | `envprobe` | reports one property as seen by the binder and by `@Value` | | `badvalidation` | values that violate every constraint, so startup fails | | `csvlist` | the recipients list as a comma-separated string | ## Endpoints | Endpoint | Purpose | |---|---| | `GET /diag/bound` | the bound objects, and the same values via `@Value` | | `GET /diag/origin?name=` | every source holding a property, in precedence order, with file and line | Both are diagnostics. Delete them before shipping. ## Documentation 1. [Two mechanisms, not two styles](docs/01-two-mechanisms.md) 2. [Relaxed binding, measured](docs/02-relaxed-binding.md) 3. [Getting the bean registered](docs/03-registration.md) 4. [Records, constructor binding and defaults](docs/04-records-and-defaults.md) 5. [Validation](docs/05-validation.md) 6. [When `@Value` is still the right answer](docs/06-when-value-still-wins.md) 7. [IDE metadata, and the JDK 23 change that silently breaks it](docs/07-ide-metadata.md) 8. [Diagnosing a value](docs/08-diagnosing-a-value.md) ## Captured output | File | Produced by | |---|---| | [`00-versions.txt`](docs/output/00-versions.txt) | `scripts/demo-versions.sh` | | [`01-relaxed-matrix.txt`](docs/output/01-relaxed-matrix.txt) | `scripts/demo-relaxed-matrix.sh` | | [`02-env-var-binding.txt`](docs/output/02-env-var-binding.txt) | `scripts/demo-env-binding.sh` | | [`03-value-vs-binding.txt`](docs/output/03-value-vs-binding.txt) | `scripts/demo-value-vs-binding.sh` | | [`04-validation-failure.txt`](docs/output/04-validation-failure.txt) | `scripts/demo-validation.sh` | | [`05-metadata-generation.txt`](docs/output/05-metadata-generation.txt) | `scripts/demo-metadata-generation.sh` | ## Three findings worth the trip - **`@Value` gets relaxed binding inside Spring Boot.** The universal claim that it does not is a statement about the Spring Framework; Boot attaches a property source that changes it. - **The configuration processor silently stops on JDK 23+** when declared as a plain dependency, so IDE auto-completion quietly dies while the build stays green. - **`@Valid` is not what makes nested constraints run.** Boot's `ValidationBindHandler` validates every object it binds.