I stopped trusting slide-deck explanations of Spring proxies, ThreadLocals, and HikariCP. So I built a lab where every trap has a broken path, a fixed path, and assertions that force the JVM to show the bug.
Repo: jeffreyjose07/spring-validation-lab
Stack: Java 21, Spring Boot 4.1, Gradle 9.3, H2, JUnit
This post is the series index. The short overview was not enough — the detailed write-ups live in the posts below.
Deep dives
| # | Post | What we proved |
|---|---|---|
| 1 | Proxies and self-invocation | this.method() skips the proxy; REQUIRES_NEW is dead text; separate bean leaves the independent row after outer rollback |
| 2 | ThreadLocals and @Async | Naive executor loses Authentication (context object can still be non-null); explicit args and DelegatingSecurityContextRunnable fix it |
| 3 | Bean lifecycle and mini-umbrellas | @PostConstruct before proxy; constructor cycles fail to boot; Spring Data invents mini-TXs without an outer umbrella |
| 4 | HikariCP, hogging, optimistic locking | REQUIRES_NEW vs pool of 10; HTTP inside TX after first SQL; @Version under 20 concurrent buyers |
Teaching notes in the repo mirror the same path under docs/. Folklore corrections live in docs/ground-truth.md.
The loop
- State the production trap.
- Write the broken service on purpose.
- Assert the failure (wrong rows, NPE, timeouts, pool fully checked out).
- Write the fixed design.
- Assert the success.
- Write down every place Boot 4.1 disagreed with the blog-post version of Spring.
How to try it
git clone https://github.com/jeffreyjose07/spring-validation-lab.git cd spring-validation-lab export JAVA_HOME=$(/usr/libexec/java_home -v 21) # macOS ./gradlew test --tests '*SelfInvocationProxyTest'Open a single test in IntelliJ and watch the Run console for LabLog banners like:
========== [PHASE1-PROXY] BROKEN self-invocation ========== → Calling this.saveIndependently(...) — REQUIRES_NEW sticky note will NOT be readWhat I am not doing next (yet)
I am deliberately not racing into Kafka outbox / saga posts until the Phase 1–2 proofs feel boring. The point of this lab is competence under the hood, not checklist coverage.
If you interview for Spring-heavy backend roles: stop only reading about proxies. Make one fail on purpose. Keep the green and red tests. Write down every place the framework surprised you.