Understanding RequestContextHolder Issues in Multithreaded Spring MVC Applications
This article explains why RequestContextHolder fails to retrieve the HttpServletRequest in a multithreaded Spring MVC environment, demonstrates the problem with a concrete example, analyzes the underlying thread‑local handling of request attributes, and clarifies the default non‑inheritable behavior that leads to null requests.
When developing with Spring MVC, obtaining the current HttpServletRequest can be done either by method‑parameter injection or by using RequestContextHolder . The article first shows the typical injection approach with a simple controller example.
@Controller
public class MyController {
@RequestMapping("/example")
public String handleRequest(HttpServletRequest request) {
// use request object
return "example";
}
}The second approach uses RequestContextHolder to fetch the request from the thread‑local storage:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();The article then reproduces a problem where a new thread attempts to read a language header from the request using a utility method ServletUtils.getLanguagesExistProblem() . In the child thread the call fails with an Assert.notNull(request) error because the request retrieved via RequestContextHolder is null .
Root cause analysis reveals that Spring MVC binds RequestAttributes (which hold the ServletRequestAttributes ) to the current thread in DispatcherServlet.processRequest via initContextHolders . By default the inheritable flag is false , so the request attributes are stored in a non‑inheritable ThreadLocal . Consequently, child threads do not inherit the request context, leading to a null request.
The article shows the relevant Spring source snippets for initContextHolders and RequestContextHolder.setRequestAttributes , illustrating how the two ThreadLocal holders ( requestAttributesHolder and inheritableRequestAttributesHolder ) are used based on the inheritable flag.
In summary, to obtain the current request in a multithreaded scenario you must either make the request attributes inheritable (e.g., by configuring RequestContextHolder.setRequestAttributes(..., true) ) or explicitly pass the request object to child threads.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.