Add custom-validation, etag-caching, restclient-basic-auth: Boot 4.1 API pass

Three companion modules verifying and rewriting the Boot 4.1.1 / Framework
7.0.9 story for three older articles: the javax->jakarta.validation namespace
fix plus Jakarta Validation 3.1 record-validation clarification, ETag/
conditional-request APIs re-verified unchanged plus the starter rename, and
RestTemplate Basic Auth rebuilt on RestClient with the exchange() trap called
out. 19 real passing tests generate every transcript quoted from the three
companion articles.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EQNA6DJ9VgCtW6zhCE8Xud
This commit is contained in:
Claude
2026-09-19 10:17:09 +00:00
parent 03bdf7ee87
commit e4b5636f7c
75 changed files with 2374 additions and 0 deletions
@@ -0,0 +1,40 @@
# 3. The Boot 4 starter split, and the exchange() trap
[Prev: RestClient with Basic Auth, two ways](02-restclient-basic-auth-patterns.md) | [README](../README.md)
Source: [`pom.xml`](../pom.xml).
## `spring-boot-starter-restclient` is not optional in Boot 4
The original article's `spring-boot-starter-web` dependency was, on Boot 3, sufficient to get an
auto-configured `RestTemplateBuilder` bean for free. On Boot 4.1, HTTP client support moved into
its own starter, confirmed the same way every version fact in this repository is confirmed --
build a throwaway project and read the real dependency tree:
```
$ mvn dependency:tree # against spring-boot-starter-parent:4.1.1 + spring-boot-starter-webmvc only
```
`spring-boot-starter-webmvc` alone does **not** pull in `spring-boot-restclient`. Leave
`spring-boot-starter-restclient` off this module's `pom.xml` and the auto-configured
`RestClient.Builder` this chapter's code depends on is simply not there -- a `NoSuchBeanDefinitionException`
at startup, not a subtle behavioural difference. This module declares it explicitly.
## The trap this module deliberately avoids
`RestClient` has its own `exchange()` method, and it means something different from
`RestTemplate.exchange()`: **RestClient's `exchange()` disables the default status handlers**, so a
4xx or 5xx response is silently returned to you instead of thrown. Every example in this module
uses `retrieve()` for exactly that reason -- `retrieve()` keeps the throw-on-4xx/5xx behaviour this
Basic Auth demo relies on (see [`docs/output/03-restclient-no-credentials-401.txt`](output/03-restclient-no-credentials-401.txt)).
A team that mechanically renames `restTemplate.exchange(...)` call sites to
`restClient.exchange(...)` during a migration ships code that stops noticing failed requests. The
[RestTemplate to RestClient migration guide](https://ankurm.com/resttemplate-to-restclient-migration-guide/)
covers this trap, the full method-mapping table, and the three behavioural differences that matter
in more depth than a Basic Auth-focused rewrite has room for.
## Going deeper
- [RestTemplate to RestClient Migration Guide](https://ankurm.com/resttemplate-to-restclient-migration-guide/) -- the exchange() trap, timeouts, and the full mapping table
- [Spring Boot 4 HTTP Service Clients (@HttpExchange)](https://ankurm.com/spring-boot-4-http-service-clients/) -- the declarative layer built on top of RestClient
- Prev: [RestClient with Basic Auth, two ways](02-restclient-basic-auth-patterns.md)