Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring request scope proxy: resolve state for the current HTTP request

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

A request-scoped proxy lets a singleton depend on an object selected from the active web request instead of storing one request's state globally.

Download Spring source kit

The Spring source kit uses Java 21 and its pinned Spring Boot dependencies. Run the named JUnit test to check this boundary.

Inject the proxy, not a captured request

The singleton ReceiptLabel reads its tenant from a proxied RequestTenant. The test binds request A and request B in turn, calls the same singleton, and observes different tenant labels. The singleton object identity stays stable while the request target changes.

Use a method call on the proxy. Direct field access reads a field on the proxy object and can bypass request-target lookup. The proxy does not authenticate either tenant. A production tenant must come from trusted identity and authorization rules, not an untrusted header stored in request scope.

No request context means no target

After the test clears RequestContextHolder, invoking the proxy throws a ScopeNotActiveException. That is expected for background work without an HTTP request. Capture a narrow authorized value and pass it explicitly to a task instead of retaining a request-scoped proxy in asynchronous work. Compare executor context boundaries.

Checked contract

Java
class RequestTenant {
    private String name;
    void setName(String value) { name = value; }
    String name() { return name; }
}
@Configuration
static class Config {
    @Bean @RequestScope(proxyMode = ScopedProxyMode.TARGET_CLASS)
    RequestTenant requestTenant() { return new RequestTenant(); }
    @Bean ReceiptLabel receiptLabel(RequestTenant tenant) { return new ReceiptLabel(tenant); }
}
record ReceiptLabel(RequestTenant tenant) {
    String text() { return tenant.name; }
}

How it is checked

RequestScopeBoundaryTest.resolvesASeparateTargetPerBoundRequest covers this behavior in the source kit. The displayed code is the test boundary; the kit contains its imports and configuration.

Costs and boundaries

One request target is retained per active request context, plus a singleton proxy. This local test does not measure concurrent traffic, session persistence or authentication; the scope ends with request cleanup.

Common Mistakes

  • Do not put caller-provided tenant text into a trusted authorization decision.
  • Do not call request-scoped targets from a background worker without an explicit context policy.
  • Do not assume scoped proxy means the target itself is thread-safe.

Read next

Spring bean scopes: singleton identity is not thread safety, Spring task executors: capacity, rejection and lost context, Spring method authorization: test the proxied service boundary, Java ThreadLocal: clear request state on reused worker threads.

Continue with the new boundary checks

Continue with Spring session scope: one target across requests, separate targets across sessions.

spring
spring-boot
request-scope-proxy
Storage details