keycloak-aplcache

Merge pull request #3688 from pedroigor/KEYCLOAK-4125 [KEYCLOAK-4125]

12/21/2016 8:34:10 PM

Details

diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java
index e332de0..dfc22dd 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java
@@ -21,6 +21,7 @@ package org.keycloak.models.authorization.infinispan;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -51,7 +52,7 @@ public class CachedPolicyStore implements PolicyStore {
 
     private static final String POLICY_ID_CACHE_PREFIX = "policy-id-";
 
-    private final Cache<String, List<CachedPolicy>> cache;
+    private final Cache<String, Map<String, List<CachedPolicy>>> cache;
     private final KeycloakSession session;
     private final CacheTransaction transaction;
     private final List<String> cacheKeys;
@@ -78,7 +79,7 @@ public class CachedPolicyStore implements PolicyStore {
         String id = policy.getId();
 
         this.transaction.whenRollback(() -> {
-            cache.remove(getCacheKeyForPolicy(id));
+            resolveResourceServerCache(resourceServer.getId()).remove(getCacheKeyForPolicy(id));
         });
 
         this.transaction.whenCommit(() -> {
@@ -90,14 +91,13 @@ public class CachedPolicyStore implements PolicyStore {
 
     @Override
     public void delete(String id) {
-        Policy policy = findById(id, null);
+        Policy policy = getDelegate().findById(id, null);
         if (policy == null) {
             return;
         }
         ResourceServer resourceServer = policy.getResourceServer();
         getDelegate().delete(id);
         this.transaction.whenCommit(() -> {
-            cache.remove(getCacheKeyForPolicy(id));
             invalidateCache(resourceServer.getId());
         });
     }
@@ -105,13 +105,15 @@ public class CachedPolicyStore implements PolicyStore {
     @Override
     public Policy findById(String id, String resourceServerId) {
         String cacheKeyForPolicy = getCacheKeyForPolicy(id);
-        List<CachedPolicy> cached = this.cache.get(cacheKeyForPolicy);
+        List<CachedPolicy> cached = resolveResourceServerCache(resourceServerId).get(cacheKeyForPolicy);
 
         if (cached == null) {
             Policy policy = getDelegate().findById(id, resourceServerId);
 
             if (policy != null) {
-                return createAdapter(updatePolicyCache(policy));
+                CachedPolicy cachedPolicy = new CachedPolicy(policy);
+                resolveResourceServerCache(resourceServerId).put(cacheKeyForPolicy, Arrays.asList(cachedPolicy));
+                return createAdapter(cachedPolicy);
             }
 
             return null;
@@ -137,12 +139,12 @@ public class CachedPolicyStore implements PolicyStore {
 
     @Override
     public List<Policy> findByResource(String resourceId, String resourceServerId) {
-        return cacheResult(new StringBuilder("findByResource").append(resourceServerId).append(resourceId).toString(), () -> getDelegate().findByResource(resourceId, resourceServerId));
+        return cacheResult(resourceServerId, new StringBuilder("findByResource").append(resourceId).toString(), () -> getDelegate().findByResource(resourceId, resourceServerId));
     }
 
     @Override
     public List<Policy> findByResourceType(String resourceType, String resourceServerId) {
-        return cacheResult(new StringBuilder("findByResourceType").append(resourceServerId).append(resourceType).toString(), () -> getDelegate().findByResourceType(resourceType, resourceServerId));
+        return cacheResult(resourceServerId, new StringBuilder("findByResourceType").append(resourceType).toString(), () -> getDelegate().findByResourceType(resourceType, resourceServerId));
     }
 
     @Override
@@ -150,7 +152,7 @@ public class CachedPolicyStore implements PolicyStore {
         List<Policy> policies = new ArrayList<>();
 
         for (String scopeId : scopeIds) {
-            policies.addAll(cacheResult(new StringBuilder("findByScopeIds").append(resourceServerId).append(scopeId).toString(), () -> getDelegate().findByScopeIds(Arrays.asList(scopeId), resourceServerId)));
+            policies.addAll(cacheResult(resourceServerId, new StringBuilder("findByScopeIds").append(scopeId).toString(), () -> getDelegate().findByScopeIds(Arrays.asList(scopeId), resourceServerId)));
         }
 
         return policies;
@@ -158,7 +160,7 @@ public class CachedPolicyStore implements PolicyStore {
 
     @Override
     public List<Policy> findByType(String type, String resourceServerId) {
-        return cacheResult(new StringBuilder("findByType").append(resourceServerId).append(type).toString(), () -> getDelegate().findByType(type, resourceServerId));
+        return cacheResult(resourceServerId, new StringBuilder("findByType").append(type).toString(), () -> getDelegate().findByType(type, resourceServerId));
     }
 
     @Override
@@ -388,11 +390,10 @@ public class CachedPolicyStore implements PolicyStore {
                     this.updated = getDelegate().findById(getId(), cached.getResourceServerId());
                     if (this.updated == null) throw new IllegalStateException("Not found in database");
                     transaction.whenCommit(() -> {
-                        cache.remove(getCacheKeyForPolicy(getId()));
                         invalidateCache(cached.getResourceServerId());
                     });
                     transaction.whenRollback(() -> {
-                        cache.remove(getCacheKeyForPolicy(getId()));
+                        resolveResourceServerCache(cached.getResourceServerId()).remove(getCacheKeyForPolicy(getId()));
                     });
                 }
 
@@ -408,23 +409,12 @@ public class CachedPolicyStore implements PolicyStore {
         return cachedStoreFactory;
     }
 
-    private CachedPolicy updatePolicyCache(Policy policy) {
-        CachedPolicy cached = new CachedPolicy(policy);
-        List<CachedPolicy> cache = new ArrayList<>();
-
-        cache.add(cached);
-
-        this.cache.put(getCacheKeyForPolicy(policy.getId()), cache);
-
-        return cached;
-    }
-
     private void invalidateCache(String resourceServerId) {
-        cacheKeys.forEach(cacheKey -> cache.keySet().stream().filter(key -> key.startsWith(cacheKey + resourceServerId)).forEach(cache::remove));
+        cache.remove(resourceServerId);
     }
 
-    private List<Policy> cacheResult(String key, Supplier<List<Policy>> provider) {
-        List<CachedPolicy> cached = cache.computeIfAbsent(key, (Function<String, List<CachedPolicy>>) o -> {
+    private List<Policy> cacheResult(String resourceServerId, String key, Supplier<List<Policy>> provider) {
+        List<CachedPolicy> cached = resolveResourceServerCache(resourceServerId).computeIfAbsent(key, (Function<String, List<CachedPolicy>>) o -> {
             List<Policy> result = provider.get();
 
             if (result.isEmpty()) {
@@ -440,4 +430,8 @@ public class CachedPolicyStore implements PolicyStore {
 
         return cached.stream().map(cachedPolicy -> createAdapter(cachedPolicy)).collect(Collectors.toList());
     }
+
+    private Map<String, List<CachedPolicy>> resolveResourceServerCache(String id) {
+        return cache.computeIfAbsent(id, key -> new HashMap<>());
+    }
 }
\ No newline at end of file
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceServerStore.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceServerStore.java
index ed98500..95d3dba 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceServerStore.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceServerStore.java
@@ -18,9 +18,10 @@
 
 package org.keycloak.models.authorization.infinispan;
 
-import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.infinispan.Cache;
 import org.keycloak.authorization.model.ResourceServer;
@@ -44,7 +45,7 @@ public class CachedResourceServerStore implements ResourceServerStore {
     private final CacheTransaction transaction;
     private StoreFactory storeFactory;
     private ResourceServerStore delegate;
-    private final Cache<String, List> cache;
+    private final Cache<String, Map<String, List<CachedResourceServer>>> cache;
 
     public CachedResourceServerStore(KeycloakSession session, CacheTransaction transaction, StoreFactory storeFactory) {
         this.session = session;
@@ -58,34 +59,33 @@ public class CachedResourceServerStore implements ResourceServerStore {
     public ResourceServer create(String clientId) {
         ResourceServer resourceServer = getDelegate().create(clientId);
 
-        this.transaction.whenRollback(() -> cache.remove(getCacheKeyForResourceServer(resourceServer.getId())));
+        this.transaction.whenRollback(() -> resolveResourceServerCache(resourceServer.getId()).remove(getCacheKeyForResourceServer(resourceServer.getId())));
 
         return createAdapter(new CachedResourceServer(resourceServer));
     }
 
     @Override
     public void delete(String id) {
+        ResourceServer resourceServer = getDelegate().findById(id);
         getDelegate().delete(id);
         this.transaction.whenCommit(() -> {
-            List<CachedResourceServer> servers = cache.remove(getCacheKeyForResourceServer(id));
-
-            if (servers != null) {
-                CachedResourceServer entry = servers.get(0);
-                cache.remove(getCacheKeyForResourceServerClientId(entry.getClientId()));
-            }
+            cache.remove(id);
+            cache.remove(resourceServer.getClientId());
         });
     }
 
     @Override
     public ResourceServer findById(String id) {
         String cacheKeyForResourceServer = getCacheKeyForResourceServer(id);
-        List<ResourceServer> cached = this.cache.get(cacheKeyForResourceServer);
+        List<CachedResourceServer> cached = resolveResourceServerCache(id).get(cacheKeyForResourceServer);
 
         if (cached == null) {
             ResourceServer resourceServer = getDelegate().findById(id);
 
             if (resourceServer != null) {
-                return createAdapter(updateResourceServerCache(resourceServer));
+                CachedResourceServer cachedResourceServer = new CachedResourceServer(resourceServer);
+                resolveResourceServerCache(id).put(cacheKeyForResourceServer, Arrays.asList(cachedResourceServer));
+                return createAdapter(cachedResourceServer);
             }
 
             return null;
@@ -97,20 +97,20 @@ public class CachedResourceServerStore implements ResourceServerStore {
     @Override
     public ResourceServer findByClient(String id) {
         String cacheKeyForResourceServer = getCacheKeyForResourceServerClientId(id);
-        List<String> cached = this.cache.get(cacheKeyForResourceServer);
+        List<CachedResourceServer> cached = resolveResourceServerCache(id).get(cacheKeyForResourceServer);
 
         if (cached == null) {
             ResourceServer resourceServer = getDelegate().findByClient(id);
 
             if (resourceServer != null) {
-                cache.put(cacheKeyForResourceServer, Arrays.asList(resourceServer.getId()));
+                resolveResourceServerCache(cacheKeyForResourceServer).put(cacheKeyForResourceServer, Arrays.asList(new CachedResourceServer(resourceServer)));
                 return findById(resourceServer.getId());
             }
 
             return null;
         }
 
-        return findById(cached.get(0));
+        return createAdapter(cached.get(0));
     }
 
     private String getCacheKeyForResourceServer(String id) {
@@ -173,7 +173,10 @@ public class CachedResourceServerStore implements ResourceServerStore {
                 if (this.updated == null) {
                     this.updated = getDelegate().findById(getId());
                     if (this.updated == null) throw new IllegalStateException("Not found in database");
-                    transaction.whenCommit(() -> cache.remove(getCacheKeyForResourceServer(getId())));
+                    transaction.whenCommit(() -> {
+                        cache.remove(getId());
+                        cache.remove(getClientId());
+                    });
                 }
 
                 return this.updated;
@@ -181,14 +184,7 @@ public class CachedResourceServerStore implements ResourceServerStore {
         };
     }
 
-    private CachedResourceServer updateResourceServerCache(ResourceServer resourceServer) {
-        CachedResourceServer cached = new CachedResourceServer(resourceServer);
-        List<ResourceServer> cache = new ArrayList<>();
-
-        cache.add(cached);
-
-        this.cache.put(getCacheKeyForResourceServer(resourceServer.getId()), cache);
-
-        return cached;
+    private Map<String, List<CachedResourceServer>> resolveResourceServerCache(String id) {
+        return cache.computeIfAbsent(id, key -> new HashMap<>());
     }
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceStore.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceStore.java
index 92adf6c..b016702 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceStore.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceStore.java
@@ -21,6 +21,7 @@ package org.keycloak.models.authorization.infinispan;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -53,7 +54,7 @@ public class CachedResourceStore implements ResourceStore {
     private final List<String> cacheKeys;
     private StoreFactory storeFactory;
     private ResourceStore delegate;
-    private final Cache<String, List<CachedResource>> cache;
+    private final Cache<String, Map<String, List<CachedResource>>> cache;
 
     public CachedResourceStore(KeycloakSession session, CacheTransaction transaction, StoreFactory storeFactory) {
         this.session = session;
@@ -63,6 +64,7 @@ public class CachedResourceStore implements ResourceStore {
         cacheKeys = new ArrayList<>();
         cacheKeys.add("findByOwner");
         cacheKeys.add("findByUri");
+        cacheKeys.add("findByName");
         this.storeFactory = storeFactory;
     }
 
@@ -71,12 +73,11 @@ public class CachedResourceStore implements ResourceStore {
         Resource resource = getDelegate().create(name, getStoreFactory().getResourceServerStore().findById(resourceServer.getId()), owner);
 
         this.transaction.whenRollback(() -> {
-            cache.remove(getCacheKeyForResource(resource.getId()));
+            resolveResourceServerCache(resourceServer.getId()).remove(getCacheKeyForResource(resource.getId()));
         });
 
         this.transaction.whenCommit(() -> {
             invalidateCache(resourceServer.getId());
-            getCachedStoreFactory().getPolicyStore().notifyChange(resource);
         });
 
         return createAdapter(new CachedResource(resource));
@@ -84,35 +85,29 @@ public class CachedResourceStore implements ResourceStore {
 
     @Override
     public void delete(String id) {
-        Resource resource = findById(id, null);
+        Resource resource = getDelegate().findById(id, null);
         if (resource == null) {
             return;
         }
         ResourceServer resourceServer = resource.getResourceServer();
         getDelegate().delete(id);
         this.transaction.whenCommit(() -> {
-            List<CachedResource> resources = cache.remove(getCacheKeyForResource(id));
-
-            if (resources != null) {
-                CachedResource entry = resources.get(0);
-                cache.remove(getCacheKeyForResourceName(entry.getName(), entry.getResourceServerId()));
-            }
-
             invalidateCache(resourceServer.getId());
-            getCachedStoreFactory().getPolicyStore().notifyChange(resource);
         });
     }
 
     @Override
     public Resource findById(String id, String resourceServerId) {
         String cacheKeyForResource = getCacheKeyForResource(id);
-        List<CachedResource> cached = this.cache.get(cacheKeyForResource);
+        List<CachedResource> cached = resolveResourceServerCache(resourceServerId).get(cacheKeyForResource);
 
         if (cached == null) {
             Resource resource = getDelegate().findById(id, resourceServerId);
 
             if (resource != null) {
-                return createAdapter(updateResourceCache(resource));
+                CachedResource cachedResource = new CachedResource(resource);
+                resolveResourceServerCache(resourceServerId).put(cacheKeyForResource, Arrays.asList(cachedResource));
+                return createAdapter(cachedResource);
             }
 
             return null;
@@ -123,12 +118,12 @@ public class CachedResourceStore implements ResourceStore {
 
     @Override
     public List<Resource> findByOwner(String ownerId, String resourceServerId) {
-        return cacheResult(new StringBuilder("findByOwner").append(resourceServerId).append(ownerId).toString(), () -> getDelegate().findByOwner(ownerId, resourceServerId));
+        return cacheResult(resourceServerId, new StringBuilder("findByOwner").append(ownerId).toString(), () -> getDelegate().findByOwner(ownerId, resourceServerId));
     }
 
     @Override
     public List<Resource> findByUri(String uri, String resourceServerId) {
-        return cacheResult(new StringBuilder("findByUri").append(resourceServerId).append(uri).toString(), () -> getDelegate().findByUri(uri, resourceServerId));
+        return cacheResult(resourceServerId, new StringBuilder("findByUri").append(uri).toString(), () -> getDelegate().findByUri(uri, resourceServerId));
     }
 
     @Override
@@ -149,13 +144,14 @@ public class CachedResourceStore implements ResourceStore {
     @Override
     public Resource findByName(String name, String resourceServerId) {
         String cacheKeyForResource = getCacheKeyForResourceName(name, resourceServerId);
-        List<CachedResource> cached = this.cache.get(cacheKeyForResource);
+        List<CachedResource> cached = resolveResourceServerCache(resourceServerId).get(cacheKeyForResource);
 
         if (cached == null) {
             Resource resource = getDelegate().findByName(name, resourceServerId);
 
             if (resource != null) {
-                cache.put(cacheKeyForResource, Arrays.asList(new CachedResource(resource)));
+                invalidateCache(resourceServerId);
+                resolveResourceServerCache(resourceServerId).put(cacheKeyForResource, Arrays.asList(new CachedResource(resource)));
                 return findById(resource.getId(), resourceServerId);
             }
 
@@ -280,15 +276,14 @@ public class CachedResourceStore implements ResourceStore {
 
             private Resource getDelegateForUpdate() {
                 if (this.updated == null) {
-                    this.updated = getDelegate().findById(getId(), cached.getResourceServerId());
+                    String resourceServerId = cached.getResourceServerId();
+                    this.updated = getDelegate().findById(getId(), resourceServerId);
                     if (this.updated == null) throw new IllegalStateException("Not found in database");
                     transaction.whenCommit(() -> {
-                        cache.remove(getCacheKeyForResource(cached.getId()));
-                        invalidateCache(cached.getResourceServerId());
-                        getCachedStoreFactory().getPolicyStore().notifyChange(updated);
+                        invalidateCache(resourceServerId);
                     });
                     transaction.whenRollback(() -> {
-                        cache.remove(getCacheKeyForResource(cached.getId()));
+                        resolveResourceServerCache(resourceServerId).remove(getCacheKeyForResource(cached.getId()));
                     });
                 }
 
@@ -301,19 +296,8 @@ public class CachedResourceStore implements ResourceStore {
         return session.getProvider(CachedStoreFactoryProvider.class);
     }
 
-    private CachedResource updateResourceCache(Resource resource) {
-        CachedResource cached = new CachedResource(resource);
-        List cache = new ArrayList<>();
-
-        cache.add(cached);
-
-        this.cache.put(getCacheKeyForResource(resource.getId()), cache);
-
-        return cached;
-    }
-
-    private List<Resource> cacheResult(String key, Supplier<List<Resource>> provider) {
-        List<CachedResource> cached = cache.computeIfAbsent(key, (Function<String, List<CachedResource>>) o -> {
+    private List<Resource> cacheResult(String resourceServerId, String key, Supplier<List<Resource>> provider) {
+        List<CachedResource> cached = resolveResourceServerCache(resourceServerId).computeIfAbsent(key, (Function<String, List<CachedResource>>) o -> {
             List<Resource> result = provider.get();
 
             if (result.isEmpty()) {
@@ -327,10 +311,20 @@ public class CachedResourceStore implements ResourceStore {
             return Collections.emptyList();
         }
 
-        return cached.stream().map(this::createAdapter).collect(Collectors.toList());
+        List<Resource> adapters = new ArrayList<>();
+
+        for (CachedResource resource : cached) {
+            adapters.add(createAdapter(resource));
+        }
+
+        return adapters;
     }
 
     private void invalidateCache(String resourceServerId) {
-        cacheKeys.forEach(cacheKey -> cache.keySet().stream().filter(key -> key.startsWith(cacheKey + resourceServerId)).forEach(cache::remove));
+        cache.remove(resourceServerId);
+    }
+
+    private Map<String, List<CachedResource>> resolveResourceServerCache(String id) {
+        return cache.computeIfAbsent(id, key -> new HashMap<>());
     }
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedScopeStore.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedScopeStore.java
index 5be00b4..3a0de26 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedScopeStore.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedScopeStore.java
@@ -18,13 +18,12 @@
 
 package org.keycloak.models.authorization.infinispan;
 
-import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.infinispan.Cache;
-import org.keycloak.authorization.model.Resource;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.model.Scope;
 import org.keycloak.authorization.store.ScopeStore;
@@ -43,7 +42,7 @@ public class CachedScopeStore implements ScopeStore {
     private static final String SCOPE_ID_CACHE_PREFIX = "scp-id-";
     private static final String SCOPE_NAME_CACHE_PREFIX = "scp-name-";
 
-    private final Cache<String, List> cache;
+    private final Cache<String, Map<String, List<CachedScope>>> cache;
     private final KeycloakSession session;
     private final CacheTransaction transaction;
     private ScopeStore delegate;
@@ -61,9 +60,9 @@ public class CachedScopeStore implements ScopeStore {
     public Scope create(String name, ResourceServer resourceServer) {
         Scope scope = getDelegate().create(name, getStoreFactory().getResourceServerStore().findById(resourceServer.getId()));
 
-        this.transaction.whenRollback(() -> cache.remove(getCacheKeyForScope(scope.getId())));
+        this.transaction.whenRollback(() -> resolveResourceServerCache(resourceServer.getId()).remove(getCacheKeyForScope(scope.getId())));
         this.transaction.whenCommit(() -> {
-            getCachedStoreFactory().getPolicyStore().notifyChange(scope);
+            invalidateCache(resourceServer.getId());
         });
 
         return createAdapter(new CachedScope(scope));
@@ -71,33 +70,29 @@ public class CachedScopeStore implements ScopeStore {
 
     @Override
     public void delete(String id) {
-        Scope scope = findById(id, null);
+        Scope scope = getDelegate().findById(id, null);
         if (scope == null) {
             return;
         }
+        ResourceServer resourceServer = scope.getResourceServer();
         getDelegate().delete(id);
         this.transaction.whenCommit(() -> {
-            List<CachedScope> scopes = cache.remove(getCacheKeyForScope(id));
-
-            if (scopes != null) {
-                CachedScope entry = scopes.get(0);
-                cache.remove(getCacheKeyForScopeName(entry.getName(), entry.getResourceServerId()));
-            }
-
-            getCachedStoreFactory().getPolicyStore().notifyChange(scope);
+            invalidateCache(resourceServer.getId());
         });
     }
 
     @Override
     public Scope findById(String id, String resourceServerId) {
         String cacheKeyForScope = getCacheKeyForScope(id);
-        List<CachedScope> cached = this.cache.get(cacheKeyForScope);
+        List<CachedScope> cached = resolveResourceServerCache(resourceServerId).get(cacheKeyForScope);
 
         if (cached == null) {
             Scope scope = getDelegate().findById(id, resourceServerId);
 
             if (scope != null) {
-                return createAdapter(updateScopeCache(scope));
+                CachedScope cachedScope = new CachedScope(scope);
+                resolveResourceServerCache(resourceServerId).put(cacheKeyForScope, Arrays.asList(cachedScope));
+                return createAdapter(cachedScope);
             }
 
             return null;
@@ -108,21 +103,21 @@ public class CachedScopeStore implements ScopeStore {
 
     @Override
     public Scope findByName(String name, String resourceServerId) {
-        String cacheKeyForScope = getCacheKeyForScopeName(name, resourceServerId);
-        List<String> cached = this.cache.get(cacheKeyForScope);
+        String cacheKeyForScope = getCacheKeyForScopeName(name);
+        List<CachedScope> cached = resolveResourceServerCache(resourceServerId).get(cacheKeyForScope);
 
         if (cached == null) {
             Scope scope = getDelegate().findByName(name, resourceServerId);
 
             if (scope != null) {
-                cache.put(cacheKeyForScope, Arrays.asList(scope.getId()));
+                resolveResourceServerCache(resourceServerId).put(cacheKeyForScope, Arrays.asList(new CachedScope(scope)));
                 return findById(scope.getId(), resourceServerId);
             }
 
             return null;
         }
 
-        return findById(cached.get(0), resourceServerId);
+        return createAdapter(cached.get(0));
     }
 
     @Override
@@ -139,8 +134,8 @@ public class CachedScopeStore implements ScopeStore {
         return SCOPE_ID_CACHE_PREFIX + id;
     }
 
-    private String getCacheKeyForScopeName(String name, String resourceServerId) {
-        return SCOPE_NAME_CACHE_PREFIX + name + "-" + resourceServerId;
+    private String getCacheKeyForScopeName(String name) {
+        return SCOPE_NAME_CACHE_PREFIX + name;
     }
 
     private ScopeStore getDelegate() {
@@ -197,11 +192,11 @@ public class CachedScopeStore implements ScopeStore {
                     this.updated = getDelegate().findById(getId(), cached.getResourceServerId());
                     if (this.updated == null) throw new IllegalStateException("Not found in database");
                     transaction.whenCommit(() -> {
-                        cache.remove(getCacheKeyForScope(getId()));
-                        getCachedStoreFactory().getPolicyStore().notifyChange(updated);
+                        invalidateCache(cached.getResourceServerId());
                     });
                     transaction.whenRollback(() -> {
-                        cache.remove(getCacheKeyForScope(cached.getId()));
+                        resolveResourceServerCache(cached.getResourceServerId()).remove(getCacheKeyForScope(cached.getId()));
+                        resolveResourceServerCache(cached.getResourceServerId()).remove(getCacheKeyForScopeName(cached.getName()));
                     });
                 }
 
@@ -214,15 +209,11 @@ public class CachedScopeStore implements ScopeStore {
         return session.getProvider(CachedStoreFactoryProvider.class);
     }
 
-    private CachedScope updateScopeCache(Scope scope) {
-        CachedScope cached = new CachedScope(scope);
-
-        List cache = new ArrayList();
-
-        cache.add(cached);
-
-        this.transaction.whenCommit(() -> this.cache.put(getCacheKeyForScope(scope.getId()), cache));
+    private void invalidateCache(String resourceServerId) {
+        cache.remove(resourceServerId);
+    }
 
-        return cached;
+    private Map<String, List<CachedScope>> resolveResourceServerCache(String id) {
+        return cache.computeIfAbsent(id, key -> new HashMap<>());
     }
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreProviderFactory.java
index 5b11340..ff7452b 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreProviderFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreProviderFactory.java
@@ -56,6 +56,6 @@ public class InfinispanStoreProviderFactory implements CachedStoreProviderFactor
 
     @Override
     public boolean isSupported() {
-        return false;
+        return true;
     }
 }
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html
index 419622f..87a6f53 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html
@@ -58,9 +58,6 @@
                     <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
                     <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
                     <button data-ng-click="nextPage()" class="next" ng-disabled="policies.length < query.max">{{:: 'next-page' | translate}}</button>
-                    <select class="first" data-ng-model="query.max"
-                            ng-options="size for size in listSizes" data-ng-change="firstPage()">
-                    </select>
                 </div>
             </td>
         </tr>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html
index 9ad378a..2d66cf3 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html
@@ -60,9 +60,6 @@
                     <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
                     <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
                     <button data-ng-click="nextPage()" class="next" ng-disabled="policies.length < query.max">{{:: 'next-page' | translate}}</button>
-                    <select class="first" data-ng-model="query.max"
-                            ng-options="size for size in listSizes" data-ng-change="firstPage()">
-                    </select>
                 </div>
             </td>
         </tr>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-list.html
index 1f8e1bd..868ed85 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-list.html
@@ -67,9 +67,6 @@
                     <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
                     <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
                     <button data-ng-click="nextPage()" class="next" ng-disabled="resources.length < query.max">{{:: 'next-page' | translate}}</button>
-                    <select class="first" data-ng-model="query.max"
-                            ng-options="size for size in listSizes" data-ng-change="firstPage()">
-                    </select>
                 </div>
             </td>
         </tr>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-list.html
index ff8bb14..c129bcf 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-list.html
@@ -39,9 +39,6 @@
                     <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
                     <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
                     <button data-ng-click="nextPage()" class="next" ng-disabled="scopes.length < query.max">{{:: 'next-page' | translate}}</button>
-                    <select class="first" data-ng-model="query.max"
-                            ng-options="size for size in listSizes" data-ng-change="firstPage()">
-                    </select>
                 </div>
             </td>
         </tr>