keycloak-uncached
Changes
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java 19(+19 -0)
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProvider.java 25(+24 -1)
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java 2(+2 -0)
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingRealmCache.java 15(+10 -5)
Details
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java
index a177b95..b998b8c 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java
@@ -352,6 +352,25 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
}
@Override
+ public boolean removeClient(String id, RealmModel realm) {
+ ClientModel client = getClientById(id, realm);
+ if (client == null) return false;
+ registerApplicationInvalidation(id);
+ registerRealmInvalidation(realm.getId());
+ cache.invalidateClientById(id);
+ cache.invalidateRealmById(realm.getId());
+
+
+
+ Set<RoleModel> roles = client.getRoles();
+ for (RoleModel role : roles) {
+ registerRoleInvalidation(role.getId());
+ }
+ return getDelegate().removeClient(id, realm);
+ }
+
+
+ @Override
public ClientTemplateModel getClientTemplateById(String id, RealmModel realm) {
CachedClientTemplate cached = cache.getClientTemplate(id);
if (cached != null && !cached.getRealm().equals(realm.getId())) {
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProvider.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProvider.java
index a15f4f1..4edb046 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProvider.java
@@ -105,6 +105,10 @@ public class LockingCacheRealmProvider implements CacheRealmProvider {
return delegate;
}
+ public LockingRealmCache getCache() {
+ return cache;
+ }
+
@Override
public void registerRealmInvalidation(String id) {
realmInvalidations.add(id);
@@ -354,6 +358,25 @@ public class LockingCacheRealmProvider implements CacheRealmProvider {
}
@Override
+ public boolean removeClient(String id, RealmModel realm) {
+ ClientModel client = getClientById(id, realm);
+ if (client == null) return false;
+
+ registerApplicationInvalidation(id);
+ registerRealmInvalidation(realm.getId());
+ cache.invalidateClientById(id);
+ cache.invalidateRealmById(realm.getId());
+
+
+
+ Set<RoleModel> roles = client.getRoles();
+ for (RoleModel role : roles) {
+ registerRoleInvalidation(role.getId());
+ }
+ return getDelegate().removeClient(id, realm);
+ }
+
+ @Override
public void close() {
if (delegate != null) delegate.close();
}
@@ -445,7 +468,7 @@ public class LockingCacheRealmProvider implements CacheRealmProvider {
@Override
public ClientModel getClientByClientId(String clientId, RealmModel realm) {
- CachedClient cached = cache.getClientByClientId(clientId);
+ CachedClient cached = cache.getClientByClientId(realm, clientId);
if (cached != null && !cached.getRealm().equals(realm.getId())) {
cached = null;
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java
index 6723048..23f8e53 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java
@@ -146,6 +146,8 @@ public class LockingCacheRealmProviderFactory implements CacheRealmProviderFacto
} else if (object instanceof CachedClient) {
CachedClient client = (CachedClient) object;
+ realmCache.getClientLookup().remove(client.getRealm() + "." + client.getClientId());
+
for (String r : client.getRoles().values()) {
realmCache.evictRoleById(r);
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingRealmCache.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingRealmCache.java
index 5b3060d..a77c59b 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingRealmCache.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingRealmCache.java
@@ -19,6 +19,7 @@ package org.keycloak.models.cache.infinispan.locking;
import org.infinispan.Cache;
import org.jboss.logging.Logger;
+import org.keycloak.models.RealmModel;
import org.keycloak.models.cache.RealmCache;
import org.keycloak.models.cache.entities.CachedClient;
import org.keycloak.models.cache.entities.CachedClientTemplate;
@@ -176,8 +177,8 @@ public class LockingRealmCache implements RealmCache {
return get(id, CachedClient.class);
}
- public CachedClient getClientByClientId(String clientId) {
- String id = clientLookup.get(clientId);
+ public CachedClient getClientByClientId(RealmModel realm, String clientId) {
+ String id = clientLookup.get(realm.getId() + "." + clientId);
return id != null ? getClient(id) : null;
}
@@ -185,14 +186,14 @@ public class LockingRealmCache implements RealmCache {
public void invalidateClient(CachedClient app) {
logger.tracev("Removing application {0}", app.getId());
invalidateObject(app.getId());
- clientLookup.remove(app.getClientId());
+ clientLookup.remove(getClientIdKey(app));
}
@Override
public void addClient(CachedClient app) {
logger.tracev("Adding application {0}", app.getId());
addRevisioned(app.getId(), (Revisioned) app);
- clientLookup.put(app.getClientId(), app.getId());
+ clientLookup.put(getClientIdKey(app), app.getId());
}
@Override
@@ -200,10 +201,14 @@ public class LockingRealmCache implements RealmCache {
CachedClient client = (CachedClient)invalidateObject(id);
if (client != null) {
logger.tracev("Removing application {0}", client.getClientId());
- clientLookup.remove(client.getClientId());
+ clientLookup.remove(getClientIdKey(client));
}
}
+ protected String getClientIdKey(CachedClient client) {
+ return client.getRealm() + "." + client.getClientId();
+ }
+
@Override
public void evictClientById(String id) {
logger.tracev("Evicting application {0}", id);
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
index 76aa238..684d102 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
@@ -191,7 +191,7 @@ public class RealmEntity {
@Column(name="ADMIN_EVENTS_DETAILS_ENABLED")
protected boolean adminEventsDetailsEnabled;
- @OneToOne
+ @OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="MASTER_ADMIN_CLIENT")
protected ClientEntity masterAdminClient;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
index 55b6087..ce245de 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
@@ -17,6 +17,7 @@
package org.keycloak.models.jpa;
+import org.jboss.logging.Logger;
import org.keycloak.migration.MigrationModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
@@ -43,6 +44,7 @@ import java.util.List;
* @version $Revision: 1 $
*/
public class JpaRealmProvider implements RealmProvider {
+ protected static final Logger logger = Logger.getLogger(JpaRealmProvider.class);
private final KeycloakSession session;
protected EntityManager em;
@@ -115,7 +117,6 @@ public class JpaRealmProvider implements RealmProvider {
if (realm == null) {
return false;
}
-
RealmAdapter adapter = new RealmAdapter(session, em, realm);
session.users().preRemove(adapter);
int num = em.createNamedQuery("deleteGroupRoleMappingsByRealm")
@@ -144,6 +145,11 @@ public class JpaRealmProvider implements RealmProvider {
em.flush();
em.clear();
+ realm = em.find(RealmEntity.class, id);
+ if (realm != null) {
+ logger.error("WTF is the realm still there after a removal????????");
+ }
+
return true;
}
@@ -188,6 +194,31 @@ public class JpaRealmProvider implements RealmProvider {
}
@Override
+ public boolean removeClient(String id, RealmModel realm) {
+ ClientModel client = getClientById(id, realm);
+ if (client == null) return false;
+
+ session.users().preRemove(realm, client);
+
+ for (RoleModel role : client.getRoles()) {
+ client.removeRole(role);
+ }
+
+
+ ClientEntity clientEntity = ((ClientAdapter)client).getEntity();
+ em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", clientEntity).executeUpdate();
+ em.flush();
+ em.remove(clientEntity); // i have no idea why, but this needs to come before deleteScopeMapping
+ try {
+ em.flush();
+ } catch (RuntimeException e) {
+ logger.errorv("Unable to delete client entity: {0} from realm {1}", client.getClientId(), realm.getName());
+ throw e;
+ }
+ return true;
+ }
+
+ @Override
public ClientTemplateModel getClientTemplateById(String id, RealmModel realm) {
ClientTemplateEntity app = em.find(ClientTemplateEntity.class, id);
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index eb03e53..da66a3b 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -17,6 +17,7 @@
package org.keycloak.models.jpa;
+import org.jboss.logging.Logger;
import org.keycloak.connections.jpa.util.JpaUtils;
import org.keycloak.common.enums.SslRequired;
import org.keycloak.models.AuthenticationExecutionModel;
@@ -65,6 +66,7 @@ import java.util.Set;
* @version $Revision: 1 $
*/
public class RealmAdapter implements RealmModel {
+ protected static final Logger logger = Logger.getLogger(RealmAdapter.class);
protected RealmEntity realm;
protected EntityManager em;
protected volatile transient PublicKey publicKey;
@@ -774,34 +776,7 @@ public class RealmAdapter implements RealmModel {
if (id == null) return false;
ClientModel client = getClientById(id);
if (client == null) return false;
-
- session.users().preRemove(this, client);
-
- for (RoleModel role : client.getRoles()) {
- client.removeRole(role);
- }
-
- ClientEntity clientEntity = null;
- Iterator<ClientEntity> it = realm.getClients().iterator();
- while (it.hasNext()) {
- ClientEntity ae = it.next();
- if (ae.getId().equals(id)) {
- clientEntity = ae;
- it.remove();
- break;
- }
- }
- for (ClientEntity a : realm.getClients()) {
- if (a.getId().equals(id)) {
- clientEntity = a;
- }
- }
- if (clientEntity == null) return false;
- em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", clientEntity).executeUpdate();
- em.remove(clientEntity);
- em.flush();
-
- return true;
+ return session.realms().removeClient(id, this);
}
@Override
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java
index ddfbdef..c5d70fb 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java
@@ -163,6 +163,17 @@ public class MongoRealmProvider implements RealmProvider {
}
@Override
+ public boolean removeClient(String id, RealmModel realm) {
+ if (id == null) return false;
+ ClientModel client = getClientById(id, realm);
+ if (client == null) return false;
+
+ session.users().preRemove(realm, client);
+
+ return getMongoStore().removeEntity(MongoClientEntity.class, id, invocationContext);
+ }
+
+ @Override
public ClientModel getClientByClientId(String clientId, RealmModel realm) {
DBObject query = new QueryBuilder()
.and("realmId").is(realm.getId())
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index ca7626c..701cced 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -868,10 +868,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
if (id == null) return false;
ClientModel client = getClientById(id);
if (client == null) return false;
-
- session.users().preRemove(this, client);
-
- return getMongoStore().removeEntity(MongoClientEntity.class, id, invocationContext);
+ return session.realms().removeClient(id, this);
}
@Override
diff --git a/server-spi/src/main/java/org/keycloak/models/RealmProvider.java b/server-spi/src/main/java/org/keycloak/models/RealmProvider.java
index 59568a3..2b3f5fa 100755
--- a/server-spi/src/main/java/org/keycloak/models/RealmProvider.java
+++ b/server-spi/src/main/java/org/keycloak/models/RealmProvider.java
@@ -40,6 +40,9 @@ public interface RealmProvider extends Provider {
RoleModel getRoleById(String id, RealmModel realm);
+
+ boolean removeClient(String id, RealmModel realm);
+
ClientTemplateModel getClientTemplateById(String id, RealmModel realm);
GroupModel getGroupById(String id, RealmModel realm);
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index dbaaad2..55695a0 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -211,10 +211,11 @@ public class RealmManager implements RealmImporter {
public boolean removeRealm(RealmModel realm) {
List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
+ ClientModel masterAdminClient = realm.getMasterAdminClient();
boolean removed = model.removeRealm(realm.getId());
if (removed) {
- if (realm.getMasterAdminClient() != null) {
- new ClientManager(this).removeClient(getKeycloakAdminstrationRealm(), realm.getMasterAdminClient());
+ if (masterAdminClient != null) {
+ new ClientManager(this).removeClient(getKeycloakAdminstrationRealm(), masterAdminClient);
}
UserSessionProvider sessions = session.sessions();
diff --git a/testsuite/stress/src/main/java/org/keycloak/test/stress/MaxRateExecutor.java b/testsuite/stress/src/main/java/org/keycloak/test/stress/MaxRateExecutor.java
index cfc9cd5..e56aa83 100755
--- a/testsuite/stress/src/main/java/org/keycloak/test/stress/MaxRateExecutor.java
+++ b/testsuite/stress/src/main/java/org/keycloak/test/stress/MaxRateExecutor.java
@@ -11,7 +11,8 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
- * Executes all test threads until completion.
+ * Executes a test N number of times. This is done multiple times over an ever expanding amount of threads to determine
+ * when the computer is saturated and you can't eek out any more concurrent requests.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $