I'm new to Kotlin Coroutines and I want to call the API for each of my employees in asynchronous way. But I faced the problem that iside the new coroutine I'm unable to retrieve authentication from the SecurityContextHolder.getContext
.
Can anybody explain please why SecurityContextHolder.getContext().authentication
becomes equal null
inside GlobalScope.async{...}
block in Kotlin? Does a new coroutine have a separate security context? And how do I solve this issue? I there a way to avoid passing the authentication from the calling perform()
function to the callApi()
function?
Below you can find the code snippet:
fun perform() {
// SecurityContextHolder.getContext().authentication contains some value!!!
val deferred = employeesRepository.getEmployees().map { callApi(it) }
runBlocking {
deferred.forEach { it.await() }
}
}
fun callApi(employee: EmployeeModel) = GlobalScope.async {
// SecurityContextHolder.getContext().authentication is null here!!!
}
If I recall correctly the SecurityContextHolder.getContext()
holds a thread-local reference to the authentication object. Using coroutines you actually switch to another thread (which does not have a thread-local authentication object).
I think passing the authentication object could work, that was my first idea too when i started to read your question. Why do you want to avoid this?
Perhaps you can create a coroutine context with auth object (or is there an existing one for this purpose?), but it's only a guess from me, i have no real experience with coroutines yet.
edit: By a quick search i found this. You can find interesting ideas in this thread: https://github.com/Kotlin/kotlinx.coroutines/issues/119