keycloak-aplcache

Details

diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java
index 2094fa2..85fd17a 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java
@@ -28,14 +28,14 @@ import java.util.*;
  * @version $Revision: 1 $
  */
 public class ClientAdapter implements ClientModel {
-    protected CacheRealmProvider cacheSession;
+    protected RealmCacheSession cacheSession;
     protected RealmModel cachedRealm;
     protected RealmCache cache;
 
     protected ClientModel updated;
     protected CachedClient cached;
 
-    public ClientAdapter(RealmModel cachedRealm, CachedClient cached, CacheRealmProvider cacheSession, RealmCache cache) {
+    public ClientAdapter(RealmModel cachedRealm, CachedClient cached, RealmCacheSession cacheSession, RealmCache cache) {
         this.cachedRealm = cachedRealm;
         this.cache = cache;
         this.cacheSession = cacheSession;
@@ -44,11 +44,23 @@ public class ClientAdapter implements ClientModel {
 
     private void getDelegateForUpdate() {
         if (updated == null) {
-            cacheSession.registerClientInvalidation(getId());
-            updated = cacheSession.getDelegate().getClientById(getId(), cachedRealm);
+            cacheSession.registerClientInvalidation(cached.getId());
+            updated = cacheSession.getDelegate().getClientById(cached.getId(), cachedRealm);
             if (updated == null) throw new IllegalStateException("Not found in database");
         }
     }
+    protected boolean invalidated;
+    public void invalidate() {
+        invalidated = true;
+    }
+
+    protected boolean isUpdated() {
+        if (updated != null) return true;
+        if (!invalidated) return false;
+        updated = cacheSession.getDelegate().getClientById(cached.getId(), cachedRealm);
+        if (updated == null) throw new IllegalStateException("Not found in database");
+        return true;
+    }
 
     @Override
     public void updateClient() {
@@ -57,12 +69,12 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public String getId() {
-        if (updated != null) return updated.getId();
+        if (isUpdated()) return updated.getId();
         return cached.getId();
     }
 
     public Set<String> getWebOrigins() {
-        if (updated != null) return updated.getWebOrigins();
+        if (isUpdated()) return updated.getWebOrigins();
         return cached.getWebOrigins();
     }
 
@@ -73,7 +85,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public ClientTemplateModel getClientTemplate() {
-        if (updated != null) return updated.getClientTemplate();
+        if (isUpdated()) return updated.getClientTemplate();
         if (cached.getClientTemplate() == null) return null;
         return cacheSession.getClientTemplateById(cached.getClientTemplate(), cachedRealm);
     }
@@ -87,7 +99,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean useTemplateScope() {
-        if (updated != null) return updated.useTemplateScope();
+        if (isUpdated()) return updated.useTemplateScope();
         return cached.isUseTemplateScope();
     }
 
@@ -100,7 +112,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean useTemplateConfig() {
-        if (updated != null) return updated.useTemplateConfig();
+        if (isUpdated()) return updated.useTemplateConfig();
         return cached.isUseTemplateConfig();
     }
 
@@ -113,7 +125,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean useTemplateMappers() {
-        if (updated != null) return updated.useTemplateMappers();
+        if (isUpdated()) return updated.useTemplateMappers();
         return cached.isUseTemplateMappers();
     }
 
@@ -137,7 +149,7 @@ public class ClientAdapter implements ClientModel {
     }
 
     public Set<String> getRedirectUris() {
-        if (updated != null) return updated.getRedirectUris();
+        if (isUpdated()) return updated.getRedirectUris();
         return cached.getRedirectUris();
     }
 
@@ -157,7 +169,7 @@ public class ClientAdapter implements ClientModel {
     }
 
     public boolean isEnabled() {
-        if (updated != null) return updated.isEnabled();
+        if (isUpdated()) return updated.isEnabled();
         return cached.isEnabled();
     }
 
@@ -168,7 +180,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public String getClientAuthenticatorType() {
-        if (updated != null) return updated.getClientAuthenticatorType();
+        if (isUpdated()) return updated.getClientAuthenticatorType();
         return cached.getClientAuthenticatorType();
     }
 
@@ -183,7 +195,7 @@ public class ClientAdapter implements ClientModel {
     }
 
     public String getSecret() {
-        if (updated != null) return updated.getSecret();
+        if (isUpdated()) return updated.getSecret();
         return cached.getSecret();
     }
 
@@ -192,7 +204,7 @@ public class ClientAdapter implements ClientModel {
         updated.setSecret(secret);
     }
     public String getRegistrationToken() {
-        if (updated != null) return updated.getRegistrationToken();
+        if (isUpdated()) return updated.getRegistrationToken();
         return cached.getRegistrationToken();
     }
 
@@ -202,7 +214,7 @@ public class ClientAdapter implements ClientModel {
     }
 
     public boolean isPublicClient() {
-        if (updated != null) return updated.isPublicClient();
+        if (isUpdated()) return updated.isPublicClient();
         return cached.isPublicClient();
     }
 
@@ -212,7 +224,7 @@ public class ClientAdapter implements ClientModel {
     }
 
     public boolean isFrontchannelLogout() {
-        if (updated != null) return updated.isPublicClient();
+        if (isUpdated()) return updated.isPublicClient();
         return cached.isFrontchannelLogout();
     }
 
@@ -223,7 +235,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean isFullScopeAllowed() {
-        if (updated != null) return updated.isFullScopeAllowed();
+        if (isUpdated()) return updated.isFullScopeAllowed();
         return cached.isFullScopeAllowed();
     }
 
@@ -235,7 +247,7 @@ public class ClientAdapter implements ClientModel {
     }
 
     public Set<RoleModel> getScopeMappings() {
-        if (updated != null) return updated.getScopeMappings();
+        if (isUpdated()) return updated.getScopeMappings();
         Set<RoleModel> roles = new HashSet<RoleModel>();
         for (String id : cached.getScope()) {
             roles.add(cacheSession.getRoleById(id, getRealm()));
@@ -275,7 +287,7 @@ public class ClientAdapter implements ClientModel {
     }
 
     public int getNotBefore() {
-        if (updated != null) return updated.getNotBefore();
+        if (isUpdated()) return updated.getNotBefore();
         return cached.getNotBefore();
     }
 
@@ -286,7 +298,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public String getProtocol() {
-        if (updated != null) return updated.getProtocol();
+        if (isUpdated()) return updated.getProtocol();
         return cached.getProtocol();
     }
 
@@ -312,13 +324,13 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public String getAttribute(String name) {
-        if (updated != null) return updated.getAttribute(name);
+        if (isUpdated()) return updated.getAttribute(name);
         return cached.getAttributes().get(name);
     }
 
     @Override
     public Map<String, String> getAttributes() {
-        if (updated != null) return updated.getAttributes();
+        if (isUpdated()) return updated.getAttributes();
         Map<String, String> copy = new HashMap<String, String>();
         copy.putAll(cached.getAttributes());
         return copy;
@@ -326,7 +338,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public Set<ProtocolMapperModel> getProtocolMappers() {
-        if (updated != null) return updated.getProtocolMappers();
+        if (isUpdated()) return updated.getProtocolMappers();
         return cached.getProtocolMappers();
     }
 
@@ -368,7 +380,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public String getClientId() {
-        if (updated != null) return updated.getClientId();
+        if (isUpdated()) return updated.getClientId();
         return cached.getClientId();
     }
 
@@ -380,7 +392,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public String getName() {
-        if (updated != null) return updated.getName();
+        if (isUpdated()) return updated.getName();
         return cached.getName();
     }
 
@@ -392,7 +404,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public String getDescription() {
-        if (updated != null) return updated.getDescription();
+        if (isUpdated()) return updated.getDescription();
         return cached.getDescription();
     }
 
@@ -404,7 +416,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean isSurrogateAuthRequired() {
-        if (updated != null) return updated.isSurrogateAuthRequired();
+        if (isUpdated()) return updated.isSurrogateAuthRequired();
         return cached.isSurrogateAuthRequired();
     }
 
@@ -416,7 +428,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public String getManagementUrl() {
-        if (updated != null) return updated.getManagementUrl();
+        if (isUpdated()) return updated.getManagementUrl();
         return cached.getManagementUrl();
     }
 
@@ -428,7 +440,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public String getRootUrl() {
-        if (updated != null) return updated.getRootUrl();
+        if (isUpdated()) return updated.getRootUrl();
         return cached.getRootUrl();
     }
 
@@ -440,7 +452,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public String getBaseUrl() {
-        if (updated != null) return updated.getBaseUrl();
+        if (isUpdated()) return updated.getBaseUrl();
         return cached.getBaseUrl();
     }
 
@@ -452,7 +464,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public List<String> getDefaultRoles() {
-        if (updated != null) return updated.getDefaultRoles();
+        if (isUpdated()) return updated.getDefaultRoles();
         return cached.getDefaultRoles();
     }
 
@@ -477,7 +489,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean isBearerOnly() {
-        if (updated != null) return updated.isBearerOnly();
+        if (isUpdated()) return updated.isBearerOnly();
         return cached.isBearerOnly();
     }
 
@@ -489,7 +501,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean isConsentRequired() {
-        if (updated != null) return updated.isConsentRequired();
+        if (isUpdated()) return updated.isConsentRequired();
         return cached.isConsentRequired();
     }
 
@@ -501,7 +513,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean isStandardFlowEnabled() {
-        if (updated != null) return updated.isStandardFlowEnabled();
+        if (isUpdated()) return updated.isStandardFlowEnabled();
         return cached.isStandardFlowEnabled();
     }
 
@@ -513,7 +525,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean isImplicitFlowEnabled() {
-        if (updated != null) return updated.isImplicitFlowEnabled();
+        if (isUpdated()) return updated.isImplicitFlowEnabled();
         return cached.isImplicitFlowEnabled();
     }
 
@@ -525,7 +537,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean isDirectAccessGrantsEnabled() {
-        if (updated != null) return updated.isDirectAccessGrantsEnabled();
+        if (isUpdated()) return updated.isDirectAccessGrantsEnabled();
         return cached.isDirectAccessGrantsEnabled();
     }
 
@@ -537,7 +549,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean isServiceAccountsEnabled() {
-        if (updated != null) return updated.isServiceAccountsEnabled();
+        if (isUpdated()) return updated.isServiceAccountsEnabled();
         return cached.isServiceAccountsEnabled();
     }
 
@@ -573,9 +585,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean removeRole(RoleModel role) {
-        cacheSession.registerRoleInvalidation(role.getId());
-        getDelegateForUpdate();
-        return updated.removeRole(role);
+        return cacheSession.removeRole(cachedRealm, role);
     }
 
     @Override
@@ -585,7 +595,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public int getNodeReRegistrationTimeout() {
-        if (updated != null) return updated.getNodeReRegistrationTimeout();
+        if (isUpdated()) return updated.getNodeReRegistrationTimeout();
         return cached.getNodeReRegistrationTimeout();
     }
 
@@ -597,7 +607,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public Map<String, Integer> getRegisteredNodes() {
-        if (updated != null) return updated.getRegisteredNodes();
+        if (isUpdated()) return updated.getRegisteredNodes();
         return cached.getRegisteredNodes();
     }
 
@@ -615,7 +625,7 @@ public class ClientAdapter implements ClientModel {
 
     @Override
     public boolean hasScope(RoleModel role) {
-        if (updated != null) return updated.hasScope(role);
+        if (isUpdated()) return updated.hasScope(role);
         if (cached.isFullScopeAllowed() || cached.getScope().contains(role.getId())) return true;
 
         Set<RoleModel> roles = getScopeMappings();
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientTemplateAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientTemplateAdapter.java
index b54738a..92d178e 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientTemplateAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientTemplateAdapter.java
@@ -36,13 +36,13 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public class ClientTemplateAdapter implements ClientTemplateModel {
-    protected CacheRealmProvider cacheSession;
+    protected RealmCacheSession cacheSession;
     protected RealmModel cachedRealm;
 
     protected ClientTemplateModel updated;
     protected CachedClientTemplate cached;
 
-    public ClientTemplateAdapter(RealmModel cachedRealm, CachedClientTemplate cached, CacheRealmProvider cacheSession) {
+    public ClientTemplateAdapter(RealmModel cachedRealm, CachedClientTemplate cached, RealmCacheSession cacheSession) {
         this.cachedRealm = cachedRealm;
         this.cacheSession = cacheSession;
         this.cached = cached;
@@ -50,15 +50,29 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     private void getDelegateForUpdate() {
         if (updated == null) {
-            cacheSession.registerClientTemplateInvalidation(getId());
-            updated = cacheSession.getDelegate().getClientTemplateById(getId(), cachedRealm);
+            cacheSession.registerClientTemplateInvalidation(cached.getId());
+            updated = cacheSession.getDelegate().getClientTemplateById(cached.getId(), cachedRealm);
             if (updated == null) throw new IllegalStateException("Not found in database");
         }
     }
 
+    protected boolean invalidated;
+    public void invalidate() {
+        invalidated = true;
+    }
+
+    protected boolean isUpdated() {
+        if (updated != null) return true;
+        if (!invalidated) return false;
+        updated = cacheSession.getDelegate().getClientTemplateById(cached.getId(), cachedRealm);
+        if (updated == null) throw new IllegalStateException("Not found in database");
+        return true;
+    }
+
+
     @Override
     public String getId() {
-        if (updated != null) return updated.getId();
+        if (isUpdated()) return updated.getId();
         return cached.getId();
     }
 
@@ -68,7 +82,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public Set<ProtocolMapperModel> getProtocolMappers() {
-        if (updated != null) return updated.getProtocolMappers();
+        if (isUpdated()) return updated.getProtocolMappers();
         return cached.getProtocolMappers();
     }
 
@@ -110,7 +124,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public String getName() {
-        if (updated != null) return updated.getName();
+        if (isUpdated()) return updated.getName();
         return cached.getName();
     }
 
@@ -122,7 +136,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public String getDescription() {
-        if (updated != null) return updated.getDescription();
+        if (isUpdated()) return updated.getDescription();
         return cached.getDescription();
     }
 
@@ -134,7 +148,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public String getProtocol() {
-        if (updated != null) return updated.getProtocol();
+        if (isUpdated()) return updated.getProtocol();
         return cached.getProtocol();
     }
 
@@ -146,7 +160,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public boolean isFullScopeAllowed() {
-        if (updated != null) return updated.isFullScopeAllowed();
+        if (isUpdated()) return updated.isFullScopeAllowed();
         return cached.isFullScopeAllowed();
     }
 
@@ -158,7 +172,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
     }
 
     public Set<RoleModel> getScopeMappings() {
-        if (updated != null) return updated.getScopeMappings();
+        if (isUpdated()) return updated.getScopeMappings();
         Set<RoleModel> roles = new HashSet<RoleModel>();
         for (String id : cached.getScope()) {
             roles.add(cacheSession.getRoleById(id, getRealm()));
@@ -195,7 +209,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public boolean hasScope(RoleModel role) {
-        if (updated != null) return updated.hasScope(role);
+        if (isUpdated()) return updated.hasScope(role);
         if (cached.isFullScopeAllowed() || cached.getScope().contains(role.getId())) return true;
 
         Set<RoleModel> roles = getScopeMappings();
@@ -207,7 +221,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
     }
 
     public boolean isPublicClient() {
-        if (updated != null) return updated.isPublicClient();
+        if (isUpdated()) return updated.isPublicClient();
         return cached.isPublicClient();
     }
 
@@ -217,7 +231,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
     }
 
     public boolean isFrontchannelLogout() {
-        if (updated != null) return updated.isPublicClient();
+        if (isUpdated()) return updated.isPublicClient();
         return cached.isFrontchannelLogout();
     }
 
@@ -242,13 +256,13 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public String getAttribute(String name) {
-        if (updated != null) return updated.getAttribute(name);
+        if (isUpdated()) return updated.getAttribute(name);
         return cached.getAttributes().get(name);
     }
 
     @Override
     public Map<String, String> getAttributes() {
-        if (updated != null) return updated.getAttributes();
+        if (isUpdated()) return updated.getAttributes();
         Map<String, String> copy = new HashMap<String, String>();
         copy.putAll(cached.getAttributes());
         return copy;
@@ -256,7 +270,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public boolean isBearerOnly() {
-        if (updated != null) return updated.isBearerOnly();
+        if (isUpdated()) return updated.isBearerOnly();
         return cached.isBearerOnly();
     }
 
@@ -268,7 +282,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public boolean isConsentRequired() {
-        if (updated != null) return updated.isConsentRequired();
+        if (isUpdated()) return updated.isConsentRequired();
         return cached.isConsentRequired();
     }
 
@@ -280,7 +294,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public boolean isStandardFlowEnabled() {
-        if (updated != null) return updated.isStandardFlowEnabled();
+        if (isUpdated()) return updated.isStandardFlowEnabled();
         return cached.isStandardFlowEnabled();
     }
 
@@ -292,7 +306,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public boolean isImplicitFlowEnabled() {
-        if (updated != null) return updated.isImplicitFlowEnabled();
+        if (isUpdated()) return updated.isImplicitFlowEnabled();
         return cached.isImplicitFlowEnabled();
     }
 
@@ -304,7 +318,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public boolean isDirectAccessGrantsEnabled() {
-        if (updated != null) return updated.isDirectAccessGrantsEnabled();
+        if (isUpdated()) return updated.isDirectAccessGrantsEnabled();
         return cached.isDirectAccessGrantsEnabled();
     }
 
@@ -316,7 +330,7 @@ public class ClientTemplateAdapter implements ClientTemplateModel {
 
     @Override
     public boolean isServiceAccountsEnabled() {
-        if (updated != null) return updated.isServiceAccountsEnabled();
+        if (isUpdated()) return updated.isServiceAccountsEnabled();
         return cached.isServiceAccountsEnabled();
     }
 
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/GroupAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/GroupAdapter.java
index 1810a34..9b44eb3 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/GroupAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/GroupAdapter.java
@@ -38,11 +38,11 @@ import java.util.Set;
 public class GroupAdapter implements GroupModel {
     protected GroupModel updated;
     protected CachedGroup cached;
-    protected CacheRealmProvider cacheSession;
+    protected RealmCacheSession cacheSession;
     protected KeycloakSession keycloakSession;
     protected RealmModel realm;
 
-    public GroupAdapter(CachedGroup cached, CacheRealmProvider cacheSession, KeycloakSession keycloakSession, RealmModel realm) {
+    public GroupAdapter(CachedGroup cached, RealmCacheSession cacheSession, KeycloakSession keycloakSession, RealmModel realm) {
         this.cached = cached;
         this.cacheSession = cacheSession;
         this.keycloakSession = keycloakSession;
@@ -51,12 +51,26 @@ public class GroupAdapter implements GroupModel {
 
     protected void getDelegateForUpdate() {
         if (updated == null) {
-            cacheSession.registerGroupInvalidation(getId());
-            updated = cacheSession.getDelegate().getGroupById(getId(), realm);
+            cacheSession.registerGroupInvalidation(cached.getId());
+            updated = cacheSession.getDelegate().getGroupById(cached.getId(), realm);
             if (updated == null) throw new IllegalStateException("Not found in database");
         }
     }
 
+    protected boolean invalidated;
+    public void invalidate() {
+        invalidated = true;
+    }
+
+    protected boolean isUpdated() {
+        if (updated != null) return true;
+        if (!invalidated) return false;
+        updated = cacheSession.getDelegate().getGroupById(cached.getId(), realm);
+        if (updated == null) throw new IllegalStateException("Not found in database");
+        return true;
+    }
+
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -76,13 +90,13 @@ public class GroupAdapter implements GroupModel {
 
     @Override
     public String getId() {
-        if (updated != null) return updated.getId();
+        if (isUpdated()) return updated.getId();
         return cached.getId();
     }
 
     @Override
     public String getName() {
-        if (updated != null) return updated.getName();
+        if (isUpdated()) return updated.getName();
         return cached.getName();
     }
 
@@ -114,7 +128,7 @@ public class GroupAdapter implements GroupModel {
 
     @Override
     public String getFirstAttribute(String name) {
-        if (updated != null) return updated.getFirstAttribute(name);
+        if (isUpdated()) return updated.getFirstAttribute(name);
         return cached.getAttributes().getFirst(name);
     }
 
@@ -132,7 +146,7 @@ public class GroupAdapter implements GroupModel {
 
     @Override
     public Set<RoleModel> getRealmRoleMappings() {
-        if (updated != null) return updated.getRealmRoleMappings();
+        if (isUpdated()) return updated.getRealmRoleMappings();
         Set<RoleModel> roleMappings = getRoleMappings();
         Set<RoleModel> realmMappings = new HashSet<RoleModel>();
         for (RoleModel role : roleMappings) {
@@ -148,7 +162,7 @@ public class GroupAdapter implements GroupModel {
 
     @Override
     public Set<RoleModel> getClientRoleMappings(ClientModel app) {
-        if (updated != null) return updated.getClientRoleMappings(app);
+        if (isUpdated()) return updated.getClientRoleMappings(app);
         Set<RoleModel> roleMappings = getRoleMappings();
         Set<RoleModel> appMappings = new HashSet<RoleModel>();
         for (RoleModel role : roleMappings) {
@@ -164,7 +178,7 @@ public class GroupAdapter implements GroupModel {
 
     @Override
     public boolean hasRole(RoleModel role) {
-        if (updated != null) return updated.hasRole(role);
+        if (isUpdated()) return updated.hasRole(role);
         if (cached.getRoleMappings().contains(role.getId())) return true;
 
         Set<RoleModel> mappings = getRoleMappings();
@@ -182,7 +196,7 @@ public class GroupAdapter implements GroupModel {
 
     @Override
     public Set<RoleModel> getRoleMappings() {
-        if (updated != null) return updated.getRoleMappings();
+        if (isUpdated()) return updated.getRoleMappings();
         Set<RoleModel> roles = new HashSet<RoleModel>();
         for (String id : cached.getRoleMappings()) {
             RoleModel roleById = keycloakSession.realms().getRoleById(id, realm);
@@ -205,20 +219,20 @@ public class GroupAdapter implements GroupModel {
 
     @Override
     public GroupModel getParent() {
-        if (updated != null) return updated.getParent();
+        if (isUpdated()) return updated.getParent();
         if (cached.getParentId() == null) return null;
         return keycloakSession.realms().getGroupById(cached.getParentId(), realm);
     }
 
     @Override
     public String getParentId() {
-        if (updated != null) return updated.getParentId();
+        if (isUpdated()) return updated.getParentId();
         return cached.getParentId();
     }
 
     @Override
     public Set<GroupModel> getSubGroups() {
-        if (updated != null) return updated.getSubGroups();
+        if (isUpdated()) return updated.getSubGroups();
         Set<GroupModel> subGroups = new HashSet<>();
         for (String id : cached.getSubGroups()) {
             GroupModel subGroup = keycloakSession.realms().getGroupById(id, realm);
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
index 837010c..be67c49 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
@@ -36,7 +36,7 @@ import java.util.*;
  */
 public class RealmAdapter implements RealmModel {
     protected CachedRealm cached;
-    protected CacheRealmProvider cacheSession;
+    protected RealmCacheSession cacheSession;
     protected RealmModel updated;
     protected RealmCache cache;
     protected volatile transient PublicKey publicKey;
@@ -44,28 +44,42 @@ public class RealmAdapter implements RealmModel {
     protected volatile transient Key codeSecretKey;
     protected volatile transient X509Certificate certificate;
 
-    public RealmAdapter(CachedRealm cached, CacheRealmProvider cacheSession) {
+    public RealmAdapter(CachedRealm cached, RealmCacheSession cacheSession) {
         this.cached = cached;
         this.cacheSession = cacheSession;
     }
 
     protected void getDelegateForUpdate() {
         if (updated == null) {
-            cacheSession.registerRealmInvalidation(getId());
-            updated = cacheSession.getDelegate().getRealm(getId());
+            cacheSession.registerRealmInvalidation(cached.getId());
+            updated = cacheSession.getDelegate().getRealm(cached.getId());
             if (updated == null) throw new IllegalStateException("Not found in database");
         }
     }
 
+    protected boolean invalidated;
+    public void invalidate() {
+        invalidated = true;
+    }
+
+    protected boolean isUpdated() {
+        if (updated != null) return true;
+        if (!invalidated) return false;
+        updated = cacheSession.getDelegate().getRealm(cached.getId());
+        if (updated == null) throw new IllegalStateException("Not found in database");
+        return true;
+    }
+
+
     @Override
     public String getId() {
-        if (updated != null) return updated.getId();
+        if (isUpdated()) return updated.getId();
         return cached.getId();
     }
 
     @Override
     public String getName() {
-        if (updated != null) return updated.getName();
+        if (isUpdated()) return updated.getName();
         return cached.getName();
     }
 
@@ -77,7 +91,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public String getDisplayName() {
-        if (updated != null) return updated.getDisplayName();
+        if (isUpdated()) return updated.getDisplayName();
         return cached.getDisplayName();
     }
 
@@ -89,7 +103,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public String getDisplayNameHtml() {
-        if (updated != null) return updated.getDisplayNameHtml();
+        if (isUpdated()) return updated.getDisplayNameHtml();
         return cached.getDisplayNameHtml();
     }
 
@@ -101,7 +115,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean isEnabled() {
-        if (updated != null) return updated.isEnabled();
+        if (isUpdated()) return updated.isEnabled();
         return cached.isEnabled();
     }
 
@@ -113,7 +127,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public SslRequired getSslRequired() {
-        if (updated != null) return updated.getSslRequired();
+        if (isUpdated()) return updated.getSslRequired();
         return cached.getSslRequired();
     }
 
@@ -125,7 +139,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean isRegistrationAllowed() {
-        if (updated != null) return updated.isRegistrationAllowed();
+        if (isUpdated()) return updated.isRegistrationAllowed();
         return cached.isRegistrationAllowed();
     }
 
@@ -137,7 +151,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean isRegistrationEmailAsUsername() {
-        if (updated != null) return updated.isRegistrationEmailAsUsername();
+        if (isUpdated()) return updated.isRegistrationEmailAsUsername();
         return cached.isRegistrationEmailAsUsername();
     }
 
@@ -149,7 +163,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean isRememberMe() {
-        if (updated != null) return updated.isRememberMe();
+        if (isUpdated()) return updated.isRememberMe();
         return cached.isRememberMe();
     }
 
@@ -161,7 +175,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean isBruteForceProtected() {
-        if (updated != null) return updated.isBruteForceProtected();
+        if (isUpdated()) return updated.isBruteForceProtected();
         return cached.isBruteForceProtected();
     }
 
@@ -173,7 +187,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getMaxFailureWaitSeconds() {
-        if (updated != null) return updated.getMaxFailureWaitSeconds();
+        if (isUpdated()) return updated.getMaxFailureWaitSeconds();
         return cached.getMaxFailureWaitSeconds();
     }
 
@@ -185,7 +199,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getWaitIncrementSeconds() {
-        if (updated != null) return updated.getWaitIncrementSeconds();
+        if (isUpdated()) return updated.getWaitIncrementSeconds();
         return cached.getWaitIncrementSeconds();
     }
 
@@ -197,7 +211,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getMinimumQuickLoginWaitSeconds() {
-        if (updated != null) return updated.getMinimumQuickLoginWaitSeconds();
+        if (isUpdated()) return updated.getMinimumQuickLoginWaitSeconds();
         return cached.getMinimumQuickLoginWaitSeconds();
     }
 
@@ -209,7 +223,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public long getQuickLoginCheckMilliSeconds() {
-        if (updated != null) return updated.getQuickLoginCheckMilliSeconds();
+        if (isUpdated()) return updated.getQuickLoginCheckMilliSeconds();
         return cached.getQuickLoginCheckMilliSeconds();
     }
 
@@ -221,7 +235,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getMaxDeltaTimeSeconds() {
-        if (updated != null) return updated.getMaxDeltaTimeSeconds();
+        if (isUpdated()) return updated.getMaxDeltaTimeSeconds();
         return cached.getMaxDeltaTimeSeconds();
     }
 
@@ -233,7 +247,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getFailureFactor() {
-        if (updated != null) return updated.getFailureFactor();
+        if (isUpdated()) return updated.getFailureFactor();
         return cached.getFailureFactor();
     }
 
@@ -245,7 +259,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean isVerifyEmail() {
-        if (updated != null) return updated.isVerifyEmail();
+        if (isUpdated()) return updated.isVerifyEmail();
         return cached.isVerifyEmail();
     }
 
@@ -257,7 +271,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean isResetPasswordAllowed() {
-        if (updated != null) return updated.isResetPasswordAllowed();
+        if (isUpdated()) return updated.isResetPasswordAllowed();
         return cached.isResetPasswordAllowed();
     }
 
@@ -269,7 +283,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean isEditUsernameAllowed() {
-        if (updated != null) return updated.isEditUsernameAllowed();
+        if (isUpdated()) return updated.isEditUsernameAllowed();
         return cached.isEditUsernameAllowed();
     }
 
@@ -281,7 +295,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean isRevokeRefreshToken() {
-        if (updated != null) return updated.isRevokeRefreshToken();
+        if (isUpdated()) return updated.isRevokeRefreshToken();
         return cached.isRevokeRefreshToken();
     }
 
@@ -293,7 +307,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getSsoSessionIdleTimeout() {
-        if (updated != null) return updated.getSsoSessionIdleTimeout();
+        if (isUpdated()) return updated.getSsoSessionIdleTimeout();
         return cached.getSsoSessionIdleTimeout();
     }
 
@@ -305,7 +319,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getSsoSessionMaxLifespan() {
-        if (updated != null) return updated.getSsoSessionMaxLifespan();
+        if (isUpdated()) return updated.getSsoSessionMaxLifespan();
         return cached.getSsoSessionMaxLifespan();
     }
 
@@ -317,7 +331,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getOfflineSessionIdleTimeout() {
-        if (updated != null) return updated.getOfflineSessionIdleTimeout();
+        if (isUpdated()) return updated.getOfflineSessionIdleTimeout();
         return cached.getOfflineSessionIdleTimeout();
     }
 
@@ -330,7 +344,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getAccessTokenLifespan() {
-        if (updated != null) return updated.getAccessTokenLifespan();
+        if (isUpdated()) return updated.getAccessTokenLifespan();
         return cached.getAccessTokenLifespan();
     }
 
@@ -342,7 +356,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getAccessTokenLifespanForImplicitFlow() {
-        if (updated != null) return updated.getAccessTokenLifespanForImplicitFlow();
+        if (isUpdated()) return updated.getAccessTokenLifespanForImplicitFlow();
         return cached.getAccessTokenLifespanForImplicitFlow();
     }
 
@@ -354,7 +368,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getAccessCodeLifespan() {
-        if (updated != null) return updated.getAccessCodeLifespan();
+        if (isUpdated()) return updated.getAccessCodeLifespan();
         return cached.getAccessCodeLifespan();
     }
 
@@ -366,7 +380,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getAccessCodeLifespanUserAction() {
-        if (updated != null) return updated.getAccessCodeLifespanUserAction();
+        if (isUpdated()) return updated.getAccessCodeLifespanUserAction();
         return cached.getAccessCodeLifespanUserAction();
     }
 
@@ -378,7 +392,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getAccessCodeLifespanLogin() {
-        if (updated != null) return updated.getAccessCodeLifespanLogin();
+        if (isUpdated()) return updated.getAccessCodeLifespanLogin();
         return cached.getAccessCodeLifespanLogin();
     }
 
@@ -390,7 +404,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public String getPublicKeyPem() {
-        if (updated != null) return updated.getPublicKeyPem();
+        if (isUpdated()) return updated.getPublicKeyPem();
         return cached.getPublicKeyPem();
     }
 
@@ -402,7 +416,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public String getPrivateKeyPem() {
-        if (updated != null) return updated.getPrivateKeyPem();
+        if (isUpdated()) return updated.getPrivateKeyPem();
         return cached.getPrivateKeyPem();
     }
 
@@ -414,7 +428,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public PublicKey getPublicKey() {
-        if (updated != null) return updated.getPublicKey();
+        if (isUpdated()) return updated.getPublicKey();
         if (publicKey != null) return publicKey;
         publicKey = cached.getPublicKey();
         if (publicKey != null) return publicKey;
@@ -431,7 +445,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public X509Certificate getCertificate() {
-        if (updated != null) return updated.getCertificate();
+        if (isUpdated()) return updated.getCertificate();
         if (certificate != null) return certificate;
         certificate = cached.getCertificate();
         if (certificate != null) return certificate;
@@ -448,7 +462,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public String getCertificatePem() {
-        if (updated != null) return updated.getCertificatePem();
+        if (isUpdated()) return updated.getCertificatePem();
         return cached.getCertificatePem();
     }
 
@@ -461,7 +475,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public PrivateKey getPrivateKey() {
-        if (updated != null) return updated.getPrivateKey();
+        if (isUpdated()) return updated.getPrivateKey();
         if (privateKey != null) {
             return privateKey;
         }
@@ -482,7 +496,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public String getCodeSecret() {
-        return updated != null ? updated.getCodeSecret() : cached.getCodeSecret();
+        return isUpdated() ? updated.getCodeSecret() : cached.getCodeSecret();
     }
 
     @Override
@@ -501,7 +515,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public List<RequiredCredentialModel> getRequiredCredentials() {
-        if (updated != null) return updated.getRequiredCredentials();
+        if (isUpdated()) return updated.getRequiredCredentials();
         return cached.getRequiredCredentials();
     }
 
@@ -513,7 +527,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public PasswordPolicy getPasswordPolicy() {
-        if (updated != null) return updated.getPasswordPolicy();
+        if (isUpdated()) return updated.getPasswordPolicy();
         return cached.getPasswordPolicy();
     }
 
@@ -525,7 +539,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public OTPPolicy getOTPPolicy() {
-        if (updated != null) return updated.getOTPPolicy();
+        if (isUpdated()) return updated.getOTPPolicy();
         return cached.getOtpPolicy();
     }
 
@@ -538,13 +552,13 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public RoleModel getRoleById(String id) {
-        if (updated != null) return updated.getRoleById(id);
+        if (isUpdated()) return updated.getRoleById(id);
         return cacheSession.getRoleById(id, this);
      }
 
     @Override
     public List<GroupModel> getDefaultGroups() {
-        if (updated != null) return updated.getDefaultGroups();
+        if (isUpdated()) return updated.getDefaultGroups();
 
         List<GroupModel> defaultGroups = new LinkedList<>();
         for (String id : cached.getDefaultGroups()) {
@@ -570,7 +584,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public List<String> getDefaultRoles() {
-        if (updated != null) return updated.getDefaultRoles();
+        if (isUpdated()) return updated.getDefaultRoles();
         return cached.getDefaultRoles();
     }
 
@@ -616,7 +630,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public ClientModel getClientById(String id) {
-        if (updated != null) return updated.getClientById(id);
+        if (isUpdated()) return updated.getClientById(id);
         return cacheSession.getClientById(id, this);
     }
 
@@ -633,7 +647,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public Map<String, String> getBrowserSecurityHeaders() {
-        if (updated != null) return updated.getBrowserSecurityHeaders();
+        if (isUpdated()) return updated.getBrowserSecurityHeaders();
         return cached.getBrowserSecurityHeaders();
     }
 
@@ -646,7 +660,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public Map<String, String> getSmtpConfig() {
-        if (updated != null) return updated.getSmtpConfig();
+        if (isUpdated()) return updated.getSmtpConfig();
         return cached.getSmtpConfig();
     }
 
@@ -659,13 +673,13 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public List<IdentityProviderModel> getIdentityProviders() {
-        if (updated != null) return updated.getIdentityProviders();
+        if (isUpdated()) return updated.getIdentityProviders();
         return cached.getIdentityProviders();
     }
 
     @Override
     public IdentityProviderModel getIdentityProviderByAlias(String alias) {
-        if (updated != null) return updated.getIdentityProviderByAlias(alias);
+        if (isUpdated()) return updated.getIdentityProviderByAlias(alias);
         for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
             if (identityProviderModel.getAlias().equals(alias)) {
                 return identityProviderModel;
@@ -695,7 +709,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public List<UserFederationProviderModel> getUserFederationProviders() {
-        if (updated != null) return updated.getUserFederationProviders();
+        if (isUpdated()) return updated.getUserFederationProviders();
         return cached.getUserFederationProviders();
     }
 
@@ -727,7 +741,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public String getLoginTheme() {
-        if (updated != null) return updated.getLoginTheme();
+        if (isUpdated()) return updated.getLoginTheme();
         return cached.getLoginTheme();
     }
 
@@ -739,7 +753,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public String getAccountTheme() {
-        if (updated != null) return updated.getAccountTheme();
+        if (isUpdated()) return updated.getAccountTheme();
         return cached.getAccountTheme();
     }
 
@@ -751,7 +765,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public String getAdminTheme() {
-        if (updated != null) return updated.getAdminTheme();
+        if (isUpdated()) return updated.getAdminTheme();
         return cached.getAdminTheme();
     }
 
@@ -763,7 +777,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public String getEmailTheme() {
-        if (updated != null) return updated.getEmailTheme();
+        if (isUpdated()) return updated.getEmailTheme();
         return cached.getEmailTheme();
     }
 
@@ -775,7 +789,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public int getNotBefore() {
-        if (updated != null) return updated.getNotBefore();
+        if (isUpdated()) return updated.getNotBefore();
         return cached.getNotBefore();
     }
 
@@ -794,7 +808,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean isEventsEnabled() {
-        if (updated != null) return updated.isEventsEnabled();
+        if (isUpdated()) return updated.isEventsEnabled();
         return cached.isEventsEnabled();
     }
 
@@ -806,7 +820,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public long getEventsExpiration() {
-        if (updated != null) return updated.getEventsExpiration();
+        if (isUpdated()) return updated.getEventsExpiration();
         return cached.getEventsExpiration();
     }
 
@@ -818,7 +832,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public Set<String> getEventsListeners() {
-        if (updated != null) return updated.getEventsListeners();
+        if (isUpdated()) return updated.getEventsListeners();
         return cached.getEventsListeners();
     }
 
@@ -830,7 +844,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public Set<String> getEnabledEventTypes() {
-        if (updated != null) return updated.getEnabledEventTypes();
+        if (isUpdated()) return updated.getEnabledEventTypes();
         return cached.getEnabledEventTypes();
     }
 
@@ -842,7 +856,7 @@ public class RealmAdapter implements RealmModel {
     
     @Override
     public boolean isAdminEventsEnabled() {
-        if (updated != null) return updated.isAdminEventsEnabled();
+        if (isUpdated()) return updated.isAdminEventsEnabled();
         return cached.isAdminEventsEnabled();
     }
 
@@ -854,7 +868,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean isAdminEventsDetailsEnabled() {
-        if (updated != null) return updated.isAdminEventsDetailsEnabled();
+        if (isUpdated()) return updated.isAdminEventsDetailsEnabled();
         return cached.isAdminEventsDetailsEnabled();
     }
 
@@ -907,15 +921,13 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean removeRole(RoleModel role) {
-        cacheSession.registerRoleInvalidation(role.getId());
-        getDelegateForUpdate();
-        return updated.removeRole(role);
+        return cacheSession.removeRole(this, role);
     }
 
 
     @Override
     public boolean isIdentityFederationEnabled() {
-        if (updated != null) return updated.isIdentityFederationEnabled();
+        if (isUpdated()) return updated.isIdentityFederationEnabled();
         return cached.isIdentityFederationEnabled();
     }
 
@@ -936,7 +948,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean isInternationalizationEnabled() {
-        if (updated != null) return updated.isInternationalizationEnabled();
+        if (isUpdated()) return updated.isInternationalizationEnabled();
         return cached.isInternationalizationEnabled();
     }
 
@@ -948,7 +960,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public Set<String> getSupportedLocales() {
-        if (updated != null) return updated.getSupportedLocales();
+        if (isUpdated()) return updated.getSupportedLocales();
         return cached.getSupportedLocales();
     }
 
@@ -960,7 +972,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public String getDefaultLocale() {
-        if (updated != null) return updated.getDefaultLocale();
+        if (isUpdated()) return updated.getDefaultLocale();
         return cached.getDefaultLocale();
     }
 
@@ -971,13 +983,13 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
-        if (updated != null) return updated.getIdentityProviderMappers();
+        if (isUpdated()) return updated.getIdentityProviderMappers();
         return cached.getIdentityProviderMapperSet();
     }
 
     @Override
     public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
-        if (updated != null) return updated.getIdentityProviderMappersByAlias(brokerAlias);
+        if (isUpdated()) return updated.getIdentityProviderMappersByAlias(brokerAlias);
         Set<IdentityProviderMapperModel> mappings = new HashSet<>();
         List<IdentityProviderMapperModel> list = cached.getIdentityProviderMappers().getList(brokerAlias);
         for (IdentityProviderMapperModel entity : list) {
@@ -1006,7 +1018,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public IdentityProviderMapperModel getIdentityProviderMapperById(String id) {
-        if (updated != null) return updated.getIdentityProviderMapperById(id);
+        if (isUpdated()) return updated.getIdentityProviderMapperById(id);
         for (List<IdentityProviderMapperModel> models : cached.getIdentityProviderMappers().values()) {
             for (IdentityProviderMapperModel model : models) {
                 if (model.getId().equals(id)) return model;
@@ -1017,7 +1029,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) {
-        if (updated != null) return updated.getIdentityProviderMapperByName(alias, name);
+        if (isUpdated()) return updated.getIdentityProviderMapperByName(alias, name);
         List<IdentityProviderMapperModel> models = cached.getIdentityProviderMappers().getList(alias);
         if (models == null) return null;
         for (IdentityProviderMapperModel model : models) {
@@ -1028,13 +1040,13 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public Set<UserFederationMapperModel> getUserFederationMappers() {
-        if (updated != null) return updated.getUserFederationMappers();
+        if (isUpdated()) return updated.getUserFederationMappers();
         return cached.getUserFederationMapperSet();
     }
 
     @Override
     public Set<UserFederationMapperModel> getUserFederationMappersByFederationProvider(String federationProviderId) {
-        if (updated != null) return updated.getUserFederationMappersByFederationProvider(federationProviderId);
+        if (isUpdated()) return updated.getUserFederationMappersByFederationProvider(federationProviderId);
         Set<UserFederationMapperModel> mappers = new HashSet<>();
         List<UserFederationMapperModel> list = cached.getUserFederationMappers().getList(federationProviderId);
         for (UserFederationMapperModel entity : list) {
@@ -1063,7 +1075,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public UserFederationMapperModel getUserFederationMapperById(String id) {
-        if (updated != null) return updated.getUserFederationMapperById(id);
+        if (isUpdated()) return updated.getUserFederationMapperById(id);
         for (List<UserFederationMapperModel> models : cached.getUserFederationMappers().values()) {
             for (UserFederationMapperModel model : models) {
                 if (model.getId().equals(id)) return model;
@@ -1074,7 +1086,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public UserFederationMapperModel getUserFederationMapperByName(String federationProviderId, String name) {
-        if (updated != null) return updated.getUserFederationMapperByName(federationProviderId, name);
+        if (isUpdated()) return updated.getUserFederationMapperByName(federationProviderId, name);
         List<UserFederationMapperModel> models = cached.getUserFederationMappers().getList(federationProviderId);
         if (models == null) return null;
         for (UserFederationMapperModel model : models) {
@@ -1085,7 +1097,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public AuthenticationFlowModel getBrowserFlow() {
-        if (updated != null) return updated.getBrowserFlow();
+        if (isUpdated()) return updated.getBrowserFlow();
         return cached.getBrowserFlow();
     }
 
@@ -1098,7 +1110,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public AuthenticationFlowModel getRegistrationFlow() {
-        if (updated != null) return updated.getRegistrationFlow();
+        if (isUpdated()) return updated.getRegistrationFlow();
         return cached.getRegistrationFlow();
     }
 
@@ -1111,7 +1123,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public AuthenticationFlowModel getDirectGrantFlow() {
-        if (updated != null) return updated.getDirectGrantFlow();
+        if (isUpdated()) return updated.getDirectGrantFlow();
         return cached.getDirectGrantFlow();
     }
 
@@ -1123,7 +1135,7 @@ public class RealmAdapter implements RealmModel {
     }
     @Override
     public AuthenticationFlowModel getResetCredentialsFlow() {
-        if (updated != null) return updated.getResetCredentialsFlow();
+        if (isUpdated()) return updated.getResetCredentialsFlow();
         return cached.getResetCredentialsFlow();
     }
 
@@ -1136,7 +1148,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public AuthenticationFlowModel getClientAuthenticationFlow() {
-        if (updated != null) return updated.getClientAuthenticationFlow();
+        if (isUpdated()) return updated.getClientAuthenticationFlow();
         return cached.getClientAuthenticationFlow();
     }
 
@@ -1148,7 +1160,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public List<AuthenticationFlowModel> getAuthenticationFlows() {
-        if (updated != null) return updated.getAuthenticationFlows();
+        if (isUpdated()) return updated.getAuthenticationFlows();
         return cached.getAuthenticationFlowList();
     }
 
@@ -1181,7 +1193,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public AuthenticationFlowModel getAuthenticationFlowById(String id) {
-        if (updated != null) return updated.getAuthenticationFlowById(id);
+        if (isUpdated()) return updated.getAuthenticationFlowById(id);
         return cached.getAuthenticationFlows().get(id);
     }
 
@@ -1201,13 +1213,13 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
-        if (updated != null) return updated.getAuthenticationExecutions(flowId);
+        if (isUpdated()) return updated.getAuthenticationExecutions(flowId);
         return cached.getAuthenticationExecutions().get(flowId);
     }
 
     @Override
     public AuthenticationExecutionModel getAuthenticationExecutionById(String id) {
-        if (updated != null) return updated.getAuthenticationExecutionById(id);
+        if (isUpdated()) return updated.getAuthenticationExecutionById(id);
         return cached.getExecutionsById().get(id);
     }
 
@@ -1233,7 +1245,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public List<AuthenticatorConfigModel> getAuthenticatorConfigs() {
-        if (updated != null) return updated.getAuthenticatorConfigs();
+        if (isUpdated()) return updated.getAuthenticatorConfigs();
         List<AuthenticatorConfigModel> models = new ArrayList<>();
         models.addAll(cached.getAuthenticatorConfigs().values());
         return Collections.unmodifiableList(models);
@@ -1261,13 +1273,13 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public AuthenticatorConfigModel getAuthenticatorConfigById(String id) {
-        if (updated != null) return updated.getAuthenticatorConfigById(id);
+        if (isUpdated()) return updated.getAuthenticatorConfigById(id);
         return cached.getAuthenticatorConfigs().get(id);
     }
 
     @Override
     public List<RequiredActionProviderModel> getRequiredActionProviders() {
-        if (updated != null) return updated.getRequiredActionProviders();
+        if (isUpdated()) return updated.getRequiredActionProviders();
         return cached.getRequiredActionProviderList();
     }
 
@@ -1293,13 +1305,13 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public RequiredActionProviderModel getRequiredActionProviderById(String id) {
-        if (updated != null) return updated.getRequiredActionProviderById(id);
+        if (isUpdated()) return updated.getRequiredActionProviderById(id);
         return cached.getRequiredActionProviders().get(id);
     }
 
     @Override
     public RequiredActionProviderModel getRequiredActionProviderByAlias(String alias) {
-        if (updated != null) return updated.getRequiredActionProviderByAlias(alias);
+        if (isUpdated()) return updated.getRequiredActionProviderByAlias(alias);
         return cached.getRequiredActionProvidersByAlias().get(alias);
     }
 
@@ -1346,7 +1358,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public List<ClientTemplateModel> getClientTemplates() {
-        if (updated != null) return updated.getClientTemplates();
+        if (isUpdated()) return updated.getClientTemplates();
         List<String> clientTemplates = cached.getClientTemplates();
         if (clientTemplates.isEmpty()) return Collections.EMPTY_LIST;
         List<ClientTemplateModel> apps = new LinkedList<ClientTemplateModel>();
@@ -1386,7 +1398,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public ClientTemplateModel getClientTemplateById(String id) {
-        if (updated != null) return updated.getClientTemplateById(id);
+        if (isUpdated()) return updated.getClientTemplateById(id);
         return cacheSession.getClientTemplateById(id, this);
     }
 
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java
index 4a149ba..2a78a41 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java
@@ -117,11 +117,11 @@ public class RealmCacheSession implements CacheRealmProvider {
     protected boolean transactionActive;
     protected boolean setRollbackOnly;
 
-    protected Map<String, RealmModel> managedRealms = new HashMap<>();
-    protected Map<String, ClientModel> managedApplications = new HashMap<>();
-    protected Map<String, ClientTemplateModel> managedClientTemplates = new HashMap<>();
-    protected Map<String, RoleModel> managedRoles = new HashMap<>();
-    protected Map<String, GroupModel> managedGroups = new HashMap<>();
+    protected Map<String, RealmAdapter> managedRealms = new HashMap<>();
+    protected Map<String, ClientAdapter> managedApplications = new HashMap<>();
+    protected Map<String, ClientTemplateAdapter> managedClientTemplates = new HashMap<>();
+    protected Map<String, RoleAdapter> managedRoles = new HashMap<>();
+    protected Map<String, GroupAdapter> managedGroups = new HashMap<>();
     protected Set<String> listInvalidations = new HashSet<>();
     protected Set<String> invalidations = new HashSet<>();
 
@@ -140,6 +140,10 @@ public class RealmCacheSession implements CacheRealmProvider {
         return startupRevision;
     }
 
+    public boolean isInvalid(String id) {
+        return invalidations.contains(id);
+    }
+
     @Override
     public void clear() {
         cache.clear();
@@ -160,33 +164,88 @@ public class RealmCacheSession implements CacheRealmProvider {
 
     @Override
     public void registerRealmInvalidation(String id) {
-        invalidations.add(id);
+        invalidateRealm(id);
         cache.realmInvalidation(id, invalidations);
     }
 
+    private void invalidateRealm(String id) {
+        invalidations.add(id);
+        RealmAdapter adapter = managedRealms.get(id);
+        if (adapter != null) adapter.invalidate();
+    }
+
     @Override
     public void registerClientInvalidation(String id) {
-        invalidations.add(id);
+        invalidateClient(id);
         cache.clientInvalidation(id, invalidations);
     }
+
+    private void invalidateClient(String id) {
+        invalidations.add(id);
+        ClientAdapter adapter = managedApplications.get(id);
+        if (adapter != null) adapter.invalidate();
+    }
+
     @Override
     public void registerClientTemplateInvalidation(String id) {
-        invalidations.add(id);
+        invalidateClientTemplate(id);
         cache.clientTemplateInvalidation(id, invalidations);
     }
 
+    private void invalidateClientTemplate(String id) {
+        invalidations.add(id);
+        ClientTemplateAdapter adapter = managedClientTemplates.get(id);
+        if (adapter != null) adapter.invalidate();
+    }
+
     @Override
     public void registerRoleInvalidation(String id) {
+        invalidateRole(id);
+        roleInvalidations(id);
+    }
+
+    private void roleInvalidations(String roleId) {
+        Set<String> newInvalidations = new HashSet<>();
+        cache.roleInvalidation(roleId, newInvalidations);
+        invalidations.addAll(newInvalidations);
+        // need to make sure that scope and group mapping clients and groups are invalidated
+        for (String id : newInvalidations) {
+            ClientAdapter adapter = managedApplications.get(id);
+            if (adapter != null) {
+                adapter.invalidate();
+                continue;
+            }
+            GroupAdapter group = managedGroups.get(id);
+            if (group != null) {
+                group.invalidate();
+                continue;
+            }
+
+
+        }
+    }
+
+
+
+
+    private void invalidateRole(String id) {
         invalidations.add(id);
-        cache.roleInvalidation(id, invalidations);
+        RoleAdapter adapter = managedRoles.get(id);
+        if (adapter != null) adapter.invalidate();
     }
 
     @Override
     public void registerGroupInvalidation(String id) {
-        invalidations.add(id);
+        invalidateGroup(id);
         cache.groupInvalidation(id, invalidations);
     }
 
+    private void invalidateGroup(String id) {
+        invalidations.add(id);
+        GroupAdapter adapter = managedGroups.get(id);
+        if (adapter != null) adapter.invalidate();
+    }
+
     protected void runInvalidations() {
         for (String id : invalidations) {
             cache.invalidateObject(id);
@@ -381,7 +440,7 @@ public class RealmCacheSession implements CacheRealmProvider {
     }
 
     protected void invalidateClient(RealmModel realm, ClientModel client) {
-        invalidations.add(client.getId());
+        invalidateClient(client.getId());
         invalidations.add(getRealmClientsQueryCacheKey(realm.getId()));
         invalidations.add(getClientByClientIdCacheKey(client.getClientId(), realm));
         listInvalidations.add(realm.getId());
@@ -474,11 +533,13 @@ public class RealmCacheSession implements CacheRealmProvider {
         invalidateClient(realm, client);
         cache.clientRemoval(realm.getId(), id, invalidations);
         for (RoleModel role : client.getRoles()) {
-            cache.roleInvalidation(role.getId(), invalidations);
+            String roleId = role.getId();
+            roleInvalidations(roleId);
         }
         return getDelegate().removeClient(id, realm);
     }
 
+
     @Override
     public void close() {
         if (delegate != null) delegate.close();
@@ -582,7 +643,7 @@ public class RealmCacheSession implements CacheRealmProvider {
         // this is needed so that a new role that hasn't been committed isn't cached in a query
         listInvalidations.add(client.getId());
         RoleModel role = getDelegate().addClientRole(realm, client, id, name);
-        invalidations.add(role.getId());
+        invalidateRole(role.getId());
         return role;
     }
 
@@ -651,7 +712,7 @@ public class RealmCacheSession implements CacheRealmProvider {
         invalidations.add(getRolesCacheKey(role.getContainer().getId()));
         invalidations.add(getRoleByNameCacheKey(role.getContainer().getId(), role.getName()));
         listInvalidations.add(role.getContainer().getId());
-        invalidations.add(role.getId());
+        registerRoleInvalidation(role.getId());
         return getDelegate().removeRole(realm, role);
     }
 
@@ -913,7 +974,7 @@ public class RealmCacheSession implements CacheRealmProvider {
         } else if (managedClientTemplates.containsKey(id)) {
             return managedClientTemplates.get(id);
         }
-        ClientTemplateModel adapter = new ClientTemplateAdapter(realm, cached, this);
+        ClientTemplateAdapter adapter = new ClientTemplateAdapter(realm, cached, this);
         managedClientTemplates.put(id, adapter);
         return adapter;
     }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RoleAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RoleAdapter.java
index 0b0c3a6..99fbcaa 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RoleAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RoleAdapter.java
@@ -37,10 +37,10 @@ public class RoleAdapter implements RoleModel {
 
     protected RoleModel updated;
     protected CachedRole cached;
-    protected CacheRealmProvider cacheSession;
+    protected RealmCacheSession cacheSession;
     protected RealmModel realm;
 
-    public RoleAdapter(CachedRole cached, CacheRealmProvider session, RealmModel realm) {
+    public RoleAdapter(CachedRole cached, RealmCacheSession session, RealmModel realm) {
         this.cached = cached;
         this.cacheSession = session;
         this.realm = realm;
@@ -48,22 +48,37 @@ public class RoleAdapter implements RoleModel {
 
     protected void getDelegateForUpdate() {
         if (updated == null) {
-            cacheSession.registerRoleInvalidation(getId());
-            updated = cacheSession.getDelegate().getRoleById(getId(), realm);
+            cacheSession.registerRoleInvalidation(cached.getId());
+            updated = cacheSession.getDelegate().getRoleById(cached.getId(), realm);
             if (updated == null) throw new IllegalStateException("Not found in database");
         }
     }
 
+    protected boolean invalidated;
+    public void invalidate() {
+        invalidated = true;
+    }
+
+    protected boolean isUpdated() {
+        if (updated != null) return true;
+        if (!invalidated) return false;
+        updated = cacheSession.getDelegate().getRoleById(cached.getId(), realm);
+        if (updated == null) throw new IllegalStateException("Not found in database");
+        return true;
+    }
+
+
+
 
     @Override
     public String getName() {
-        if (updated != null) return updated.getName();
+        if (isUpdated()) return updated.getName();
         return cached.getName();
     }
 
     @Override
     public String getDescription() {
-        if (updated != null) return updated.getDescription();
+        if (isUpdated()) return updated.getDescription();
         return cached.getDescription();
     }
 
@@ -75,7 +90,7 @@ public class RoleAdapter implements RoleModel {
 
     @Override
     public boolean isScopeParamRequired() {
-        if (updated != null) return updated.isScopeParamRequired();
+        if (isUpdated()) return updated.isScopeParamRequired();
         return cached.isScopeParamRequired();
     }
 
@@ -87,7 +102,7 @@ public class RoleAdapter implements RoleModel {
 
     @Override
     public String getId() {
-        if (updated != null) return updated.getId();
+        if (isUpdated()) return updated.getId();
         return cached.getId();
     }
 
@@ -99,7 +114,7 @@ public class RoleAdapter implements RoleModel {
 
     @Override
     public boolean isComposite() {
-        if (updated != null) return updated.isComposite();
+        if (isUpdated()) return updated.isComposite();
         return cached.isComposite();
     }
 
@@ -117,7 +132,7 @@ public class RoleAdapter implements RoleModel {
 
     @Override
     public Set<RoleModel> getComposites() {
-        if (updated != null) return updated.getComposites();
+        if (isUpdated()) return updated.getComposites();
         Set<RoleModel> set = new HashSet<RoleModel>();
         for (String id : cached.getComposites()) {
             RoleModel role = realm.getRoleById(id);
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/stream/HasRolePredicate.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/stream/HasRolePredicate.java
index 7d32462..13f1165 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/stream/HasRolePredicate.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/stream/HasRolePredicate.java
@@ -1,5 +1,6 @@
 package org.keycloak.models.cache.infinispan.stream;
 
+import org.keycloak.models.cache.infinispan.entities.CachedClient;
 import org.keycloak.models.cache.infinispan.entities.CachedGroup;
 import org.keycloak.models.cache.infinispan.entities.CachedRole;
 import org.keycloak.models.cache.infinispan.entities.Revisioned;
@@ -41,6 +42,11 @@ public class HasRolePredicate implements Predicate<Map.Entry<String, Revisioned>
             RoleQuery roleQuery = (RoleQuery)value;
             if (roleQuery.getRoles().contains(role)) return true;
         }
+        if (value instanceof CachedClient) {
+            CachedClient cachedClient = (CachedClient)value;
+            if (cachedClient.getScope().contains(role)) return true;
+
+        }
         return false;
     }
 }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java
index 595dccd..1766a2f 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java
@@ -33,6 +33,7 @@ import org.keycloak.services.managers.ClientManager;
 
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -40,13 +41,11 @@ import java.util.List;
 public class ClientModelTest extends AbstractModelTest {
     private ClientModel client;
     private RealmModel realm;
-    private ClientManager appManager;
 
     @Before
     @Override
     public void before() throws Exception {
         super.before();
-        appManager = new ClientManager(realmManager);
 
         realm = realmManager.createRealm("original");
         client = realm.addClient("application");
@@ -74,6 +73,77 @@ public class ClientModelTest extends AbstractModelTest {
     }
 
     @Test
+    public void testClientRoleRemovalAndClientScope() throws Exception {
+        // Client "from" has a role.  Assign this role to a scope to client "scoped".  Delete the role and make sure
+        // cache gets cleared
+        ClientModel from = realm.addClient("from");
+        RoleModel role = from.addRole("clientRole");
+        String roleId = role.getId();
+        ClientModel scoped = realm.addClient("scoped");
+        String idOfClient = scoped.getId();
+        scoped.setFullScopeAllowed(false);
+        scoped.addScopeMapping(role);
+        commit();
+        realm = session.realms().getRealmByName("original");
+        scoped = realm.getClientByClientId("scoped");
+        from = realm.getClientByClientId("from");
+        role = session.realms().getRoleById(roleId, realm);
+        from.removeRole(role);
+        commit();
+        realm = session.realms().getRealmByName("original");
+        scoped = realm.getClientByClientId("scoped");
+        Set<RoleModel> scopeMappings = scoped.getScopeMappings();
+        Assert.assertEquals(0, scopeMappings.size());  // used to throw an NPE
+
+    }
+
+    @Test
+    public void testClientRoleRemovalAndClientScopeSameTx() throws Exception {
+        // Client "from" has a role.  Assign this role to a scope to client "scoped".  Delete the role and make sure
+        // cache gets cleared
+        ClientModel from = realm.addClient("from");
+        RoleModel role = from.addRole("clientRole");
+        String roleId = role.getId();
+        ClientModel scoped = realm.addClient("scoped");
+        String idOfClient = scoped.getId();
+        scoped.setFullScopeAllowed(false);
+        scoped.addScopeMapping(role);
+        commit();
+        realm = session.realms().getRealmByName("original");
+        scoped = realm.getClientByClientId("scoped");
+        from = realm.getClientByClientId("from");
+        role = session.realms().getRoleById(roleId, realm);
+        from.removeRole(role);
+        Set<RoleModel> scopeMappings = scoped.getScopeMappings();
+        Assert.assertEquals(0, scopeMappings.size());  // used to throw an NPE
+
+    }
+
+    @Test
+    public void testRealmRoleRemovalAndClientScope() throws Exception {
+        // Client "from" has a role.  Assign this role to a scope to client "scoped".  Delete the role and make sure
+        // cache gets cleared
+        RoleModel role = realm.addRole("clientRole");
+        String roleId = role.getId();
+        ClientModel scoped = realm.addClient("scoped");
+        String idOfClient = scoped.getId();
+        scoped.setFullScopeAllowed(false);
+        scoped.addScopeMapping(role);
+        commit();
+        realm = session.realms().getRealmByName("original");
+        scoped = realm.getClientByClientId("scoped");
+        role = session.realms().getRoleById(roleId, realm);
+        realm.removeRole(role);
+        commit();
+        realm = session.realms().getRealmByName("original");
+        scoped = realm.getClientByClientId("scoped");
+        Set<RoleModel> scopeMappings = scoped.getScopeMappings();
+        Assert.assertEquals(0, scopeMappings.size());  // used to throw an NPE
+
+    }
+
+
+    @Test
     public void persist() {
         RealmModel persisted = realmManager.getRealm(realm.getId());