Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KeycloakUserManagementService's user cache does not support non request scope and throws an exception #27

Open
maarten-ritense opened this issue Jan 13, 2025 · 0 comments
Assignees
Labels
bug Something isn't working

Comments

@maarten-ritense
Copy link

Expected behavior

No exception should be thrown when using the KeycloakUserManagementService.findByUserIdentifier from a non request scope like @Async or @Scheduled annotated methods.

Current behavior

When you annotate a method with @Async or @Scheduled and it then make use of the KeycloakUserManagementService.findByUserIdentifier to lookup a user via its user identifier the exception below is thrown:

org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'scopedTarget.requestScopeUserCache': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton

Possible solution (optional)

Switch to a cache mechanism which is not scope restricted. I came across the Caffeine Cache (https://github.com/ben-manes/caffeine | https://www.baeldung.com/spring-boot-caffeine-cache) which is a high-performance cache library for Java and also has support for TTL of items so maybe that is an interesting cache to switch over to.

Steps to reproduce

Example of a piece of code which fails a.t.m. due to this exception which is triggered when a task is activated which has an assignee or when a task is assigned:

import mu.KotlinLogging
import com.ritense.valtimo.contract.authentication.UserManagementService
import org.camunda.bpm.spring.boot.starter.event.TaskEvent
import org.springframework.scheduling.annotation.Async
import org.springframework.transaction.event.TransactionPhase
import org.springframework.transaction.event.TransactionalEventListener
import java.util.UUID

open class CamundaTaskAssignedEventListener(
    private val userManagementService: UserManagementService
) {

    @Async
    @TransactionalEventListener(
        condition = "#taskEvent.eventName == 'assignment' && #taskEvent.assignee != null",
        phase = TransactionPhase.AFTER_COMMIT
    )
    open fun onTaskEvent(taskEvent: TaskEvent) {
        logger.debug {
            "Triggered by assignment of CamundaTask(id=${taskEvent.id}, name=${taskEvent.name}) to ${taskEvent.assignee})"
        }
        logger.info {"""
            TaskAssignedEvent(
                taskId = taskEvent.taskDefinitionKey,
                taskName = taskEvent.name,
                assignee = findByUsername(taskEvent.assignee),
                processInstanceId = UUID.fromString(taskEvent.processInstanceId),
                taskInstanceId = UUID.fromString(taskEvent.id)
            ) triggered by assignment of CamundaTask(id=${taskEvent.id}, name=${taskEvent.name}) to ${taskEvent.assignee})""".trimIndent()
        }
    }

    fun findByUsername(username: String): String {
        logger.debug { "Trying to find e-mail for user '$username'" }
        return userManagementService.findByUserIdentifier(username)?.email
            ?: throw UserNotFoundException.forUsername(username)
    }

    companion object {
        private val logger = KotlinLogging.logger {}
    }
}
@maarten-ritense maarten-ritense added the bug Something isn't working label Jan 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants