keycloak-memoizeit

KEYCLOAK-2185 Add support to disable realm and user cache,

1/20/2016 11:08:37 AM

Changes

Details

diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
index 9b47f50..777345e 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -34,7 +34,9 @@ public class RealmRepresentation {
     protected Boolean resetPasswordAllowed;
     protected Boolean editUsernameAllowed;
 
+    @Deprecated
     protected Boolean userCacheEnabled;
+    @Deprecated
     protected Boolean realmCacheEnabled;
 
     //--- brute force settings
@@ -367,22 +369,6 @@ public class RealmRepresentation {
         this.rememberMe = rememberMe;
     }
 
-    public Boolean isRealmCacheEnabled() {
-        return realmCacheEnabled;
-    }
-
-    public void setRealmCacheEnabled(Boolean realmCacheEnabled) {
-        this.realmCacheEnabled = realmCacheEnabled;
-    }
-
-    public Boolean isUserCacheEnabled() {
-        return userCacheEnabled;
-    }
-
-    public void setUserCacheEnabled(Boolean userCacheEnabled) {
-        this.userCacheEnabled = userCacheEnabled;
-    }
-
     public Boolean isVerifyEmail() {
         return verifyEmail;
     }
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/content/standalone/configuration/keycloak-server.json b/distribution/feature-packs/server-feature-pack/src/main/resources/content/standalone/configuration/keycloak-server.json
index a5b4d1b..b96d61b 100644
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/content/standalone/configuration/keycloak-server.json
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/content/standalone/configuration/keycloak-server.json
@@ -22,6 +22,18 @@
         "provider": "jpa"
     },
 
+    "userCache": {
+        "infinispan" : {
+            "enabled": true
+        }
+    },
+
+    "realmCache": {
+        "infinispan" : {
+            "enabled": true
+        }
+    },
+
     "userSessionPersister": {
         "provider": "jpa"
     },
diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml b/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml
index ac64797..1d9cf1c 100755
--- a/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml
+++ b/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml
@@ -218,6 +218,21 @@ public class MyEventListenerProviderFactory implements EventListenerProviderFact
 }]]></programlisting>
             </para>
         </section>
+
+        <section>
+            <title>Disabling a provider</title>
+            <para>
+                You can disable a provider by setting the enabled field for the provider to false in <literal>keycloak-server.json</literal>.
+                For example to disable the Infinispan user cache provider add:
+<programlisting><![CDATA[{
+"userCache": {
+    "infinispan" : {
+        "enabled": false
+    }
+}
+}]]></programlisting>
+            </para>
+        </section>
     </section>
 
     <section>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index bd00840..3adb152 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -66,10 +66,10 @@ i18n-enabled=Internationalization Enabled
 supported-locales=Supported Locales
 supported-locales.placeholder=Type a locale and enter
 default-locale=Default Locale
-realm-cache-enabled=Realm Cache Enabled
-realm-cache-enabled.tooltip=Enable/disable cache for realms, clients and roles.
-user-cache-enabled=User Cache Enabled
-user-cache-enabled.tooltip=Enable/disable cache for users and user role mappings.
+realm-cache-clear=Realm Cache
+realm-cache-clear.tooltip=Clears all entries from the realm cache (this will clear entries for all realms)
+user-cache-clear=User Cache
+user-cache-clear.tooltip=Clears all entries from the user cache (this will clear entries for all realms)
 revoke-refresh-token=Revoke Refresh Token
 revoke-refresh-token.tooltip=If enabled refresh tokens can only be used once. Otherwise refresh tokens are not revoked when used and can be used multiple times.
 sso-session-idle=SSO Session Idle
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index 548c6e1..f58004d 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -349,8 +349,20 @@ module.controller('RealmThemeCtrl', function($scope, Current, Realm, realm, serv
     }, true);
 });
 
-module.controller('RealmCacheCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) {
-    genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/cache-settings");
+module.controller('RealmCacheCtrl', function($scope, realm, RealmClearUserCache, RealmClearRealmCache, Notifications) {
+
+    $scope.clearUserCache = function() {
+        RealmClearUserCache.save({ realm: realm.realm}, function () {
+            Notifications.success("User cache cleared");
+        });
+    }
+
+    $scope.clearRealmCache = function() {
+        RealmClearRealmCache.save({ realm: realm.realm}, function () {
+           Notifications.success("Realm cache cleared");
+        });
+    }
+
 });
 
 module.controller('RealmPasswordPolicyCtrl', function($scope, Realm, realm, $http, $location, Dialog, Notifications, PasswordPolicy) {
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
index 5e81744..7939403 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
@@ -595,6 +595,18 @@ module.factory('RealmPushRevocation', function($resource) {
     });
 });
 
+module.factory('RealmClearUserCache', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clear-user-cache', {
+        realm : '@realm'
+    });
+});
+
+module.factory('RealmClearRealmCache', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clear-realm-cache', {
+        realm : '@realm'
+    });
+});
+
 module.factory('RealmSessionStats', function($resource) {
     return $resource(authUrl + '/admin/realms/:realm/session-stats', {
         realm : '@realm'
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html
index db26796..29d978e 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html
@@ -3,25 +3,19 @@
 
     <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
         <div class="form-group">
-            <label class="col-md-2 control-label" for="realmCacheEnabled">{{:: 'realm-cache-enabled' | translate}}</label>
+            <label class="col-md-2 control-label">{{:: 'realm-cache-clear' | translate}}</label>
             <div class="col-md-6">
-                <input ng-model="realm.realmCacheEnabled" name="realmCacheEnabled" id="realmCacheEnabled" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
+                <button type="submit" data-ng-click="clearRealmCache()" class="btn btn-default">{{:: 'clear' | translate}}</button>
             </div>
-             <kc-tooltip>{{:: 'realm-cache-enabled.tooltip' | translate}}</kc-tooltip>
+
+            <kc-tooltip>{{:: 'realm-cache-clear.tooltip' | translate}}</kc-tooltip>
          </div>
         <div class="form-group">
-            <label class="col-md-2 control-label" for="userCacheEnabled">{{:: 'user-cache-enabled' | translate}}</label>
+            <label class="col-md-2 control-label">{{:: 'user-cache-clear' | translate}}</label>
             <div class="col-md-6">
-                <input ng-model="realm.userCacheEnabled" name="userCacheEnabled" id="userCacheEnabled" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
-            </div>
-            <kc-tooltip>{{:: 'user-cache-enabled.tooltip' | translate}}</kc-tooltip>
-        </div>
-
-        <div class="form-group" data-ng-show="access.manageRealm">
-            <div class="col-md-10 col-md-offset-2">
-                <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
-                <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
+                <button type="submit" data-ng-click="clearUserCache()" class="btn btn-default">{{:: 'clear' | translate}}</button>
             </div>
+            <kc-tooltip>{{:: 'user-cache-clear.tooltip' | translate}}</kc-tooltip>
         </div>
     </form>
 </div>
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java
index 478a087..a8a6317 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheRealmProvider.java
@@ -39,19 +39,13 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
     }
 
     @Override
-    public MigrationModel getMigrationModel() {
-        return getDelegate().getMigrationModel();
-    }
-
-
-    @Override
-    public boolean isEnabled() {
-        return cache.isEnabled();
+    public void clear() {
+        cache.clear();
     }
 
     @Override
-    public void setEnabled(boolean enabled) {
-        cache.setEnabled(enabled);
+    public MigrationModel getMigrationModel() {
+        return getDelegate().getMigrationModel();
     }
 
     @Override
@@ -149,7 +143,6 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
     @Override
     public RealmModel createRealm(String name) {
         RealmModel realm = getDelegate().createRealm(name);
-        if (!cache.isEnabled()) return realm;
         registerRealmInvalidation(realm.getId());
         return realm;
     }
@@ -157,14 +150,12 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
     @Override
     public RealmModel createRealm(String id, String name) {
         RealmModel realm =  getDelegate().createRealm(id, name);
-        if (!cache.isEnabled()) return realm;
         registerRealmInvalidation(realm.getId());
         return realm;
     }
 
     @Override
     public RealmModel getRealm(String id) {
-        if (!cache.isEnabled()) return getDelegate().getRealm(id);
         CachedRealm cached = cache.getCachedRealm(id);
         if (cached == null) {
             RealmModel model = getDelegate().getRealm(id);
@@ -184,7 +175,6 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
 
     @Override
     public RealmModel getRealmByName(String name) {
-        if (!cache.isEnabled()) return getDelegate().getRealmByName(name);
         CachedRealm cached = cache.getCachedRealmByName(name);
         if (cached == null) {
             RealmModel model = getDelegate().getRealmByName(name);
@@ -218,7 +208,6 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
 
     @Override
     public boolean removeRealm(String id) {
-        if (!cache.isEnabled()) return getDelegate().removeRealm(id);
         cache.invalidateCachedRealmById(id);
 
         RealmModel realm = getDelegate().getRealm(id);
@@ -247,7 +236,6 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
 
     @Override
     public RoleModel getRoleById(String id, RealmModel realm) {
-        if (!cache.isEnabled()) return getDelegate().getRoleById(id, realm);
         CachedRole cached = cache.getRole(id);
         if (cached != null && !cached.getRealm().equals(realm.getId())) {
             cached = null;
@@ -276,7 +264,6 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
 
     @Override
     public GroupModel getGroupById(String id, RealmModel realm) {
-        if (!cache.isEnabled()) return getDelegate().getGroupById(id, realm);
         CachedGroup cached = cache.getGroup(id);
         if (cached != null && !cached.getRealm().equals(realm.getId())) {
             cached = null;
@@ -301,7 +288,6 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
 
     @Override
     public ClientModel getClientById(String id, RealmModel realm) {
-        if (!cache.isEnabled()) return getDelegate().getClientById(id, realm);
         CachedClient cached = cache.getApplication(id);
         if (cached != null && !cached.getRealm().equals(realm.getId())) {
             cached = null;
@@ -324,7 +310,6 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
     }
     @Override
     public ClientTemplateModel getClientTemplateById(String id, RealmModel realm) {
-        if (!cache.isEnabled()) return getDelegate().getClientTemplateById(id, realm);
         CachedClientTemplate cached = cache.getClientTemplate(id);
         if (cached != null && !cached.getRealm().equals(realm.getId())) {
             cached = null;
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheUserProvider.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheUserProvider.java
index 12e5b5d..ee5f049 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheUserProvider.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/DefaultCacheUserProvider.java
@@ -22,8 +22,6 @@ public class DefaultCacheUserProvider implements CacheUserProvider {
     protected Set<String> realmInvalidations = new HashSet<>();
     protected Map<String, UserModel> managedUsers = new HashMap<>();
 
-    protected boolean clearAll;
-
     public DefaultCacheUserProvider(UserCache cache, KeycloakSession session) {
         this.cache = cache;
         this.session = session;
@@ -32,13 +30,8 @@ public class DefaultCacheUserProvider implements CacheUserProvider {
     }
 
     @Override
-    public boolean isEnabled() {
-        return cache.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        cache.setEnabled(enabled);
+    public void clear() {
+        cache.clear();
     }
 
     @Override
@@ -73,9 +66,6 @@ public class DefaultCacheUserProvider implements CacheUserProvider {
             @Override
             public void commit() {
                 if (delegate == null) return;
-                if (clearAll) {
-                    cache.clear();
-                }
                 runInvalidations();
                 transactionActive = false;
             }
@@ -110,7 +100,6 @@ public class DefaultCacheUserProvider implements CacheUserProvider {
 
     @Override
     public UserModel getUserById(String id, RealmModel realm) {
-        if (!cache.isEnabled()) return getDelegate().getUserById(id, realm);
         if (isRegisteredForInvalidation(realm, id)) {
             return getDelegate().getUserById(id, realm);
         }
@@ -136,7 +125,6 @@ public class DefaultCacheUserProvider implements CacheUserProvider {
         
         username = username.toLowerCase();
         
-        if (!cache.isEnabled()) return getDelegate().getUserByUsername(username, realm);
         if (realmInvalidations.contains(realm.getId())) {
             return getDelegate().getUserByUsername(username, realm);
         }
@@ -164,7 +152,6 @@ public class DefaultCacheUserProvider implements CacheUserProvider {
         
         email = email.toLowerCase();
         
-        if (!cache.isEnabled()) return getDelegate().getUserByEmail(email, realm);
         if (realmInvalidations.contains(realm.getId())) {
             return getDelegate().getUserByEmail(email, realm);
         }
@@ -276,7 +263,6 @@ public class DefaultCacheUserProvider implements CacheUserProvider {
 
     @Override
     public boolean removeUser(RealmModel realm, UserModel user) {
-        if (!cache.isEnabled()) return getDelegate().removeUser(realm, user);
         registerUserInvalidation(realm, user.getId());
         return getDelegate().removeUser(realm, user);
     }
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java
index 07e2d9a..ffacc55 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java
@@ -20,34 +20,23 @@ public class InfinispanRealmCache implements RealmCache {
 
     protected final Cache<String, Object> cache;
     protected final ConcurrentHashMap<String, String> realmLookup;
-    protected volatile boolean enabled = true;
 
     public InfinispanRealmCache(Cache<String, Object> cache, ConcurrentHashMap<String, String> realmLookup) {
         this.cache = cache;
         this.realmLookup = realmLookup;
     }
 
-    @Override
-    public void clear() {
-        cache.clear();
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return enabled;
+    public Cache<String, Object> getCache() {
+        return cache;
     }
 
     @Override
-    public void setEnabled(boolean enabled) {
-        if (this.enabled && !enabled) {
-            clear();
-        }
-        this.enabled = enabled;
+    public void clear() {
+        cache.clear();
     }
 
     @Override
     public CachedRealm getCachedRealm(String id) {
-        if (!enabled) return null;
         return get(id, CachedRealm.class);
     }
 
@@ -66,7 +55,6 @@ public class InfinispanRealmCache implements RealmCache {
 
     @Override
     public void addCachedRealm(CachedRealm realm) {
-        if (!enabled) return;
         logger.tracev("Adding realm {0}", realm.getId());
         cache.putForExternalRead(realm.getId(), realm);
         realmLookup.put(realm.getName(), realm.getId());
@@ -74,14 +62,12 @@ public class InfinispanRealmCache implements RealmCache {
 
     @Override
     public CachedRealm getCachedRealmByName(String name) {
-        if (!enabled) return null;
         String id = realmLookup.get(name);
         return id != null ? getCachedRealm(id) : null;
     }
 
     @Override
     public CachedClient getApplication(String id) {
-        if (!enabled) return null;
         return get(id, CachedClient.class);
     }
 
@@ -93,7 +79,6 @@ public class InfinispanRealmCache implements RealmCache {
 
     @Override
     public void addCachedClient(CachedClient app) {
-        if (!enabled) return;
         logger.tracev("Adding application {0}", app.getId());
         cache.putForExternalRead(app.getId(), app);
     }
@@ -112,7 +97,6 @@ public class InfinispanRealmCache implements RealmCache {
 
     @Override
     public CachedGroup getGroup(String id) {
-        if (!enabled) return null;
         return get(id, CachedGroup.class);
     }
 
@@ -124,7 +108,6 @@ public class InfinispanRealmCache implements RealmCache {
 
     @Override
     public void addCachedGroup(CachedGroup role) {
-        if (!enabled) return;
         logger.tracev("Adding group {0}", role.getId());
         cache.putForExternalRead(role.getId(), role);
     }
@@ -144,7 +127,6 @@ public class InfinispanRealmCache implements RealmCache {
 
     @Override
     public CachedRole getRole(String id) {
-        if (!enabled) return null;
         return get(id, CachedRole.class);
     }
 
@@ -168,7 +150,6 @@ public class InfinispanRealmCache implements RealmCache {
 
     @Override
     public void addCachedRole(CachedRole role) {
-        if (!enabled) return;
         logger.tracev("Adding role {0}", role.getId());
         cache.putForExternalRead(role.getId(), role);
     }
@@ -186,7 +167,6 @@ public class InfinispanRealmCache implements RealmCache {
 
     @Override
     public CachedClientTemplate getClientTemplate(String id) {
-        if (!enabled) return null;
         return get(id, CachedClientTemplate.class);
     }
 
@@ -198,7 +178,6 @@ public class InfinispanRealmCache implements RealmCache {
 
     @Override
     public void addCachedClientTemplate(CachedClientTemplate app) {
-        if (!enabled) return;
         logger.tracev("Adding client template {0}", app.getId());
         cache.putForExternalRead(app.getId(), app);
     }
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java
index c08566b..0d4639c 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanUserCache.java
@@ -29,19 +29,6 @@ public class InfinispanUserCache implements UserCache {
     }
 
     @Override
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        if (this.enabled && !enabled) {
-            clear();
-        }
-        this.enabled = enabled;
-    }
-
-    @Override
     public CachedUser getCachedUser(String realmId, String id) {
         if (realmId == null || id == null) return null;
         CachedUser user = cache.get(id);
@@ -49,12 +36,6 @@ public class InfinispanUserCache implements UserCache {
     }
 
     @Override
-    public void invalidateCachedUser(String realmId, CachedUser user) {
-        logger.tracev("Invalidating user {0}", user.getId());
-        cache.remove(user.getId());
-    }
-
-    @Override
     public void invalidateCachedUserById(String realmId, String id) {
         logger.tracev("Invalidating user {0}", id);
         cache.remove(id);
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java
index 6386f9f..e0582f5 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java
@@ -7,11 +7,9 @@ import org.keycloak.models.RealmProvider;
  * @version $Revision: 1 $
  */
 public interface CacheRealmProvider extends RealmProvider {
+    void clear();
     RealmProvider getDelegate();
 
-    boolean isEnabled();
-    void setEnabled(boolean enabled);
-
     void registerRealmInvalidation(String id);
 
     void registerApplicationInvalidation(String id);
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java
index ec0d021..ac1f5da 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java
@@ -8,8 +8,7 @@ import org.keycloak.models.UserProvider;
  * @version $Revision: 1 $
  */
 public interface CacheUserProvider extends UserProvider {
+    void clear();
     UserProvider getDelegate();
-    boolean isEnabled();
-    void setEnabled(boolean enabled);
     void registerUserInvalidation(RealmModel realm, String id);
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java
index 56f9bc0..002a771 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java
@@ -55,10 +55,6 @@ public interface RealmCache {
 
     void invalidateGroupById(String id);
 
-    boolean isEnabled();
-
-    void setEnabled(boolean enabled);
-
     CachedClientTemplate getClientTemplate(String id);
 
     void invalidateClientTemplate(CachedClientTemplate app);
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java
index 9b0336f..6af0a29 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java
@@ -7,12 +7,11 @@ import org.keycloak.models.cache.entities.CachedUser;
  * @version $Revision: 1 $
  */
 public interface UserCache {
+
     void clear();
 
     CachedUser getCachedUser(String realmId, String id);
 
-    void invalidateCachedUser(String realmId, CachedUser user);
-
     void addCachedUser(String realmId, CachedUser user);
 
     CachedUser getCachedUserByUsername(String realmId, String name);
@@ -23,7 +22,4 @@ public interface UserCache {
 
     void invalidateRealmUsers(String realmId);
 
-    boolean isEnabled();
-
-    void setEnabled(boolean enabled);
 }
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
index 26f52a2..c8eb3ba 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
@@ -1,25 +1,12 @@
 package org.keycloak.services;
 
-import org.jboss.logging.Logger;
-import org.keycloak.models.KeycloakContext;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.KeycloakTransactionManager;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.UserFederationManager;
-import org.keycloak.models.UserProvider;
-import org.keycloak.models.UserSessionProvider;
+import org.keycloak.models.*;
 import org.keycloak.models.cache.CacheRealmProvider;
 import org.keycloak.models.cache.CacheUserProvider;
 import org.keycloak.provider.Provider;
 import org.keycloak.provider.ProviderFactory;
 
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -35,8 +22,6 @@ public class DefaultKeycloakSession implements KeycloakSession {
     private UserSessionProvider sessionProvider;
     private UserFederationManager federationManager;
     private KeycloakContext context;
-    
-    private static final Logger logger = Logger.getLogger(DefaultKeycloakSession.class);
 
     public DefaultKeycloakSession(DefaultKeycloakSessionFactory factory) {
         this.factory = factory;
@@ -51,16 +36,18 @@ public class DefaultKeycloakSession implements KeycloakSession {
     }
 
     private RealmProvider getRealmProvider() {
-        if (factory.getDefaultProvider(CacheRealmProvider.class) != null) {
-            return getProvider(CacheRealmProvider.class);
+        CacheRealmProvider cache = getProvider(CacheRealmProvider.class);
+        if (cache != null) {
+            return cache;
         } else {
             return getProvider(RealmProvider.class);
         }
     }
 
     private UserProvider getUserProvider() {
-        if (factory.getDefaultProvider(CacheUserProvider.class) != null) {
-            return getProvider(CacheUserProvider.class);
+        CacheUserProvider cache = getProvider(CacheUserProvider.class);
+        if (cache != null) {
+            return cache;
         } else {
             return getProvider(UserProvider.class);
         }
@@ -87,7 +74,6 @@ public class DefaultKeycloakSession implements KeycloakSession {
             userModel = getUserProvider();
         }
         return userModel;
-
     }
 
     public <T extends Provider> T getProvider(Class<T> clazz) {
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
index 08699e0..7a7974a 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
@@ -79,20 +79,24 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory {
             } else {
                 for (ProviderFactory factory : pm.load(spi)) {
                     Config.Scope scope = Config.scope(spi.getName(), factory.getId());
-                    factory.init(scope);
+                    if (scope.getBoolean("enabled", true)) {
+                        factory.init(scope);
 
-                    if (spi.isInternal() && !isInternal(factory)) {
-                        log.warnv("{0} ({1}) is implementing the internal SPI {2}. This SPI is internal and may change without notice", factory.getId(), factory.getClass().getName(), spi.getName());
-                    }
+                        if (spi.isInternal() && !isInternal(factory)) {
+                            log.warnv("{0} ({1}) is implementing the internal SPI {2}. This SPI is internal and may change without notice", factory.getId(), factory.getClass().getName(), spi.getName());
+                        }
 
-                    factories.put(factory.getId(), factory);
+                        factories.put(factory.getId(), factory);
+                    } else {
+                        log.debugv("SPI {0} provider {1} disabled", spi.getName(), factory.getId());
+                    }
                 }
 
                 if (factories.size() == 1) {
                     provider = factories.values().iterator().next().getId();
                     this.provider.put(spi.getProviderClass(), provider);
 
-                    log.debugv("Loaded SPI {0}  (provider = {1})", spi.getName(), provider);
+                    log.debugv("Loaded SPI {0} (provider = {1})", spi.getName(), provider);
                 } else {
                     log.debugv("Loaded SPI {0} (providers = {1})", spi.getName(), factories.keySet());
                 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index a5c050d..e282ef0 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -191,16 +191,7 @@ public class RealmAdminResource {
     @Produces(MediaType.APPLICATION_JSON)
     public RealmRepresentation getRealm() {
         if (auth.hasView()) {
-            RealmRepresentation rep = ModelToRepresentation.toRepresentation(realm, false);
-            if (session.realms() instanceof CacheRealmProvider) {
-                CacheRealmProvider cacheRealmProvider = (CacheRealmProvider)session.realms();
-                rep.setRealmCacheEnabled(cacheRealmProvider.isEnabled());
-            }
-            if (session.userStorage() instanceof CacheUserProvider) {
-                CacheUserProvider cache = (CacheUserProvider)session.userStorage();
-                rep.setUserCacheEnabled(cache.isEnabled());
-            }
-            return rep;
+            return ModelToRepresentation.toRepresentation(realm, false);
         } else {
             auth.requireAny();
 
@@ -227,14 +218,6 @@ public class RealmAdminResource {
         logger.debug("updating realm: " + realm.getName());
         try {
             RepresentationToModel.updateRealm(rep, realm);
-            if (rep.isRealmCacheEnabled() != null && session.realms() instanceof CacheRealmProvider) {
-                CacheRealmProvider cacheRealmProvider = (CacheRealmProvider)session.realms();
-                cacheRealmProvider.setEnabled(rep.isRealmCacheEnabled());
-            }
-            if (rep.isUserCacheEnabled() != null && session.userStorage() instanceof CacheUserProvider) {
-                CacheUserProvider cache = (CacheUserProvider)session.userStorage();
-                cache.setEnabled(rep.isUserCacheEnabled());
-            }
 
             // Refresh periodic sync tasks for configured federationProviders
             List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
@@ -724,4 +707,35 @@ public class RealmAdminResource {
         PartialImportManager partialImport = new PartialImportManager(rep, session, realm, adminEvent);
         return partialImport.saveResources();
     }
+
+    /**
+     * Clear realm cache
+     *
+     */
+    @Path("clear-realm-cache")
+    @POST
+    public void clearRealmCache() {
+        auth.requireManage();
+        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+        CacheRealmProvider cache = session.getProvider(CacheRealmProvider.class);
+        if (cache != null) {
+            cache.clear();
+        }
+    }
+
+    /**
+     * Clear user cache
+     *
+     */
+    @Path("clear-user-cache")
+    @POST
+    public void clearUserCache() {
+        auth.requireManage();
+        adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
+        CacheUserProvider cache = session.getProvider(CacheUserProvider.class);
+        if (cache != null) {
+            cache.clear();
+        }
+    }
+
 }
diff --git a/testsuite/integration/src/test/resources/META-INF/keycloak-server.json b/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
index 8ea3789..401fc6b 100755
--- a/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
+++ b/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
@@ -26,6 +26,18 @@
         "provider": "${keycloak.userSessionPersister.provider:jpa}"
     },
 
+    "userCache": {
+        "infinispan" : {
+            "enabled": true
+        }
+    },
+
+    "realmCache": {
+        "infinispan" : {
+            "enabled": true
+        }
+    },
+
     "timer": {
         "provider": "basic"
     },