Spring (WebFlux) has e.g. this extension function:
suspend fun ServerResponse.BodyBuilder.bodyValueAndAwait(body: Any): ServerResponse =
bodyValue(body).awaitSingle()
See https://github.com/spring-projects/spring-framework/blob/master/spring-webflux/src/main/kotlin/org/springframework/web/reactive/function/server/ServerResponseExtensions.kt#L62
According to the ...AndAwait naming convention I propose these Kotlin extension functions for ReactiveUserDetailsService:
suspend fun ReactiveUserDetailsService.findByUsernameAndAwait(username: String): UserDetails? =
findByUsername(username).awaitFirstOrNull()
suspend fun ReactiveUserDetailsService.getAuthoritiesAndAwait(username: String): Collection<GrantedAuthority> {
val userDetails = findByUsernameAndAwait(username) ?: return emptyList()
return userDetails.authorities
}
suspend fun ReactiveUserDetailsService.getRolesAndAwait(username: String): Collection<String?> =
getAuthoritiesAndAwait(username).map { grantedAuthority -> grantedAuthority.authority }
Comment From: rwinch
@juergenzimmermann I think the difference is Spring's WebClient is intended to be used in blocking applications to allow parallel execution. If you need blocking operations, you should use the UserDetailsService instead of ReactiveUserDetailsService. Can you clarify why you feel this is appropriate for ReactiveUserDetailsService?
Comment From: juergenzimmermann
@rwinch I'm having a reactive microservice, and therefore I'm using ReactiveUserDetailsService. Inside the business service I've to find out the roles of the user who was sending an HTTP request to the REST API.
Comment From: rwinch
Sorry I just reread what was happening and realized it is using coroutines rather than blocking. Please ignore me :)
Comment From: eleftherias
@juergenzimmermann
I don't think getRolesAndAwait and getAuthoritiesAndAwait belong as extensions of ReactiveUserDetailsService, for the same reason that getRoles and getAuthorities are not methods in ReactiveUserDetailsService.
Roles and authorities are part of UserDetails which is why the getters are in that class.
We can modify this issue to be specific to findByUsernameAndAwait.
In the meantime, would this be equivalent to the following?
findByUsername(username).awaitFirstOrNull()
Comment From: juergenzimmermann
Yes, it will be equivalent to findByUsername(username).awaitFirstOrNull().