Hi everyone!
We have an IDP mapper plugin that works fine with the UserModel.setSingleAttribute
method to add attributes to a user after his login.
However, we’re facing a situation where we need to add these attributes asynchronously using a new thread. First question: is that possible?
We’ve tried different approaches involving sessions and context injections, but we consistently encounter a persistence context error, like “Cannot access delegate without a transaction.”
Before going to the API Client method thats works fine, we would like to exhaust the other possibilities.
Here is the example code thats we try:
@Override
protected void setValuesOnModel(UserModel user, BrokeredIdentityContext context) throws IOException {
user.setSingleAttribute("works", "fine"); //works fine!
KeycloakSessionFactory factory = this.session.getKeycloakSessionFactory();
CompletableFuture.runAsync(() -> {
try{
try { Thread.sleep(5000); }
catch (InterruptedException e) { e.printStackTrace(); }
KeycloakSession newsession = factory.create();
UserModel userdd = newsession.users().getUserById(this.realm, user.getId());
LOGGER.warnf(userdd.getFirstName()); // print MAURO
user.setSingleAttribute("thread", "attribute"); //Error
}catch (Exception e) {
e.printStackTrace();
}
});
}
The results:
keycloak-server | 2024-11-28 11:21:58,321 WARN [br.gov.pbh.mappers.idp.GovBrCnpjsMapper] (ForkJoinPool.commonPool-worker-1) MAURO
keycloak-server | java.lang.IllegalStateException: Cannot access delegate without a transaction
keycloak-server | at org.keycloak.models.cache.infinispan.UserCacheSession.getDelegate(UserCacheSession.java:119)
keycloak-server | at org.keycloak.models.cache.infinispan.UserAdapter.getUserModel(UserAdapter.java:453)
keycloak-server | at org.keycloak.models.cache.infinispan.UserAdapter.getDelegateForUpdate(UserAdapter.java:103)
keycloak-server | at org.keycloak.models.cache.infinispan.UserAdapter.setSingleAttribute(UserAdapter.java:176)
keycloak-server | at br.gov.pbh.mappers.idp.GovBrCnpjsMapper.lambda$setValuesOnModel$1(GovBrCnpjsMapper.java:120)
keycloak-server | at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804)
keycloak-server | at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1796)
keycloak-server | at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:387)
keycloak-server | at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312)
keycloak-server | at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843)
keycloak-server | at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808)
keycloak-server | at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188)
In one of several tests scenarios, we noticed that while the main thread is active, in the second thread add attributes works fine. After terminating the main thread, the error occurs in the second, like both, eventualy, is using the same persistence context closed by the first.
We are using keycloak 25.0.4
We would like some advice.
Thank you all very much!