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:
- 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?