Files
spring-boot-demo/restclient-basic-auth/docs/03-starter-split-and-exchange-trap.md
T
Claude e4b5636f7c 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
2026-09-19 10:17:09 +00:00

2.5 KiB

3. The Boot 4 starter split, and the exchange() trap

Prev: RestClient with Basic Auth, two ways | README

Source: 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). 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 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