New Java Features Are Not Just for Interviews. Two Real-World Use Cases from Axelix
Description and use
The article demonstrates replacing ThreadLocal with ScopedValue to safely and automatically propagate an authentication context into deep transport-layer code. ScopedValue provides a bounded execution scope, preventing token leakage and mutation.
Problem
Passing an authentication token from an HTTP filter to deep transport-layer code without propagating it through many method parameters, while ensuring the token cannot be mutated or leaked between requests.
Outcome
ScopedValue replaced ThreadLocal for passing SecurityContext, eliminating mutable shared state, ensuring automatic cleanup, and preventing accidental token leakage or mutation.
Workflow
- 1. In the servlet filter, create a SecurityContext from the authenticated user.
- 2. Call Master’s callWithinSecurityContext with the SecurityContext and a ThrowingCallable that performs the operation.
- 3. Inside callWithinSecurityContext, use ScopedValue.where(...).call(...) to bind the SecurityContext for the duration of the callable.
- 4. Within the callable, any code can retrieve the SecurityContext via ScopedValue.get() without passing it as a parameter.
- 5. After the callable completes (normally or exceptionally), the ScopedValue binding is automatically removed, preventing leakage.
Evidence
In Java 25, ScopedValue was finalized. It solves a narrower problem than ThreadLocal: it allows a value to be passed down the call chain for the duration of a particular operation.
The key difference lies in the model itself. A ThreadLocal resembles a mutable box attached to a thread. A ScopedValue describes the binding of a value within a dynamic execution scope.
- Record date: 2026-09-21T08:00:30.864Z