javaspringspring-mvcspring-portlet-mvcrequestcontext

How to setThreadContextInheritable(true) via xml on Spring's dispatcherportlet and dispatcherservlet


I want to make the current request available to child threads without passing on the original request as method parameters through several layers. The application runs both as a servlet and as a portlet.

Normally, DispatcherServlet and DispatcherPortlet set the current request into a RequestContextHolder on the current thread. That way, a call thread has access to the current request. The request is not propagated to child threads.

In my case, the request spawns a subthread where it makes a ReST call using RestTemplate, and I need to access the original request in an ClientHttpRequestInterceptor that intercepts the RestTemplate. The request that is passed to intercept is useless, I need the original request that hit the server.

Both DispatcherServlet and DispatcherPortlet have a feature to pass on the RequestContext to child threads: setThreadContextInheritable(true). However, it seems not so easy to set that flag to true. There is no init-param which sets it, and usually you specify them in web.xml or portlet.xml.

Is there a way to customize a dispatcher portlet or servlet via their setters using xml configuration? The only way I found is to write a custom dispatcherservlet/portlet which sets the flag to true internally and use that in web.xml and portlet.xml.


Solution

  • There is no way to do this directly through XML configuration. You would need to do as you said and create a subclass of DispatcherServlet which internally calls setThreadContextInheritable(true).

    The alternative is to perform your ServletContext configuration in Java. Spring provides a WebApplicationInitializer and a number of useful subtypes where you can register a customized DispatcherServlet (other servlets and filters).

    You'd create your instance.

    DispatcherServlet servlet = new DispatcherServlet(context);
    servlet.setThreadContextInheritable(true);
    

    and then register it

    ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", servlet);