5

I am using SpringBoot 1.5.2 release. I have an asynchronous REST call that spawns separate java thread to finish a long running job. The long running job need to update DB tables, where I configured Spring auditing bean to update table with current login username. The issue i got is: After enabling inheritable flag by calling setThreadContextInheritable(true), the ServletRequestAttributes object passed down to the child thread which does the long running DB update was marked "inactive" before the child thread finishes its job, that ends up the error when auditing bean try to access the username from ServletRequestAttributes cached in RequestContextHolder.

To turn on inheritable flag, please refer to Scope 'session' is not active for the current thread; IllegalStateException: No thread-bound request found

Here is major code to get what i have so far:

  1. In Application.java
@Override
public Executor getAsyncExecutor() {
    SimpleAsyncTaskExecutor executor = new
        SimpleAsyncTaskExecutor(appProperties.threadNamePrefix);
    return executor;
}
@Bean
public ServletRegistrationBean registerAirportDispatchServlet() {
    DispatcherServlet dispatcherServlet = new DispatcherServlet();
    AnnotationConfigWebApplicationContext applicationContext =
        new AnnotationConfigWebApplicationContext();
    dispatcherServlet.setApplicationContext(applicationContext);
    dispatcherServlet.setThreadContextInheritable(true);
    ServletRegistrationBean servletRegistrationBean =
        new ServletRegistrationBean(dispatcherServlet, "/*");
    servletRegistrationBean.setName("AirportSCSDispacherServlet");
    return servletRegistrationBean;
}
@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public AccessToken getAccessToken() {
    RequestAttributes attribs =
        RequestContextHolder.getRequestAttributes();
    //do something with the attribs here...
    return token;
}

Yes, i have to register my DispatcherServlet and set flag there instead of using RequestContextFilter and RequestContextListener because down the path of request filtering, DispatcherServlet set inheritable flag to false which will overwrite true flag set from RequestContextFilter and RequestContextListener earlier of chain. From debugging, i can tell inside the method processRequest() of FrameworkServlet which is super class of DispatcherServlet, it calls requestAttributes.requestCompleted(); at line 989, and this requestAttributes object is saved in RequestContextHolder as inherited attributes for newly spawned thread, when the new thread try to get this attributes for AccessToken, Spring framework throws error because it is marked as inactive. I have tried SESSION scope, it did not work since my REST call is not in session, i am using Keycloak for authentication, so the request attributes contains string access token in it.

I am asking here: is there better anyway that i can keep this inherited request attributes object still active?

Jeroen Steenbeeke
  • 3,884
  • 5
  • 17
  • 26
Yongqin
  • 91
  • 7
  • 1
    did u solve this issue? I also have the same issue where I have to pass request attribute to the child thread and I have used this method got same error : cant ask for request attribute. Is there any other way to solve this? Also strange thing that is happening that it is working fir first time, then it not working . Please help me out – Ankit Bansal Apr 05 '18 at 09:41
  • Please share the solution if you have fixed this... We've got exactly the same error and none of the solutions being suggested in the internet work – xbmono Nov 14 '19 at 23:48
  • I finally found this solution and it worked for me: https://medium.com/@pranav_maniar/spring-accessing-request-scope-beans-outside-of-web-request-faad27b5ed57 – xbmono Nov 15 '19 at 02:14

1 Answers1

0

I got struck with the exact same problem. My application is starting an asynchronous thread and after that sending http response back to client immediately. As i have already sent response by the time i try to get attributes in async thread, the requestActive field is false. That is the reason for this error. We can't set the requestActive field externally. Spring will handle this field according to the http request status.

manish reddy
  • 157
  • 1
  • 11