When using @Async, there will be a new thread to execute the task the task which is annoted with @Async. In a case that you tend to copy the data from the original thread to the @Async thread,like this case - copy MDC data to @Async thread, then you need to use TaskDecorator to reach your goal.
Please refer to official docs to implement @Async in you application.
Then implement the taskDecorator.
class MdcTaskDecorator implements TaskDecorator {
@Override
public Runnable decorate(Runnable runnable) {
// Right now: Web thread context !
// (Grab the current thread MDC data)
Map<String, String> contextMap = MDC.getCopyOfContextMap();
return () -> {
try {
// Right now: @Async thread context !
// (Restore the Web thread context's MDC data)
MDC.setContextMap(contextMap);
runnable.run();
} finally {
MDC.clear();
}
};
}
}
Then config ThreadPoolExecutor for your @Async:
@Configuration
public class AsyncConfig implements AsyncConfigurer {
@Autowired
private ThreadPoolProperties threadPoolProperties;
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(threadPoolProperties.getCoreSize());
executor.setMaxPoolSize(threadPoolProperties.getMaxSize());
executor.setQueueCapacity(threadPoolProperties.getQueueCapacity());
executor.setThreadNamePrefix("threadPoolExecutor-");
//set the decorator to the executor
executor.setTaskDecorator(new MdcTaskDecorator());
executor.initialize();
return executor;
}
}
Refered to https://moelholm.com/blog/2017/07/24/spring-43-using-a-taskdecorator-to-copy-mdc-data-to-async-threads.