How to enable request scope in async task executor
We ran into the same problem - needed to execute code in the background using @Async, so it was unable to use any Session- or RequestScope beans. We solved it the following way:
- Create a custom TaskPoolExecutor that stores scoped information with the tasks
- Create a special Callable (or Runnable) that uses the information to set and clear the context for the background thread
- Create an override configuration to use the custom executor
Note: this will only work for Session and Request scoped beans, and not for security context (as in Spring Security). You'd have to use another method to set the security context if that is what you're after.
Note2: For brevity, only shown the Callable and submit() implementation. You can do the same for the Runnable and execute().
Here is the code:
Executor:
public class ContextAwarePoolExecutor extends ThreadPoolTaskExecutor {
@Override
public <T> Future<T> submit(Callable<T> task) {
return super.submit(new ContextAwareCallable(task, RequestContextHolder.currentRequestAttributes()));
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
return super.submitListenable(new ContextAwareCallable(task, RequestContextHolder.currentRequestAttributes()));
}
}
Callable:
public class ContextAwareCallable<T> implements Callable<T> {
private Callable<T> task;
private RequestAttributes context;
public ContextAwareCallable(Callable<T> task, RequestAttributes context) {
this.task = task;
this.context = context;
}
@Override
public T call() throws Exception {
if (context != null) {
RequestContextHolder.setRequestAttributes(context);
}
try {
return task.call();
} finally {
RequestContextHolder.resetRequestAttributes();
}
}
}
Configuration:
@Configuration
public class ExecutorConfig extends AsyncConfigurerSupport {
@Override
@Bean
public Executor getAsyncExecutor() {
return new ContextAwarePoolExecutor();
}
}
SimpleAsyncTaskExecutor Interceptor - Enable Request Scope in SimpleAsyncTaskExecutor
So I also tried another solution using ThreadPoolTaskExecutor.
Basically I used this solution: http://www.chrisport.ch/java/2016/10/12/java-spring-context-aware.html and switched MDC context stuff to final RequestAttributes originalContextCopy = RequestContextHolder.getRequestAttributes();
and RequestContextHolder.resetRequestAttributes();
Scope 'request' is not active for the current thread while using @Async
That is correct, an @Async thread cannot be bound to or use request scope as there is no request scope in the asynchronous execution.
Related Topics
Mockito - Nullpointerexception When Stubbing Method
Convert Yyyy-Mm-Dd Hh:Mm:Ss.Sss Zzz Format Strin to Date Object
Spring Security - 405 Request Method 'Post' Not Supported
How to Get Spring Boot to Automatically Create Database Schema
How to Pass the Same Object Across Multiple Classes Java
How to Move Marker Along Polyline Using Google Map
Eclipse Problems View Not Showing Errors Anymore
How to Replace Every N-Th Character X from an String
How to Set a Description and an Example in Swagger With Swagger Annotations
Bootstrap.Yml Not Loading in Spring Boot 2
Chrome Browser Is Not Opening in Selenium Webdriver
How to Handle Incorrect User Input into a Scanner
Selenium Webdriver: Modifying Navigator.Webdriver Flag to Prevent Selenium Detection
How to Run Java Program in Terminal With External Library Jar
How to Store User Input into an Existing Array
Why Does Intellij Idea Suddenly Not Recognize Tests in Test Folder Anymore
Is There a Simpler Way to Check Multiple Values Against One Value in an If-Statement