Async, CompleteableFuture 에서 RequestContextHolder 에 접근하기
728x90
RequestContextHolder 는 ThreadLocal 을 사용하여 attributes 들을 저장하고 있다.
MVC spring 에서 비동기적으로 작업을 처리해야 할때가 있는데 이때 RequestContextHolder 에 접근하게 되면 Thread 가 달라 attributes 가 원하는 값이 나오지 않게 된다.
문제해결
@Configuration
class WebConfig : ServletContextInitializer {
override fun onStartup(servletContext: ServletContext) {
val applicationContext = AnnotationConfigWebApplicationContext()
val dispatcherServlet = DispatcherServlet(applicationContext)
dispatcherServlet.setThreadContextInheritable(true)
val dispatcher: ServletRegistration.Dynamic = servletContext.addServlet("dispatcherServlet", dispatcherServlet)
dispatcher.setLoadOnStartup(1)
dispatcher.addMapping("/")
}
}
ServletContextInitializer 의 onStartup 을 override 하여 Request 의 Main Thread 에서 Thread 가 변경될 경우 attributes 들을 copy 하여 넘기는 방식이다.
https://gompangs.tistory.com/entry/Spring-RequestContextHolder
Thread Pool 을 override 하기
class ContextAwarePoolExecutor : ThreadPoolTaskExecutor() {
override fun <T> submit(task: Callable<T>): Future<T> {
return super.submit(ContextAwareCallable(task, RequestContextHolder.currentRequestAttributes()))
}
override fun <T> submitListenable(task: Callable<T>): ListenableFuture<T> {
return super.submitListenable(ContextAwareCallable(task, RequestContextHolder.currentRequestAttributes()))
}
}
class ContextAwareCallable<T>(
private val task: Callable<T>,
private val context: RequestAttributes?
) : Callable<T> {
override fun call(): T {
if (context != null) {
RequestContextHolder.setRequestAttributes(context)
}
return try {
task.call()
} finally {
RequestContextHolder.resetRequestAttributes()
}
}
}
728x90
'Kotlin > Spring' 카테고리의 다른 글
spring boot jib 를 사용 하여 배포 자동화 하기 (w. github action) (0) | 2023.03.23 |
---|---|
Kotlin 으로 Spring batch 시작하기 Part.1 (0) | 2022.10.29 |
댓글
이 글 공유하기
다른 글
-
spring boot jib 를 사용 하여 배포 자동화 하기 (w. github action)
spring boot jib 를 사용 하여 배포 자동화 하기 (w. github action)
2023.03.23 -
Kotlin 으로 Spring batch 시작하기 Part.1
Kotlin 으로 Spring batch 시작하기 Part.1
2022.10.29