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
etag-caching
Companion module for Mastering Cache Control with ETag in Spring Boot RESTful APIs on ankurm.com, re-verified against Spring Boot 4.1.1 / Spring Framework 7.0.9.
mvn test regenerates every transcript in docs/output/.
Versions
| Spring Boot | 4.1.1 |
| Spring Framework | 7.0.9 |
| JDK | Eclipse Temurin 25.0.4.1 (LTS) |
Quickstart
export JAVA_HOME=/path/to/jdk-25
mvn -DskipTests package
./scripts/run.sh
curl -i http://localhost:8080/api/products/42
mvn test # 5 tests, regenerates docs/output/
Endpoints
| Endpoint | Shows |
|---|---|
GET /api/products/{id} |
deep cache: WebRequest.checkNotModified() before the "expensive" part |
PUT /api/products/{id} |
conditional update with If-Match, optimistic locking, ETag rotation |
GET /api/echo/{message} |
shallow cache: zero-code ShallowEtagHeaderFilter on a scoped URL pattern |
Documentation
- spring-boot-starter-web is deprecated in favour of spring-boot-starter-webmvc
- ETags are unchanged, verified rather than assumed
- Deep cache vs shallow cache, and conditional PUT with If-Match
Findings worth the trip
spring-boot-starter-web's own published POM now says "deprecated in favor of spring-boot-starter-webmvc" -- read directly off Maven Central, not a migration guide. Both resolve to an identical dependency set today.ShallowEtagHeaderFilter,WebRequest.checkNotModified(), andResponseEntity.eTag()are all unchanged on Spring Framework 7.0.9 -- same packages, same behaviour, confirmed by compiling and running against them rather than assumed from the Boot 3 version of this article.- Registering
ShallowEtagHeaderFilteras a plain@Beanapplies it globally; this module scopes it to one URL pattern withFilterRegistrationBeaninstead, so it does not shadow the deliberately deeper caching on/api/products.
License
MIT -- see LICENSE.