keycloak-uncached

cache impl

6/13/2014 6:17:45 PM

Changes

model/pom.xml 2(+1 -1)

services/pom.xml 12(+12 -0)

Details

diff --git a/export-import/export-import-impl/pom.xml b/export-import/export-import-impl/pom.xml
index 595b2b7..2c27436 100755
--- a/export-import/export-import-impl/pom.xml
+++ b/export-import/export-import-impl/pom.xml
@@ -97,6 +97,12 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-invalidation-cache-model</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-model-jpa</artifactId>
             <version>${project.version}</version>
             <scope>test</scope>
diff --git a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
index f364503..3c841a5 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
@@ -54,7 +54,7 @@ public class RealmEntity extends AbstractIdentifiableEntity {
 
     private Map<String, String> smtpConfig = new HashMap<String, String>();
     private Map<String, String> socialConfig = new HashMap<String, String>();
-    private Map<String, String> ldapServerConfig;
+    private Map<String, String> ldapServerConfig = new HashMap<String, String>();
 
     private boolean auditEnabled;
     private long auditExpiration;
diff --git a/model/invalidation-cache/model-adapters/pom.xml b/model/invalidation-cache/model-adapters/pom.xml
index 929b80b..3eecff0 100755
--- a/model/invalidation-cache/model-adapters/pom.xml
+++ b/model/invalidation-cache/model-adapters/pom.xml
@@ -36,17 +36,6 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-            <version>${hibernate.entitymanager.version}</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
             <groupId>org.jboss.resteasy</groupId>
             <artifactId>resteasy-jaxrs</artifactId>
             <scope>provided</scope>
@@ -83,37 +72,6 @@
                     <target>${maven.compiler.target}</target>
                 </configuration>
             </plugin>
-
-            <!-- Test jar used in export-import -->
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>package-tests-jar</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>test-jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>default-test</id>
-                        <configuration>
-                            <dependenciesToScan>
-                                <dependency>org.keycloak:keycloak-model-tests</dependency>
-                            </dependenciesToScan>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-
         </plugins>
     </build>
 
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ApplicationAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ApplicationAdapter.java
index 62de047..81f608e 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ApplicationAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ApplicationAdapter.java
@@ -28,6 +28,7 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode
     @Override
     protected void getDelegateForUpdate() {
         if (updated == null) {
+            cacheSession.registerApplicationInvalidation(getId());
             updatedClient = updated = cacheSession.getDelegate().getApplicationById(getId(), cachedRealm);
             if (updated == null) throw new IllegalStateException("Not found in database");
         }
@@ -40,7 +41,8 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode
 
     @Override
     public String getName() {
-        return getClientId();
+        if (updated != null) return updated.getName();
+        return cached.getName();
     }
 
     @Override
@@ -150,17 +152,22 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode
     @Override
     public RoleModel addRole(String name) {
         getDelegateForUpdate();
-        return updated.addRole(name);
+        RoleModel role = updated.addRole(name);
+        cacheSession.registerRoleInvalidation(role.getId());
+        return role;
     }
 
     @Override
     public RoleModel addRole(String id, String name) {
         getDelegateForUpdate();
-        return updated.addRole(id, name);
+        RoleModel role =  updated.addRole(id, name);
+        cacheSession.registerRoleInvalidation(role.getId());
+        return role;
     }
 
     @Override
     public boolean removeRole(RoleModel role) {
+        cacheSession.registerRoleInvalidation(role.getId());
         getDelegateForUpdate();
         return updated.removeRole(role);
     }
@@ -171,8 +178,25 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode
 
         Set<RoleModel> roles = new HashSet<RoleModel>();
         for (String id : cached.getRoles().values()) {
-            roles.add(cacheSession.getRoleById(id, cachedRealm));
+            RoleModel roleById = cacheSession.getRoleById(id, cachedRealm);
+            if (roleById == null) continue;
+            roles.add(roleById);
         }
         return roles;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof ApplicationModel)) return false;
+
+        ApplicationModel that = (ApplicationModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSession.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSession.java
index 9aec5d4..7ad72b8 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSession.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSession.java
@@ -1,291 +1,19 @@
 package org.keycloak.models.cache;
 
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.AuthenticationLinkModel;
-import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakTransaction;
-import org.keycloak.models.OAuthClientModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.SocialLinkModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.UsernameLoginFailureModel;
-import org.keycloak.models.cache.entities.CachedRealm;
-import org.keycloak.models.cache.entities.CachedRole;
-import org.keycloak.provider.ProviderSession;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class CacheKeycloakSession implements KeycloakSession {
-    protected KeycloakCache cache;
-    protected ProviderSession providerSession;
-    protected KeycloakSession sessionDelegate;
-    protected KeycloakTransaction transactionDelegate;
-    protected boolean transactionActive;
-    protected boolean setRollbackOnly;
-
-    protected Set<String> realmInvalidations = new HashSet<String>();
-    protected boolean clearAll;
-
-    protected KeycloakSession getDelegate() {
-        if (!transactionActive) throw new IllegalStateException("Cannot access delegate without a transaction");
-        if (sessionDelegate != null) return sessionDelegate;
-        sessionDelegate = providerSession.getProvider(KeycloakSession.class);
-        transactionDelegate = sessionDelegate.getTransaction();
-        if (!transactionDelegate.isActive()) {
-            transactionDelegate.begin();
-            if (setRollbackOnly) {
-                transactionDelegate.setRollbackOnly();
-            }
-        }
-        return sessionDelegate;
-    }
-
-    public void registerInvalidation(RealmAdapter realm) {
-        realmInvalidations.add(realm.getId());
-    }
-
-    public void runInvalidations() {
-        for (String id : realmInvalidations) {
-            cache.invalidateCachedRealmById(id);
-        }
-
-    }
-
-    @Override
-    public KeycloakTransaction getTransaction() {
-        return new KeycloakTransaction() {
-            @Override
-            public void begin() {
-                transactionActive = true;
-            }
-
-            @Override
-            public void commit() {
-                if (sessionDelegate == null) return;
-                try {
-                    sessionDelegate.getTransaction().commit();
-                } finally {
-                    runInvalidations();
-                }
-            }
-
-            @Override
-            public void rollback() {
-                setRollbackOnly = true;
-                if (sessionDelegate == null) return;
-                try {
-                    sessionDelegate.getTransaction().commit();
-                } finally {
-                    runInvalidations();
-                }
-            }
-
-            @Override
-            public void setRollbackOnly() {
-                setRollbackOnly = true;
-                if (sessionDelegate == null) return;
-                sessionDelegate.getTransaction().setRollbackOnly();
-                setRollbackOnly = true;
-            }
-
-            @Override
-            public boolean getRollbackOnly() {
-                return setRollbackOnly;
-            }
-
-            @Override
-            public boolean isActive() {
-                return transactionActive;
-            }
-        };
-    }
-
-    @Override
-    public RealmModel createRealm(String name) {
-        return getDelegate().createRealm(name);
-    }
-
-    @Override
-    public RealmModel createRealm(String id, String name) {
-        return getDelegate().createRealm(id, name);
-    }
-
-    @Override
-    public RealmModel getRealm(String id) {
-        CachedRealm cached = cache.getCachedRealm(id);
-        if (cached == null) {
-            RealmModel model = getDelegate().getRealm(id);
-            if (model == null) return null;
-            cached = new CachedRealm(cache, this, model);
-        }
-        return new RealmAdapter(cached, this);
-    }
-
-    @Override
-    public RealmModel getRealmByName(String name) {
-        CachedRealm cached = cache.getCachedRealmByName(name);
-        if (cached == null) {
-            RealmModel model = getDelegate().getRealmByName(name);
-            if (model == null) return null;
-            cached = new CachedRealm(cache, this, model);
-        }
-        return new RealmAdapter(cached, this);
-    }
-
-    @Override
-    public UserModel getUserById(String id, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public UserModel getUserByUsername(String username, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public UserModel getUserByEmail(String email, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public List<RealmModel> getRealms() {
-        // we don't cache this for now
-        return getDelegate().getRealms();
-    }
-
-    @Override
-    public boolean removeRealm(String id) {
-        cache.invalidateCachedRealmById(id);
-        boolean didIt = getDelegate().removeRealm(id);
-        realmInvalidations.add(id);
-
-        return didIt;
-    }
-
-    @Override
-    public void removeAllData() {
-        cache.clear();
-        getDelegate().removeAllData();
-        clearAll = true;
-    }
-
-    @Override
-    public void close() {
-        if (sessionDelegate != null) sessionDelegate.close();
-    }
-
-    @Override
-    public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public List<UserModel> getUsers(RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public List<UserModel> searchForUser(String search, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public Set<SocialLinkModel> getSocialLinks(UserModel user, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public RoleModel getRoleById(String id, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public ApplicationModel getApplicationById(String id, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public OAuthClientModel getOAuthClientById(String id, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public UsernameLoginFailureModel getUserLoginFailure(String username, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public UsernameLoginFailureModel addUserLoginFailure(String username, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public List<UsernameLoginFailureModel> getAllUserLoginFailures(RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public UserSessionModel createUserSession(RealmModel realm, UserModel user, String ipAddress) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public UserSessionModel getUserSession(String id, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public List<UserSessionModel> getUserSessions(UserModel user, RealmModel realm) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public Set<UserSessionModel> getUserSessions(RealmModel realm, ClientModel client) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public int getActiveUserSessions(RealmModel realm, ClientModel client) {
-        return 0;  //To change body of implemented methods use File | Settings | File Templates.
-    }
+public interface CacheKeycloakSession extends KeycloakSession {
+    KeycloakSession getDelegate();
 
-    @Override
-    public void removeUserSession(UserSessionModel session) {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
+    void registerRealmInvalidation(String id);
 
-    @Override
-    public void removeUserSessions(RealmModel realm, UserModel user) {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
+    void registerApplicationInvalidation(String id);
 
-    @Override
-    public void removeExpiredUserSessions(RealmModel realm) {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
+    void registerRoleInvalidation(String id);
 
-    @Override
-    public void removeUserSessions(RealmModel realm) {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
+    void registerOAuthClientInvalidation(String id);
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSessionFactory.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSessionFactory.java
new file mode 100755
index 0000000..2b6c05c
--- /dev/null
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSessionFactory.java
@@ -0,0 +1,13 @@
+package org.keycloak.models.cache;
+
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.ProviderSession;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface CacheKeycloakSessionFactory extends ProviderFactory<CacheKeycloakSession> {
+    CacheKeycloakSession create(ProviderSession providerSession);
+    void close();
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSessionSpi.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSessionSpi.java
new file mode 100755
index 0000000..f0b53a4
--- /dev/null
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSessionSpi.java
@@ -0,0 +1,27 @@
+package org.keycloak.models.cache;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CacheKeycloakSessionSpi implements Spi {
+
+    @Override
+    public String getName() {
+        return "cacheKeycloakSession";
+    }
+
+    @Override
+    public Class<? extends Provider> getProviderClass() {
+        return CacheKeycloakSession.class;
+    }
+
+    @Override
+    public Class<? extends ProviderFactory> getProviderFactoryClass() {
+        return CacheKeycloakSessionFactory.class;
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheKeycloakSession.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheKeycloakSession.java
new file mode 100755
index 0000000..b4f6376
--- /dev/null
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheKeycloakSession.java
@@ -0,0 +1,404 @@
+package org.keycloak.models.cache;
+
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakTransaction;
+import org.keycloak.models.OAuthClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.SocialLinkModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.UsernameLoginFailureModel;
+import org.keycloak.models.cache.entities.CachedApplication;
+import org.keycloak.models.cache.entities.CachedApplicationRole;
+import org.keycloak.models.cache.entities.CachedOAuthClient;
+import org.keycloak.models.cache.entities.CachedRealm;
+import org.keycloak.models.cache.entities.CachedRealmRole;
+import org.keycloak.models.cache.entities.CachedRole;
+import org.keycloak.provider.ProviderSession;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class DefaultCacheKeycloakSession implements CacheKeycloakSession {
+    protected KeycloakCache cache;
+    protected ProviderSession providerSession;
+    protected KeycloakSession sessionDelegate;
+    protected KeycloakTransaction transactionDelegate;
+    protected boolean transactionActive;
+    protected boolean setRollbackOnly;
+
+    protected Set<String> realmInvalidations = new HashSet<String>();
+    protected Set<String> appInvalidations = new HashSet<String>();
+    protected Set<String> roleInvalidations = new HashSet<String>();
+    protected Set<String> clientInvalidations = new HashSet<String>();
+    protected Map<String, RealmModel> managedRealms = new HashMap<String, RealmModel>();
+    protected Map<String, ApplicationModel> managedApplications = new HashMap<String, ApplicationModel>();
+    protected Map<String, OAuthClientModel> managedClients = new HashMap<String, OAuthClientModel>();
+    protected Map<String, RoleModel> managedRoles = new HashMap<String, RoleModel>();
+
+    protected boolean clearAll;
+
+    public DefaultCacheKeycloakSession(KeycloakCache cache, ProviderSession providerSession) {
+        this.cache = cache;
+        this.providerSession = providerSession;
+    }
+
+    @Override
+    public KeycloakSession getDelegate() {
+        if (!transactionActive) throw new IllegalStateException("Cannot access delegate without a transaction");
+        if (sessionDelegate != null) return sessionDelegate;
+        sessionDelegate = providerSession.getProvider(KeycloakSession.class);
+        transactionDelegate = sessionDelegate.getTransaction();
+        if (!transactionDelegate.isActive()) {
+            transactionDelegate.begin();
+            if (setRollbackOnly) {
+                transactionDelegate.setRollbackOnly();
+            }
+        }
+        return sessionDelegate;
+    }
+
+    @Override
+    public void registerRealmInvalidation(String id) {
+        realmInvalidations.add(id);
+    }
+
+    @Override
+    public void registerApplicationInvalidation(String id) {
+        appInvalidations.add(id);
+    }
+
+    @Override
+    public void registerRoleInvalidation(String id) {
+        roleInvalidations.add(id);
+    }
+
+    @Override
+    public void registerOAuthClientInvalidation(String id) {
+        clientInvalidations.add(id);
+    }
+
+    protected void runInvalidations() {
+        for (String id : realmInvalidations) {
+            cache.invalidateCachedRealmById(id);
+        }
+        for (String id : roleInvalidations) {
+            cache.invalidateRoleById(id);
+        }
+        for (String id : appInvalidations) {
+            cache.invalidateCachedApplicationById(id);
+        }
+        for (String id : clientInvalidations) {
+            cache.invalidateCachedOAuthClientById(id);
+        }
+
+    }
+
+    @Override
+    public KeycloakTransaction getTransaction() {
+        return new KeycloakTransaction() {
+            @Override
+            public void begin() {
+                transactionActive = true;
+            }
+
+            @Override
+            public void commit() {
+                if (sessionDelegate == null) return;
+                try {
+                    sessionDelegate.getTransaction().commit();
+                    if (clearAll) {
+                        cache.clear();
+                    }
+                } finally {
+                    runInvalidations();
+                }
+            }
+
+            @Override
+            public void rollback() {
+                setRollbackOnly = true;
+                if (sessionDelegate == null) return;
+                try {
+                    sessionDelegate.getTransaction().rollback();
+                } finally {
+                    runInvalidations();
+                }
+            }
+
+            @Override
+            public void setRollbackOnly() {
+                setRollbackOnly = true;
+                if (sessionDelegate == null) return;
+                sessionDelegate.getTransaction().setRollbackOnly();
+                setRollbackOnly = true;
+            }
+
+            @Override
+            public boolean getRollbackOnly() {
+                return setRollbackOnly;
+            }
+
+            @Override
+            public boolean isActive() {
+                return transactionActive;
+            }
+        };
+    }
+
+    @Override
+    public RealmModel createRealm(String name) {
+        RealmModel realm = getDelegate().createRealm(name);
+        registerRealmInvalidation(realm.getId());
+        return realm;
+    }
+
+    @Override
+    public RealmModel createRealm(String id, String name) {
+        RealmModel realm =  getDelegate().createRealm(id, name);
+        registerRealmInvalidation(realm.getId());
+        return realm;
+    }
+
+    @Override
+    public RealmModel getRealm(String id) {
+        CachedRealm cached = cache.getCachedRealm(id);
+        if (cached == null) {
+            RealmModel model = getDelegate().getRealm(id);
+            if (model == null) return null;
+            if (realmInvalidations.contains(id)) return model;
+            cached = new CachedRealm(cache, this, model);
+            cache.addCachedRealm(cached);
+        } else if (realmInvalidations.contains(id)) {
+            return getDelegate().getRealm(id);
+        } else if (managedRealms.containsKey(id)) {
+            return managedRealms.get(id);
+        }
+        RealmAdapter adapter = new RealmAdapter(cached, this);
+        managedRealms.put(id, adapter);
+        return adapter;
+    }
+
+    @Override
+    public RealmModel getRealmByName(String name) {
+        CachedRealm cached = cache.getCachedRealmByName(name);
+        if (cached == null) {
+            RealmModel model = getDelegate().getRealmByName(name);
+            if (model == null) return null;
+            if (realmInvalidations.contains(model.getId())) return model;
+            cached = new CachedRealm(cache, this, model);
+            cache.addCachedRealm(cached);
+        } else if (realmInvalidations.contains(cached.getId())) {
+            return getDelegate().getRealmByName(name);
+        } else if (managedRealms.containsKey(cached.getId())) {
+            return managedRealms.get(cached.getId());
+        }
+        RealmAdapter adapter = new RealmAdapter(cached, this);
+        managedRealms.put(cached.getId(), adapter);
+        return adapter;
+    }
+
+    @Override
+    public UserModel getUserById(String id, RealmModel realm) {
+        return getDelegate().getUserById(id, realm);
+    }
+
+    @Override
+    public UserModel getUserByUsername(String username, RealmModel realm) {
+        return getDelegate().getUserByUsername(username, realm);
+    }
+
+    @Override
+    public UserModel getUserByEmail(String email, RealmModel realm) {
+        return getDelegate().getUserByEmail(email, realm);
+    }
+
+    @Override
+    public List<RealmModel> getRealms() {
+        // we don't cache this for now
+        return getDelegate().getRealms();
+    }
+
+    @Override
+    public boolean removeRealm(String id) {
+        cache.invalidateCachedRealmById(id);
+        boolean didIt = getDelegate().removeRealm(id);
+        realmInvalidations.add(id);
+
+        return didIt;
+    }
+
+    @Override
+    public void removeAllData() {
+        cache.clear();
+        getDelegate().removeAllData();
+        clearAll = true;
+    }
+
+    @Override
+    public void close() {
+        if (sessionDelegate != null) sessionDelegate.close();
+    }
+
+    @Override
+    public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) {
+        return getDelegate().getUserBySocialLink(socialLink, realm);
+    }
+
+    @Override
+    public List<UserModel> getUsers(RealmModel realm) {
+        return getDelegate().getUsers(realm);
+    }
+
+    @Override
+    public List<UserModel> searchForUser(String search, RealmModel realm) {
+        return getDelegate().searchForUser(search, realm);
+    }
+
+    @Override
+    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
+        return getDelegate().searchForUserByAttributes(attributes, realm);
+    }
+
+    @Override
+    public Set<SocialLinkModel> getSocialLinks(UserModel user, RealmModel realm) {
+        return getDelegate().getSocialLinks(user, realm);
+    }
+
+    @Override
+    public SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm) {
+        return getDelegate().getSocialLink(user, socialProvider, realm);
+    }
+
+    @Override
+    public RoleModel getRoleById(String id, RealmModel realm) {
+        CachedRole cached = cache.getRole(id);
+        if (cached == null) {
+            RoleModel model = getDelegate().getRoleById(id, realm);
+            if (model == null) return null;
+            if (roleInvalidations.contains(id)) return model;
+            if (model.getContainer() instanceof ApplicationModel) {
+                cached = new CachedApplicationRole(((ApplicationModel) model.getContainer()).getId(), model);
+            } else {
+                cached = new CachedRealmRole(model);
+            }
+            cache.addCachedRole(cached);
+
+        } else if (roleInvalidations.contains(id)) {
+            return getDelegate().getRoleById(id, realm);
+        } else if (managedRoles.containsKey(id)) {
+            return managedRoles.get(id);
+        }
+        RoleAdapter adapter = new RoleAdapter(cached, cache, this, realm);
+        managedRoles.put(id, adapter);
+        return adapter;
+    }
+
+    @Override
+    public ApplicationModel getApplicationById(String id, RealmModel realm) {
+        CachedApplication cached = cache.getApplication(id);
+        if (cached == null) {
+            ApplicationModel model = getDelegate().getApplicationById(id, realm);
+            if (model == null) return null;
+            if (appInvalidations.contains(id)) return model;
+            cached = new CachedApplication(cache, getDelegate(), realm, model);
+            cache.addCachedApplication(cached);
+        } else if (appInvalidations.contains(id)) {
+            return getDelegate().getApplicationById(id, realm);
+        } else if (managedApplications.containsKey(id)) {
+            return managedApplications.get(id);
+        }
+        ApplicationAdapter adapter = new ApplicationAdapter(realm, cached, this, cache);
+        managedApplications.put(id, adapter);
+        return adapter;
+    }
+
+    @Override
+    public OAuthClientModel getOAuthClientById(String id, RealmModel realm) {
+        CachedOAuthClient cached = cache.getOAuthClient(id);
+        if (cached == null) {
+            OAuthClientModel model = getDelegate().getOAuthClientById(id, realm);
+            if (model == null) return null;
+            if (clientInvalidations.contains(id)) return model;
+            cached = new CachedOAuthClient(cache, getDelegate(), realm, model);
+            cache.addCachedOAuthClient(cached);
+        } else if (clientInvalidations.contains(id)) {
+            return getDelegate().getOAuthClientById(id, realm);
+        } else if (managedClients.containsKey(id)) {
+            return managedClients.get(id);
+        }
+        OAuthClientAdapter adapter = new OAuthClientAdapter(realm, cached, this, cache);
+        managedClients.put(id, adapter);
+        return adapter;
+    }
+
+    @Override
+    public UsernameLoginFailureModel getUserLoginFailure(String username, RealmModel realm) {
+        return getDelegate().getUserLoginFailure(username, realm);
+    }
+
+    @Override
+    public UsernameLoginFailureModel addUserLoginFailure(String username, RealmModel realm) {
+        return getDelegate().addUserLoginFailure(username, realm);
+    }
+
+    @Override
+    public List<UsernameLoginFailureModel> getAllUserLoginFailures(RealmModel realm) {
+        return getDelegate().getAllUserLoginFailures(realm);
+    }
+
+    @Override
+    public UserSessionModel createUserSession(RealmModel realm, UserModel user, String ipAddress) {
+        return getDelegate().createUserSession(realm, user, ipAddress);
+    }
+
+    @Override
+    public UserSessionModel getUserSession(String id, RealmModel realm) {
+        return getDelegate().getUserSession(id, realm);
+    }
+
+    @Override
+    public List<UserSessionModel> getUserSessions(UserModel user, RealmModel realm) {
+        return getDelegate().getUserSessions(user, realm);
+    }
+
+    @Override
+    public Set<UserSessionModel> getUserSessions(RealmModel realm, ClientModel client) {
+        return getDelegate().getUserSessions(realm, client);
+    }
+
+    @Override
+    public int getActiveUserSessions(RealmModel realm, ClientModel client) {
+        return getDelegate().getActiveUserSessions(realm, client);
+    }
+
+    @Override
+    public void removeUserSession(UserSessionModel session) {
+        getDelegate().removeUserSession(session);
+    }
+
+    @Override
+    public void removeUserSessions(RealmModel realm, UserModel user) {
+        getDelegate().removeUserSessions(realm, user);
+    }
+
+    @Override
+    public void removeExpiredUserSessions(RealmModel realm) {
+        getDelegate().removeExpiredUserSessions(realm);
+    }
+
+    @Override
+    public void removeUserSessions(RealmModel realm) {
+        getDelegate().removeUserSessions(realm);
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/KeycloakCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/KeycloakCache.java
index 52d7094..20ad44b 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/KeycloakCache.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/KeycloakCache.java
@@ -47,4 +47,5 @@ public interface KeycloakCache {
     void invalidateCachedRoleById(String id);
 
 
+    void invalidateRoleById(String id);
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/OAuthClientAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/OAuthClientAdapter.java
index 73ffa70..cc6d3d6 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/OAuthClientAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/OAuthClientAdapter.java
@@ -29,6 +29,7 @@ public class OAuthClientAdapter extends ClientAdapter implements OAuthClientMode
     @Override
     protected void getDelegateForUpdate() {
         if (updated == null) {
+            cacheSession.registerOAuthClientInvalidation(getId());
             updatedClient = updated = cacheSession.getDelegate().getOAuthClientById(getId(), cachedRealm);
             if (updated == null) throw new IllegalStateException("Not found in database");
         }
@@ -45,4 +46,19 @@ public class OAuthClientAdapter extends ClientAdapter implements OAuthClientMode
         getDelegateForUpdate();
         updated.setClientId(id);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof OAuthClientModel)) return false;
+
+        OAuthClientModel that = (OAuthClientModel) o;
+
+        return that.getId().equals(this.getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
index 0440f6d..5dc2539 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
@@ -52,6 +52,7 @@ public class RealmAdapter implements RealmModel {
 
     protected void getDelegateForUpdate() {
         if (updated == null) {
+            cacheSession.registerRealmInvalidation(getId());
             updated = cacheSession.getDelegate().getRealm(getId());
             if (updated == null) throw new IllegalStateException("Not found in database");
         }
@@ -440,20 +441,8 @@ public class RealmAdapter implements RealmModel {
     @Override
     public RoleModel getRoleById(String id) {
         if (updated != null) return updated.getRoleById(id);
-        if (!cached.getRolesById().contains(id)) return null;
-        CachedRole cachedRole = cache.getRole(id);
-        if (cachedRole == null) {
-            RoleModel roleModel = cacheSession.getDelegate().getRoleById(id, this);
-            if (roleModel == null) return null;
-            if (roleModel.getContainer() instanceof ApplicationModel) {
-                cachedRole = new CachedApplicationRole(((ApplicationModel) roleModel.getContainer()).getId(), roleModel);
-                cache.addCachedRole(cachedRole);
-            } else {
-                cachedRole = new CachedRealmRole(roleModel);
-            }
-        }
-        return new RoleAdapter(cachedRole, cache, cacheSession, this);
-    }
+        return cacheSession.getRoleById(id, this);
+     }
 
     @Override
     public List<String> getDefaultRoles() {
@@ -519,17 +508,22 @@ public class RealmAdapter implements RealmModel {
     @Override
     public ApplicationModel addApplication(String name) {
         getDelegateForUpdate();
-        return updated.addApplication(name);
+        ApplicationModel app = updated.addApplication(name);
+        cacheSession.registerApplicationInvalidation(app.getId());
+        return app;
     }
 
     @Override
     public ApplicationModel addApplication(String id, String name) {
         getDelegateForUpdate();
-        return updated.addApplication(id, name);
+        ApplicationModel app =  updated.addApplication(id, name);
+        cacheSession.registerApplicationInvalidation(app.getId());
+        return app;
     }
 
     @Override
     public boolean removeApplication(String id) {
+        cacheSession.registerApplicationInvalidation(id);
         getDelegateForUpdate();
         return updated.removeApplication(id);
     }
@@ -629,13 +623,17 @@ public class RealmAdapter implements RealmModel {
     @Override
     public OAuthClientModel addOAuthClient(String name) {
         getDelegateForUpdate();
-        return updated.addOAuthClient(name);
+        OAuthClientModel client = updated.addOAuthClient(name);
+        cacheSession.registerOAuthClientInvalidation(client.getId());
+        return client;
     }
 
     @Override
     public OAuthClientModel addOAuthClient(String id, String name) {
         getDelegateForUpdate();
-        return updated.addOAuthClient(id, name);
+        OAuthClientModel client =  updated.addOAuthClient(id, name);
+        cacheSession.registerOAuthClientInvalidation(client.getId());
+        return client;
     }
 
     @Override
@@ -654,6 +652,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean removeOAuthClient(String id) {
+        cacheSession.registerOAuthClientInvalidation(id);
         getDelegateForUpdate();
         return updated.removeOAuthClient(id);
     }
@@ -782,6 +781,7 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean removeRoleById(String id) {
+        cacheSession.registerRoleInvalidation(id);
         getDelegateForUpdate();
         return updated.removeRoleById(id);
     }
@@ -845,17 +845,22 @@ public class RealmAdapter implements RealmModel {
     @Override
     public RoleModel addRole(String name) {
         getDelegateForUpdate();
-        return updated.addRole(name);
+        RoleModel role = updated.addRole(name);
+        cacheSession.registerRoleInvalidation(role.getId());
+        return role;
     }
 
     @Override
     public RoleModel addRole(String id, String name) {
         getDelegateForUpdate();
-        return updated.addRole(id, name);
+        RoleModel role =  updated.addRole(id, name);
+        cacheSession.registerRoleInvalidation(role.getId());
+        return role;
     }
 
     @Override
     public boolean removeRole(RoleModel role) {
+        cacheSession.registerRoleInvalidation(role.getId());
         getDelegateForUpdate();
         return updated.removeRole(role);
     }
@@ -866,7 +871,9 @@ public class RealmAdapter implements RealmModel {
 
         Set<RoleModel> roles = new HashSet<RoleModel>();
         for (String id : cached.getRealmRoles().values()) {
-            roles.add(cacheSession.getRoleById(id, this));
+            RoleModel roleById = cacheSession.getRoleById(id, this);
+            if (roleById == null) continue;
+            roles.add(roleById);
         }
         return roles;
     }
@@ -958,7 +965,7 @@ public class RealmAdapter implements RealmModel {
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
-        if (!(o instanceof RealmModel)) return false;
+        if (o == null || !(o instanceof RealmModel)) return false;
 
         RealmModel that = (RealmModel) o;
         return that.getId().equals(getId());
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java
index a7f8890..06bb610 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java
@@ -32,6 +32,7 @@ public class RoleAdapter implements RoleModel {
 
     protected void getDelegateForUpdate() {
         if (updated == null) {
+            cacheSession.registerRoleInvalidation(getId());
             updated = cacheSession.getDelegate().getRoleById(getId(), realm);
             if (updated == null) throw new IllegalStateException("Not found in database");
         }
@@ -118,4 +119,19 @@ public class RoleAdapter implements RoleModel {
         Set<RoleModel> visited = new HashSet<RoleModel>();
         return KeycloakModelUtils.searchFor(role, this, visited);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof RoleModel)) return false;
+
+        RoleModel that = (RoleModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCache.java
index 317b351..69bd613 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCache.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCache.java
@@ -23,11 +23,17 @@ public class SimpleCache implements KeycloakCache {
 
     protected ConcurrentHashMap<String, CachedRealm> realmCache = new ConcurrentHashMap<String, CachedRealm>();
     protected ConcurrentHashMap<String, CachedRealm> realmCacheByName = new ConcurrentHashMap<String, CachedRealm>();
+    protected ConcurrentHashMap<String, CachedApplication> applicationCache = new ConcurrentHashMap<String, CachedApplication>();
+    protected ConcurrentHashMap<String, CachedOAuthClient> clientCache = new ConcurrentHashMap<String, CachedOAuthClient>();
+    protected ConcurrentHashMap<String, CachedRole> roleCache = new ConcurrentHashMap<String, CachedRole>();
 
     @Override
     public void clear() {
         realmCache.clear();
         realmCacheByName.clear();
+        applicationCache.clear();
+        clientCache.clear();
+        roleCache.clear();
     }
 
     @Override
@@ -51,7 +57,7 @@ public class SimpleCache implements KeycloakCache {
     @Override
     public void addCachedRealm(CachedRealm realm) {
         realmCache.put(realm.getId(), realm);
-        realmCache.put(realm.getName(), realm);
+        realmCacheByName.put(realm.getName(), realm);
 
     }
 
@@ -62,61 +68,66 @@ public class SimpleCache implements KeycloakCache {
 
     @Override
     public CachedApplication getApplication(String id) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+        return applicationCache.get(id);
     }
 
     @Override
     public void invalidateApplication(CachedApplication app) {
-        //To change body of implemented methods use File | Settings | File Templates.
+        applicationCache.remove(app.getId());
     }
 
     @Override
     public void addCachedApplication(CachedApplication app) {
-        //To change body of implemented methods use File | Settings | File Templates.
+        applicationCache.put(app.getId(), app);
     }
 
     @Override
     public void invalidateCachedApplicationById(String id) {
-        //To change body of implemented methods use File | Settings | File Templates.
+        applicationCache.remove(id);
     }
 
     @Override
     public CachedOAuthClient getOAuthClient(String id) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+        return clientCache.get(id);
     }
 
     @Override
     public void invalidateOAuthClient(CachedOAuthClient client) {
-        //To change body of implemented methods use File | Settings | File Templates.
+        clientCache.remove(client.getId());
     }
 
     @Override
     public void addCachedOAuthClient(CachedOAuthClient client) {
-        //To change body of implemented methods use File | Settings | File Templates.
+        clientCache.put(client.getId(), client);
     }
 
     @Override
     public void invalidateCachedOAuthClientById(String id) {
-        //To change body of implemented methods use File | Settings | File Templates.
+        clientCache.remove(id);
     }
 
     @Override
     public CachedRole getRole(String id) {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+        return roleCache.get(id);
     }
 
     @Override
     public void invalidateRole(CachedRole role) {
-        //To change body of implemented methods use File | Settings | File Templates.
+        roleCache.remove(role);
+    }
+
+    @Override
+    public void invalidateRoleById(String id) {
+        roleCache.remove(id);
     }
 
     @Override
     public void addCachedRole(CachedRole role) {
-        //To change body of implemented methods use File | Settings | File Templates.
+        roleCache.put(role.getId(), role);
     }
 
     @Override
     public void invalidateCachedRoleById(String id) {
-        //To change body of implemented methods use File | Settings | File Templates.
+        roleCache.remove(id);
     }
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCacheKeycloakSessionFactory.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCacheKeycloakSessionFactory.java
new file mode 100755
index 0000000..8836732
--- /dev/null
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCacheKeycloakSessionFactory.java
@@ -0,0 +1,32 @@
+package org.keycloak.models.cache;
+
+import org.keycloak.Config;
+import org.keycloak.provider.ProviderSession;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SimpleCacheKeycloakSessionFactory implements CacheKeycloakSessionFactory {
+    protected KeycloakCache cache = new SimpleCache();
+
+    @Override
+    public CacheKeycloakSession create(ProviderSession providerSession) {
+        return new DefaultCacheKeycloakSession(cache, providerSession);
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+    @Override
+    public void close() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public String getId() {
+        return "simple";
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheKeycloakSessionFactory b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheKeycloakSessionFactory
new file mode 100755
index 0000000..0cf4453
--- /dev/null
+++ b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheKeycloakSessionFactory
@@ -0,0 +1 @@
+org.keycloak.models.cache.SimpleCacheKeycloakSessionFactory
\ No newline at end of file
diff --git a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.provider.Spi
new file mode 100755
index 0000000..6460d62
--- /dev/null
+++ b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -0,0 +1 @@
+org.keycloak.models.cache.CacheKeycloakSessionSpi
\ No newline at end of file
diff --git a/model/jpa/pom.xml b/model/jpa/pom.xml
index cda40e8..4c7e269 100755
--- a/model/jpa/pom.xml
+++ b/model/jpa/pom.xml
@@ -36,6 +36,12 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-invalidation-cache-model</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.hibernate.javax.persistence</groupId>
             <artifactId>hibernate-jpa-2.0-api</artifactId>
             <scope>provided</scope>
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java
index 31574ee..36ea182 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java
@@ -131,7 +131,7 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode
     @Override
     public boolean removeRole(RoleModel roleModel) {
         RoleAdapter roleAdapter = (RoleAdapter)roleModel;
-        if (roleAdapter == null) {
+        if (roleModel == null) {
             return false;
         }
         if (!roleAdapter.getContainer().equals(this)) return false;
@@ -142,13 +142,13 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode
 
         applicationEntity.getRoles().remove(role);
         applicationEntity.getDefaultRoles().remove(role);
-
         em.createNativeQuery("delete from CompositeRole where role = :role").setParameter("role", role).executeUpdate();
         em.createQuery("delete from " + ScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
         em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate();
         role.setApplication(null);
         em.flush();
         em.remove(role);
+        em.flush();
 
         return true;
     }
@@ -244,12 +244,18 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode
         em.flush();
     }
 
+    @Override
     public boolean equals(Object o) {
-        if (o == null) return false;
-        if (o == this) return true;
-        if (!(o instanceof ApplicationAdapter)) return false;
-        ApplicationAdapter app = (ApplicationAdapter)o;
-        return app.getId().equals(getId());
+        if (this == o) return true;
+        if (o == null || !(o instanceof ApplicationModel)) return false;
+
+        ApplicationModel that = (ApplicationModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
     }
 
     public String toString() {
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
index f8bc8f6..08476ef 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
@@ -204,6 +204,7 @@ public abstract class ClientAdapter implements ClientModel {
         Set<RoleModel> roles = new HashSet<RoleModel>();
         for (ScopeMappingEntity entity : entities) {
             roles.add(new RoleAdapter(realm, em, entity.getRole()));
+            em.detach(entity);
         }
         return roles;
     }
@@ -215,6 +216,8 @@ public abstract class ClientAdapter implements ClientModel {
         entity.setClient(getEntity());
         entity.setRole(((RoleAdapter) role).getRole());
         em.persist(entity);
+        em.flush();
+        em.detach(entity);
     }
 
     @Override
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
index 96ac2c9..9367d25 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
@@ -38,7 +38,7 @@ public abstract class ClientEntity {
     private int notBefore;
     private boolean publicClient;
 
-    @ManyToOne
+    @ManyToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "realm")
     protected RealmEntity realm;
 
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java
index e42eefe..e18c2f8 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java
@@ -1,6 +1,7 @@
 package org.keycloak.models.jpa.entities;
 
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
@@ -28,7 +29,7 @@ public class CredentialEntity {
     protected String device;
     protected byte[] salt;
 
-    @ManyToOne
+    @ManyToOne(fetch = FetchType.LAZY)
     protected UserEntity user;
 
     public String getValue() {
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ScopeMappingEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ScopeMappingEntity.java
index 4709030..8e19898 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ScopeMappingEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ScopeMappingEntity.java
@@ -3,6 +3,7 @@ package org.keycloak.models.jpa.entities;
 import org.hibernate.annotations.GenericGenerator;
 
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
@@ -23,9 +24,9 @@ public class ScopeMappingEntity {
     @GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
     @GeneratedValue(generator = "keycloak_generator")
     protected String id;
-    @ManyToOne
+    @ManyToOne(fetch= FetchType.LAZY)
     protected ClientEntity client;
-    @ManyToOne
+    @ManyToOne(fetch= FetchType.LAZY)
     protected RoleEntity role;
 
     public String getId() {
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/SocialLinkEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/SocialLinkEntity.java
index 84db8f6..a1de3af 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/SocialLinkEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/SocialLinkEntity.java
@@ -1,6 +1,7 @@
 package org.keycloak.models.jpa.entities;
 
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
@@ -25,10 +26,10 @@ public class SocialLinkEntity {
     @GeneratedValue(generator = "keycloak_generator")
     private String id;
 
-    @ManyToOne
+    @ManyToOne(fetch = FetchType.LAZY)
     private UserEntity user;
 
-    @ManyToOne
+    @ManyToOne(fetch = FetchType.LAZY)
     protected RealmEntity realm;
 
     protected String socialProvider;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
index 39d03a4..d873901 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
@@ -8,6 +8,7 @@ import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
@@ -57,7 +58,7 @@ public class UserEntity {
     protected int notBefore;
 
 
-    @ManyToOne
+    @ManyToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "realm")
     protected RealmEntity realm;
 
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UsernameLoginFailureEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UsernameLoginFailureEntity.java
index e3336e0..f3cffb4 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UsernameLoginFailureEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UsernameLoginFailureEntity.java
@@ -1,6 +1,7 @@
 package org.keycloak.models.jpa.entities;
 
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
@@ -26,7 +27,7 @@ public class UsernameLoginFailureEntity {
     protected String lastIPFailure;
 
 
-    @ManyToOne
+    @ManyToOne(fetch = FetchType.LAZY)
     protected RealmEntity realm;
 
     public String getId() {
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java
index e6a62af..c890c9f 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java
@@ -1,5 +1,6 @@
 package org.keycloak.models.jpa;
 
+import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
@@ -37,4 +38,19 @@ public class OAuthClientAdapter extends ClientAdapter implements OAuthClientMode
     public void setDirectGrantsOnly(boolean flag) {
         oAuthClientEntity.setDirectGrantsOnly(flag);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof OAuthClientModel)) return false;
+
+        OAuthClientModel that = (OAuthClientModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 89ab556..fb92f14 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -1001,11 +1001,18 @@ public class RealmAdapter implements RealmModel {
         em.flush();
     }
 
+    @Override
     public boolean equals(Object o) {
-        if (o == null) return false;
-        if (!(o instanceof RealmAdapter)) return false;
-        RealmAdapter r = (RealmAdapter) o;
-        return r.getId().equals(getId());
+        if (this == o) return true;
+        if (o == null || !(o instanceof RealmModel)) return false;
+
+        RealmModel that = (RealmModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
     }
 
     @Override
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
index c947c8f..ba4d136 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
@@ -1,5 +1,6 @@
 package org.keycloak.models.jpa;
 
+import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
@@ -115,17 +116,14 @@ public class RoleAdapter implements RoleModel {
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
+        if (o == null || !(o instanceof RoleModel)) return false;
 
-        RoleAdapter that = (RoleAdapter) o;
-
-        if (!role.getId().equals(that.role.getId())) return false;
-
-        return true;
+        RoleModel that = (RoleModel) o;
+        return that.getId().equals(getId());
     }
 
     @Override
     public int hashCode() {
-        return role.getId().hashCode();
+        return getId().hashCode();
     }
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
index f7eb178..586180e 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
@@ -282,6 +282,7 @@ public class UserAdapter implements UserModel {
         entity.setRole(roleEntity);
         em.persist(entity);
         em.flush();
+        em.detach(entity);
     }
 
     @Override
@@ -307,6 +308,7 @@ public class UserAdapter implements UserModel {
         Set<RoleModel> roles = new HashSet<RoleModel>();
         for (UserRoleMappingEntity entity : entities) {
             roles.add(realm.getRoleById(entity.getRole().getId()));
+            em.detach(entity);
         }
         return roles;
     }
@@ -359,5 +361,20 @@ public class UserAdapter implements UserModel {
         em.flush();
     }
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof UserModel)) return false;
+
+        UserModel that = (UserModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+
 
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/UserSessionAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/UserSessionAdapter.java
index db22054..333f7d1 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/UserSessionAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/UserSessionAdapter.java
@@ -117,10 +117,10 @@ public class UserSessionAdapter implements UserSessionModel {
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
+        if (o == null || !(o instanceof UserSessionModel)) return false;
 
-        UserSessionAdapter that = (UserSessionAdapter) o;
-        return that.getId().equals(this.getId());
+        UserSessionModel that = (UserSessionModel) o;
+        return that.getId().equals(getId());
     }
 
     @Override
diff --git a/model/mongo/pom.xml b/model/mongo/pom.xml
index 7e8fcfb..eda284f 100755
--- a/model/mongo/pom.xml
+++ b/model/mongo/pom.xml
@@ -38,6 +38,12 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-invalidation-cache-model</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.jboss.logging</groupId>
             <artifactId>jboss-logging</artifactId>
             <scope>provided</scope>
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java
index 9569b3d..d2ab912 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java
@@ -8,6 +8,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity;
 import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
@@ -204,4 +205,19 @@ public class ApplicationAdapter extends ClientAdapter<MongoApplicationEntity> im
         updateMongoEntity();
     }
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof ApplicationModel)) return false;
+
+        ApplicationModel that = (ApplicationModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java
index c008aaa..0ebd713 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java
@@ -1,5 +1,6 @@
 package org.keycloak.models.mongo.keycloak.adapters;
 
+import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
@@ -30,4 +31,19 @@ public class OAuthClientAdapter extends ClientAdapter<MongoOAuthClientEntity> im
     public void setDirectGrantsOnly(boolean flag) {
         getMongoEntity().setDirectGrantsOnly(flag);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof OAuthClientModel)) return false;
+
+        OAuthClientModel that = (OAuthClientModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index 5c187c2..ecf5b76 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -1059,4 +1059,19 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
         this.session.removeExpiredUserSessions(this);
     }
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof RealmModel)) return false;
+
+        RealmModel that = (RealmModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java
index 6053df3..3eb9f0c 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java
@@ -145,4 +145,19 @@ public class RoleAdapter extends AbstractMongoAdapter<MongoRoleEntity> implement
     public MongoRoleEntity getMongoEntity() {
         return role;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof RoleModel)) return false;
+
+        RoleModel that = (RoleModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
index b26c50a..e582b93 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
@@ -351,14 +351,17 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
         getMongoStore().updateEntity(user, invocationContext);
     }
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof UserModel)) return false;
 
+        UserModel that = (UserModel) o;
+        return that.getId().equals(getId());
+    }
 
-
-
-
-
-
-
-
-
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserSessionAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserSessionAdapter.java
index 29e4b0d..ce9b175 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserSessionAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserSessionAdapter.java
@@ -126,4 +126,19 @@ public class UserSessionAdapter extends AbstractMongoAdapter<MongoUserSessionEnt
     public void removeAssociatedClient(ClientModel client) {
         getMongoStore().pullItemFromList(entity, "associatedClientIds", client.getId(), invocationContext);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof UserSessionModel)) return false;
+
+        UserSessionModel that = (UserSessionModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
 }

model/pom.xml 2(+1 -1)

diff --git a/model/pom.xml b/model/pom.xml
index db287b0..2d972fe 100755
--- a/model/pom.xml
+++ b/model/pom.xml
@@ -26,10 +26,10 @@
     </build>
     <modules>
         <module>api</module>
+        <module>invalidation-cache</module>
         <!-- <module>picketlink</module> -->
         <module>jpa</module>
         <module>mongo</module>
-        <module>invalidation-cache</module>
         <module>tests</module>
     </modules>
 </project>
diff --git a/model/tests/pom.xml b/model/tests/pom.xml
index 311f5e3..bfd2678 100755
--- a/model/tests/pom.xml
+++ b/model/tests/pom.xml
@@ -35,6 +35,12 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-invalidation-cache-model</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-authentication-api</artifactId>
             <version>${project.version}</version>
             <scope>compile</scope>
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java
index 428d4c8..5366d04 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AbstractModelTest.java
@@ -14,6 +14,8 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.Config;
+import org.keycloak.models.cache.CacheKeycloakSession;
+import org.keycloak.models.cache.SimpleCache;
 import org.keycloak.provider.ProviderSession;
 import org.keycloak.provider.ProviderSessionFactory;
 import org.keycloak.representations.idm.RealmRepresentation;
@@ -38,7 +40,7 @@ public class AbstractModelTest {
         providerSessionFactory = KeycloakApplication.createProviderSessionFactory();
 
         ProviderSession providerSession = providerSessionFactory.createSession();
-        KeycloakSession identitySession = providerSession.getProvider(KeycloakSession.class);
+        KeycloakSession identitySession = providerSession.getProvider(CacheKeycloakSession.class);
         try {
             identitySession.getTransaction().begin();
             new ApplianceBootstrap().bootstrap(identitySession, "/auth");
@@ -57,7 +59,7 @@ public class AbstractModelTest {
     public void before() throws Exception {
         providerSession = providerSessionFactory.createSession();
 
-        identitySession = providerSession.getProvider(KeycloakSession.class);
+        identitySession = providerSession.getProvider(CacheKeycloakSession.class);
         identitySession.getTransaction().begin();
         realmManager = new RealmManager(identitySession);
     }
@@ -68,7 +70,7 @@ public class AbstractModelTest {
         providerSession.close();
 
         providerSession = providerSessionFactory.createSession();
-        identitySession = providerSession.getProvider(KeycloakSession.class);
+        identitySession = providerSession.getProvider(CacheKeycloakSession.class);
         try {
             identitySession.getTransaction().begin();
 
@@ -103,7 +105,7 @@ public class AbstractModelTest {
         providerSession.close();
 
         providerSession = providerSessionFactory.createSession();
-        identitySession = providerSession.getProvider(KeycloakSession.class);
+        identitySession = providerSession.getProvider(CacheKeycloakSession.class);
         identitySession.getTransaction().begin();
         realmManager = new RealmManager(identitySession);
     }
diff --git a/model/tests/src/test/java/org/keycloak/model/test/ApplicationModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/ApplicationModelTest.java
index 05fbe78..f8869bc 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/ApplicationModelTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/ApplicationModelTest.java
@@ -51,7 +51,8 @@ public class ApplicationModelTest extends AbstractModelTest {
     public void persist() {
         RealmModel persisted = realmManager.getRealm(realm.getId());
 
-        assertEquals(application, persisted.getApplicationNameMap().get("app-name"));
+        ApplicationModel actual = persisted.getApplicationNameMap().get("app-name");
+        assertEquals(application, actual);
     }
 
     @Test
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersExternalModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersExternalModelTest.java
index bcd36fa..17674c4 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersExternalModelTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersExternalModelTest.java
@@ -40,7 +40,7 @@ public class AuthProvidersExternalModelTest extends AbstractModelTest {
 
     @Before
     @Override
-    public void  before() throws Exception {
+    public void before() throws Exception {
         super.before();
 
         // Create 2 realms and user in realm1

services/pom.xml 12(+12 -0)

diff --git a/services/pom.xml b/services/pom.xml
index b1606bc..9d9a564 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -69,6 +69,18 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-invalidation-cache-model</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-authentication-api</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-social-core</artifactId>
             <version>${project.version}</version>
             <scope>provided</scope>
diff --git a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
index 7ba261d..eba6113 100755
--- a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
+++ b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
@@ -2,8 +2,8 @@ package org.keycloak.services.filters;
 
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.KeycloakTransaction;
+import org.keycloak.models.cache.CacheKeycloakSession;
 import org.keycloak.provider.ProviderSession;
 import org.keycloak.provider.ProviderSessionFactory;
 
@@ -33,7 +33,7 @@ public class KeycloakSessionServletFilter implements Filter {
         HttpServletRequest request = (HttpServletRequest)servletRequest;
         ResteasyProviderFactory.pushContext(ProviderSession.class, providerSession);
 
-        KeycloakSession session = providerSession.getProvider(KeycloakSession.class);
+        KeycloakSession session = providerSession.getProvider(CacheKeycloakSession.class);
         ResteasyProviderFactory.pushContext(KeycloakSession.class, session);
         KeycloakTransaction tx = session.getTransaction();
         ResteasyProviderFactory.pushContext(KeycloakTransaction.class, tx);
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index 434df20..f7be0a8 100755
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -127,6 +127,11 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-invalidation-cache-model</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-timer-api</artifactId>
             <version>${project.version}</version>
         </dependency>
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/perf/AccessTokenPerfTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/perf/AccessTokenPerfTest.java
index c5d3a02..55a1c7a 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/perf/AccessTokenPerfTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/perf/AccessTokenPerfTest.java
@@ -234,10 +234,11 @@ public class AccessTokenPerfTest {
     @Test
     public void perfJaxrsClientLogin()
     {
-        long ITERATIONS = 100;
+        long ITERATIONS = 10;
         JaxrsClientLogin login = new JaxrsClientLogin();
         long start = System.currentTimeMillis();
         for (int i = 0; i < ITERATIONS; i++) {
+            System.out.println("*************************");
             login.run();
         }
         long end = System.currentTimeMillis() - start;
@@ -247,7 +248,7 @@ public class AccessTokenPerfTest {
     @Test
     public void perfBrowserLogin()
     {
-        long ITERATIONS = 100;
+        long ITERATIONS = 10;
         long start = System.currentTimeMillis();
         BrowserLogin login = new BrowserLogin();
         for (int i = 0; i < ITERATIONS; i++) {
@@ -259,7 +260,7 @@ public class AccessTokenPerfTest {
 
     @Test
     public void multiThread() throws Exception {
-        int num_threads = 20;
+        int num_threads = 10;
         Thread[] threads = new Thread[num_threads];
         for (int i = 0; i < num_threads; i++) {
             threads[i] = new Thread(new Runnable() {