keycloak-uncached

cache refactor

6/6/2014 4:12:58 PM

Changes

Details

diff --git a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/AbstractModelAuthenticationProvider.java b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/AbstractModelAuthenticationProvider.java
old mode 100644
new mode 100755
index 5c6b834..730f3f4
--- a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/AbstractModelAuthenticationProvider.java
+++ b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/AbstractModelAuthenticationProvider.java
@@ -66,7 +66,7 @@ public abstract class AbstractModelAuthenticationProvider implements Authenticat
         cred.setType(CredentialRepresentation.PASSWORD);
         cred.setValue(password);
 
-        realm.updateCredential(user, cred);
+        user.updateCredential(cred);
         return true;
     }
 
diff --git a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelExporter.java b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelExporter.java
index cdfdcab..660ce10 100755
--- a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelExporter.java
+++ b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelExporter.java
@@ -255,7 +255,7 @@ public class ModelExporter {
                 userEntity.setRoleIds(roleIds);
 
                 // credentials
-                List<UserCredentialValueModel> credentials = realm.getCredentialsDirectly(userModel);
+                List<UserCredentialValueModel> credentials = userModel.getCredentialsDirectly();
                 List<CredentialEntity> credEntities = new ArrayList<CredentialEntity>();
                 for (UserCredentialValueModel credModel : credentials) {
                     CredentialEntity credEntity = new CredentialEntity();
diff --git a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java
index be78099..0bfbd4d 100755
--- a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java
+++ b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java
@@ -302,7 +302,7 @@ public class ModelImporter {
                     UserCredentialValueModel credModel = new UserCredentialValueModel();
                     this.propertiesManager.setBasicPropertiesToModel(credModel, credEntity);
 
-                    realm.updateCredentialDirectly(user, credModel);
+                    user.updateCredentialDirectly(credModel);
                 }
             }
         }
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
index aa61bec..a99a09e 100755
--- a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
@@ -15,6 +15,9 @@ public interface KeycloakSession extends Provider {
     RealmModel createRealm(String id, String name);
     RealmModel getRealm(String id);
     RealmModel getRealmByName(String name);
+    UserModel getUserById(String id, String realmId);
+    UserModel getUserByUsername(String username, String realmId);
+    UserModel getUserByEmail(String email, String realmId);
     List<RealmModel> getRealms();
     boolean removeRealm(String id);
 
diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java
index c2ec9f3..829b9b0 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -110,12 +110,6 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
 
     boolean validateTOTP(UserModel user, String password, String token);
 
-    void updateCredential(UserModel user, UserCredentialModel cred);
-
-    List<UserCredentialValueModel> getCredentialsDirectly(UserModel user);
-
-    void updateCredentialDirectly(UserModel user, UserCredentialValueModel cred);
-
     UserModel getUser(String name);
 
     UserModel getUserByEmail(String email);
diff --git a/model/api/src/main/java/org/keycloak/models/UserModel.java b/model/api/src/main/java/org/keycloak/models/UserModel.java
index b01cf93..f0e34b8 100755
--- a/model/api/src/main/java/org/keycloak/models/UserModel.java
+++ b/model/api/src/main/java/org/keycloak/models/UserModel.java
@@ -1,5 +1,6 @@
 package org.keycloak.models;
 
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -60,6 +61,14 @@ public interface UserModel {
     int getNotBefore();
     void setNotBefore(int notBefore);
 
+    void updateCredential(UserCredentialModel cred);
+
+    List<UserCredentialValueModel> getCredentialsDirectly();
+
+    void updateCredentialDirectly(UserCredentialValueModel cred);
+
+
+
 
     public static enum RequiredAction {
         VERIFY_EMAIL, UPDATE_PROFILE, CONFIGURE_TOTP, UPDATE_PASSWORD
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
new file mode 100755
index 0000000..9b0e421
--- /dev/null
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheKeycloakSession.java
@@ -0,0 +1,176 @@
+package org.keycloak.models.cache;
+
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakTransaction;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.cache.entities.CachedRealm;
+import org.keycloak.provider.ProviderSession;
+
+import java.util.HashSet;
+import java.util.List;
+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(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(model);
+        }
+        return new RealmAdapter(cached, this);
+    }
+
+    @Override
+    public UserModel getUserById(String id, String realmId) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UserModel getUserByUsername(String username, String realmId) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UserModel getUserByEmail(String email, String realmId) {
+        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();
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
new file mode 100755
index 0000000..10a8901
--- /dev/null
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
@@ -0,0 +1,295 @@
+package org.keycloak.models.cache.entities;
+
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.AuthenticationLinkModel;
+import org.keycloak.models.AuthenticationProviderModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.OAuthClientModel;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.SocialLinkModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.UsernameLoginFailureModel;
+import org.keycloak.models.entities.AuthenticationProviderEntity;
+import org.keycloak.models.entities.RequiredCredentialEntity;
+
+import java.io.Serializable;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+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 CachedRealm {
+
+    private String id;
+    private String name;
+    private boolean enabled;
+    private boolean sslNotRequired;
+    private boolean registrationAllowed;
+    private boolean rememberMe;
+    private boolean verifyEmail;
+    private boolean passwordCredentialGrantAllowed;
+    private boolean resetPasswordAllowed;
+    private boolean social;
+    private boolean updateProfileOnInitialSocialLogin;
+    //--- brute force settings
+    private boolean bruteForceProtected;
+    private int maxFailureWaitSeconds;
+    private int minimumQuickLoginWaitSeconds;
+    private int waitIncrementSeconds;
+    private long quickLoginCheckMilliSeconds;
+    private int maxDeltaTimeSeconds;
+    private int failureFactor;
+    //--- end brute force settings
+
+    private int ssoSessionIdleTimeout;
+    private int ssoSessionMaxLifespan;
+    private int accessTokenLifespan;
+    private int accessCodeLifespan;
+    private int accessCodeLifespanUserAction;
+    private int notBefore;
+    private PasswordPolicy passwordPolicy;
+
+    private String publicKeyPem;
+    private String privateKeyPem;
+
+    private String loginTheme;
+    private String accountTheme;
+    private String adminTheme;
+    private String emailTheme;
+
+    private List<RequiredCredentialModel> requiredCredentials = new ArrayList<RequiredCredentialModel>();
+    private List<AuthenticationProviderModel> authenticationProviders = new ArrayList<AuthenticationProviderModel>();
+
+    private Map<String, String> smtpConfig = new HashMap<String, String>();
+    private Map<String, String> socialConfig = new HashMap<String, String>();
+    private Map<String, String> ldapServerConfig = new HashMap<String, String>();
+
+    private boolean auditEnabled;
+    private long auditExpiration;
+    private Set<String> auditListeners = new HashSet<String>();
+
+    public CachedRealm() {
+    }
+
+    public CachedRealm(RealmModel model) {
+        id = model.getId();
+        name = model.getName();
+        enabled = model.isEnabled();
+        sslNotRequired = model.isSslNotRequired();
+        registrationAllowed = model.isRegistrationAllowed();
+        rememberMe = model.isRememberMe();
+        verifyEmail = model.isVerifyEmail();
+        passwordCredentialGrantAllowed = model.isPasswordCredentialGrantAllowed();
+        resetPasswordAllowed = model.isResetPasswordAllowed();
+        social = model.isSocial();
+        updateProfileOnInitialSocialLogin = model.isUpdateProfileOnInitialSocialLogin();
+        //--- brute force settings
+        bruteForceProtected = model.isBruteForceProtected();
+        maxFailureWaitSeconds = model.getMaxFailureWaitSeconds();
+        minimumQuickLoginWaitSeconds = model.getMinimumQuickLoginWaitSeconds();
+        waitIncrementSeconds = model.getWaitIncrementSeconds();
+        quickLoginCheckMilliSeconds = model.getQuickLoginCheckMilliSeconds();
+        maxDeltaTimeSeconds = model.getMaxDeltaTimeSeconds();
+        failureFactor = model.getFailureFactor();
+        //--- end brute force settings
+
+        ssoSessionIdleTimeout = model.getSsoSessionIdleTimeout();
+        ssoSessionMaxLifespan = model.getSsoSessionMaxLifespan();
+        accessTokenLifespan = model.getAccessTokenLifespan();
+        accessCodeLifespan = model.getAccessCodeLifespan();
+        accessCodeLifespanUserAction = model.getAccessCodeLifespanUserAction();
+        notBefore = model.getNotBefore();
+        passwordPolicy = model.getPasswordPolicy();
+
+        publicKeyPem = model.getPublicKeyPem();
+        privateKeyPem = model.getPrivateKeyPem();
+
+        loginTheme = model.getLoginTheme();
+        accountTheme = model.getAccountTheme();
+        adminTheme = model.getAdminTheme();
+        emailTheme = model.getEmailTheme();
+
+        requiredCredentials = model.getRequiredCredentials();
+        authenticationProviders = model.getAuthenticationProviders();
+
+        smtpConfig.putAll(model.getSmtpConfig());
+        socialConfig.putAll(model.getSocialConfig());
+        ldapServerConfig.putAll(model.getLdapServerConfig());
+
+        auditEnabled = model.isAuditEnabled();
+        auditExpiration = model.getAuditExpiration();
+        auditListeners.addAll(model.getAuditListeners());
+    }
+
+
+    public String getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public boolean isSslNotRequired() {
+        return sslNotRequired;
+    }
+
+    public boolean isRegistrationAllowed() {
+        return registrationAllowed;
+    }
+
+    public boolean isPasswordCredentialGrantAllowed() {
+        return passwordCredentialGrantAllowed;
+    }
+
+    public boolean isRememberMe() {
+        return this.rememberMe;
+    }
+
+    public boolean isBruteForceProtected() {
+        return bruteForceProtected;
+    }
+
+    public int getMaxFailureWaitSeconds() {
+        return this.maxFailureWaitSeconds;
+    }
+
+    public int getWaitIncrementSeconds() {
+        return this.waitIncrementSeconds;
+    }
+
+    public int getMinimumQuickLoginWaitSeconds() {
+        return this.minimumQuickLoginWaitSeconds;
+    }
+
+    public long getQuickLoginCheckMilliSeconds() {
+        return quickLoginCheckMilliSeconds;
+    }
+
+    public int getMaxDeltaTimeSeconds() {
+        return maxDeltaTimeSeconds;
+    }
+
+    public int getFailureFactor() {
+        return failureFactor;
+    }
+
+    public boolean isVerifyEmail() {
+        return verifyEmail;
+    }
+
+    public boolean isResetPasswordAllowed() {
+        return resetPasswordAllowed;
+    }
+
+    public int getSsoSessionIdleTimeout() {
+        return ssoSessionIdleTimeout;
+    }
+
+    public int getSsoSessionMaxLifespan() {
+        return ssoSessionMaxLifespan;
+    }
+
+    public int getAccessTokenLifespan() {
+        return accessTokenLifespan;
+    }
+
+    public int getAccessCodeLifespan() {
+        return accessCodeLifespan;
+    }
+
+    public int getAccessCodeLifespanUserAction() {
+        return accessCodeLifespanUserAction;
+    }
+
+    public String getPublicKeyPem() {
+        return publicKeyPem;
+    }
+
+    public String getPrivateKeyPem() {
+        return privateKeyPem;
+    }
+
+    public List<RequiredCredentialModel> getRequiredCredentials() {
+        return requiredCredentials;
+    }
+
+    public PasswordPolicy getPasswordPolicy() {
+        return passwordPolicy;
+    }
+
+    public boolean isSocial() {
+        return social;
+    }
+
+    public boolean isUpdateProfileOnInitialSocialLogin() {
+        return updateProfileOnInitialSocialLogin;
+    }
+
+    public Map<String, String> getSmtpConfig() {
+        return smtpConfig;
+    }
+
+    public Map<String, String> getSocialConfig() {
+        return socialConfig;
+    }
+
+    public Map<String, String> getLdapServerConfig() {
+        return ldapServerConfig;
+    }
+
+    public List<AuthenticationProviderModel> getAuthenticationProviders() {
+        return authenticationProviders;
+    }
+
+    public String getLoginTheme() {
+        return loginTheme;
+    }
+
+    public String getAccountTheme() {
+        return accountTheme;
+    }
+
+    public String getAdminTheme() {
+        return this.adminTheme;
+    }
+
+    public String getEmailTheme() {
+        return emailTheme;
+    }
+
+    public int getNotBefore() {
+        return notBefore;
+    }
+
+    public boolean isAuditEnabled() {
+        return auditEnabled;
+    }
+
+    public long getAuditExpiration() {
+        return auditExpiration;
+    }
+
+    public Set<String> getAuditListeners() {
+        return auditListeners;
+    }
+
+}
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
new file mode 100755
index 0000000..fdf0897
--- /dev/null
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/KeycloakCache.java
@@ -0,0 +1,21 @@
+package org.keycloak.models.cache;
+
+import org.keycloak.models.cache.entities.CachedRealm;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface KeycloakCache {
+    CachedRealm getCachedRealm(String id);
+
+    void invalidateCachedRealm(CachedRealm realm);
+
+    void addCachedRealm(CachedRealm realm);
+
+    CachedRealm getCachedRealmByName(String name);
+
+    void clear();
+
+    void invalidateCachedRealmById(String id);
+}
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
new file mode 100755
index 0000000..735c108
--- /dev/null
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
@@ -0,0 +1,846 @@
+package org.keycloak.models.cache;
+
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.AuthenticationLinkModel;
+import org.keycloak.models.AuthenticationProviderModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.OAuthClientModel;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.SocialLinkModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
+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.utils.KeycloakModelUtils;
+
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.LinkedList;
+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 RealmAdapter implements RealmModel {
+    protected CachedRealm cached;
+    protected CacheKeycloakSession cacheSession;
+    protected RealmModel updated;
+    protected volatile transient PublicKey publicKey;
+    protected volatile transient PrivateKey privateKey;
+
+    public RealmAdapter(CachedRealm cached, CacheKeycloakSession cacheSession) {
+        this.cached = cached;
+        this.cacheSession = cacheSession;
+    }
+
+    @Override
+    public String getId() {
+        if (updated != null) return updated.getId();
+        return cached.getId();
+    }
+
+    @Override
+    public String getName() {
+        if (updated != null) return updated.getName();
+        return cached.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        getDelegateForUpdate();
+        updated.setName(name);
+    }
+
+    protected void getDelegateForUpdate() {
+        if (updated == null) {
+            updated = cacheSession.getRealm(getId());
+            if (updated == null) throw new IllegalStateException("Not found in database");
+        }
+    }
+
+    @Override
+    public boolean isEnabled() {
+        if (updated != null) return updated.isEnabled();
+        return cached.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        getDelegateForUpdate();
+        updated.setEnabled(enabled);
+    }
+
+    @Override
+    public boolean isSslNotRequired() {
+        if (updated != null) return updated.isSslNotRequired();
+        return cached.isSslNotRequired();
+    }
+
+    @Override
+    public void setSslNotRequired(boolean sslNotRequired) {
+        getDelegateForUpdate();
+        updated.setSslNotRequired(sslNotRequired);
+    }
+
+    @Override
+    public boolean isRegistrationAllowed() {
+        if (updated != null) return updated.isRegistrationAllowed();
+        return cached.isRegistrationAllowed();
+    }
+
+    @Override
+    public void setRegistrationAllowed(boolean registrationAllowed) {
+        getDelegateForUpdate();
+        updated.setRegistrationAllowed(registrationAllowed);
+    }
+
+    @Override
+    public boolean isPasswordCredentialGrantAllowed() {
+        if (updated != null) return updated.isPasswordCredentialGrantAllowed();
+        return cached.isPasswordCredentialGrantAllowed();
+    }
+
+    @Override
+    public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
+        getDelegateForUpdate();
+        updated.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
+    }
+
+    @Override
+    public boolean isRememberMe() {
+        if (updated != null) return updated.isRememberMe();
+        return cached.isRememberMe();
+    }
+
+    @Override
+    public void setRememberMe(boolean rememberMe) {
+        getDelegateForUpdate();
+        updated.setRememberMe(rememberMe);
+    }
+
+    @Override
+    public boolean isBruteForceProtected() {
+        if (updated != null) return updated.isBruteForceProtected();
+        return cached.isBruteForceProtected();
+    }
+
+    @Override
+    public void setBruteForceProtected(boolean value) {
+        getDelegateForUpdate();
+        updated.setBruteForceProtected(value);
+    }
+
+    @Override
+    public int getMaxFailureWaitSeconds() {
+        if (updated != null) return updated.getMaxFailureWaitSeconds();
+        return cached.getMaxFailureWaitSeconds();
+    }
+
+    @Override
+    public void setMaxFailureWaitSeconds(int val) {
+        getDelegateForUpdate();
+        updated.setMaxFailureWaitSeconds(val);
+    }
+
+    @Override
+    public int getWaitIncrementSeconds() {
+        if (updated != null) return updated.getWaitIncrementSeconds();
+        return cached.getWaitIncrementSeconds();
+    }
+
+    @Override
+    public void setWaitIncrementSeconds(int val) {
+        getDelegateForUpdate();
+        updated.setWaitIncrementSeconds(val);
+    }
+
+    @Override
+    public int getMinimumQuickLoginWaitSeconds() {
+        if (updated != null) return updated.getMinimumQuickLoginWaitSeconds();
+        return cached.getMinimumQuickLoginWaitSeconds();
+    }
+
+    @Override
+    public void setMinimumQuickLoginWaitSeconds(int val) {
+        getDelegateForUpdate();
+        updated.setMinimumQuickLoginWaitSeconds(val);
+    }
+
+    @Override
+    public long getQuickLoginCheckMilliSeconds() {
+        if (updated != null) return updated.getQuickLoginCheckMilliSeconds();
+        return cached.getQuickLoginCheckMilliSeconds();
+    }
+
+    @Override
+    public void setQuickLoginCheckMilliSeconds(long val) {
+        getDelegateForUpdate();
+        updated.setQuickLoginCheckMilliSeconds(val);
+    }
+
+    @Override
+    public int getMaxDeltaTimeSeconds() {
+        if (updated != null) return updated.getMaxDeltaTimeSeconds();
+        return cached.getMaxDeltaTimeSeconds();
+    }
+
+    @Override
+    public void setMaxDeltaTimeSeconds(int val) {
+        getDelegateForUpdate();
+        updated.setMaxDeltaTimeSeconds(val);
+    }
+
+    @Override
+    public int getFailureFactor() {
+        if (updated != null) return updated.getFailureFactor();
+        return cached.getFailureFactor();
+    }
+
+    @Override
+    public void setFailureFactor(int failureFactor) {
+        getDelegateForUpdate();
+        updated.setFailureFactor(failureFactor);
+    }
+
+    @Override
+    public boolean isVerifyEmail() {
+        if (updated != null) return updated.isVerifyEmail();
+        return cached.isVerifyEmail();
+    }
+
+    @Override
+    public void setVerifyEmail(boolean verifyEmail) {
+        getDelegateForUpdate();
+        updated.setVerifyEmail(verifyEmail);
+    }
+
+    @Override
+    public boolean isResetPasswordAllowed() {
+        if (updated != null) return updated.isResetPasswordAllowed();
+        return cached.isResetPasswordAllowed();
+    }
+
+    @Override
+    public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
+        getDelegateForUpdate();
+        updated.setResetPasswordAllowed(resetPasswordAllowed);
+    }
+
+    @Override
+    public int getSsoSessionIdleTimeout() {
+        if (updated != null) return updated.getSsoSessionIdleTimeout();
+        return cached.getSsoSessionIdleTimeout();
+    }
+
+    @Override
+    public void setSsoSessionIdleTimeout(int seconds) {
+        getDelegateForUpdate();
+        updated.setSsoSessionIdleTimeout(seconds);
+    }
+
+    @Override
+    public int getSsoSessionMaxLifespan() {
+        if (updated != null) return updated.getSsoSessionMaxLifespan();
+        return cached.getSsoSessionMaxLifespan();
+    }
+
+    @Override
+    public void setSsoSessionMaxLifespan(int seconds) {
+        getDelegateForUpdate();
+        updated.setSsoSessionMaxLifespan(seconds);
+    }
+
+    @Override
+    public int getAccessTokenLifespan() {
+        if (updated != null) return updated.getAccessTokenLifespan();
+        return cached.getAccessTokenLifespan();
+    }
+
+    @Override
+    public void setAccessTokenLifespan(int seconds) {
+        getDelegateForUpdate();
+        updated.setAccessTokenLifespan(seconds);
+    }
+
+    @Override
+    public int getAccessCodeLifespan() {
+        if (updated != null) return updated.getAccessCodeLifespan();
+        return cached.getAccessCodeLifespan();
+    }
+
+    @Override
+    public void setAccessCodeLifespan(int seconds) {
+        getDelegateForUpdate();
+        updated.setAccessCodeLifespan(seconds);
+    }
+
+    @Override
+    public int getAccessCodeLifespanUserAction() {
+        if (updated != null) return updated.getAccessCodeLifespanUserAction();
+        return cached.getAccessCodeLifespanUserAction();
+    }
+
+    @Override
+    public void setAccessCodeLifespanUserAction(int seconds) {
+        getDelegateForUpdate();
+        updated.setAccessCodeLifespanUserAction(seconds);
+    }
+
+    @Override
+    public String getPublicKeyPem() {
+        if (updated != null) return updated.getPublicKeyPem();
+        return cached.getPublicKeyPem();
+    }
+
+    @Override
+    public void setPublicKeyPem(String publicKeyPem) {
+        getDelegateForUpdate();
+        updated.setPublicKeyPem(publicKeyPem);
+    }
+
+    @Override
+    public String getPrivateKeyPem() {
+        if (updated != null) return updated.getPrivateKeyPem();
+        return cached.getPrivateKeyPem();
+    }
+
+    @Override
+    public void setPrivateKeyPem(String privateKeyPem) {
+        getDelegateForUpdate();
+        updated.setPrivateKeyPem(privateKeyPem);
+    }
+
+    @Override
+    public PublicKey getPublicKey() {
+        if (publicKey != null) return publicKey;
+        publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
+        return publicKey;
+    }
+
+    @Override
+    public void setPublicKey(PublicKey publicKey) {
+        this.publicKey = publicKey;
+        String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
+        setPublicKeyPem(publicKeyPem);
+    }
+
+    @Override
+    public PrivateKey getPrivateKey() {
+        if (privateKey != null) return privateKey;
+        privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
+        return privateKey;
+    }
+
+    @Override
+    public void setPrivateKey(PrivateKey privateKey) {
+        this.privateKey = privateKey;
+        String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
+        setPrivateKeyPem(privateKeyPem);
+    }
+
+    @Override
+    public List<RequiredCredentialModel> getRequiredCredentials() {
+
+        List<RequiredCredentialModel> copy = new LinkedList<RequiredCredentialModel>();
+        if (updated != null) copy.addAll(updated.getRequiredCredentials());
+        else copy.addAll(cached.getRequiredCredentials());
+        return copy;
+    }
+
+    @Override
+    public void addRequiredCredential(String cred) {
+        getDelegateForUpdate();
+        updated.addRequiredCredential(cred);
+    }
+
+    @Override
+    public PasswordPolicy getPasswordPolicy() {
+        if (updated != null) return updated.getPasswordPolicy();
+        return cached.getPasswordPolicy();
+    }
+
+    @Override
+    public void setPasswordPolicy(PasswordPolicy policy) {
+        getDelegateForUpdate();
+        updated.setPasswordPolicy(policy);
+    }
+
+    @Override
+    public boolean validatePassword(UserModel user, String password) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean validateTOTP(UserModel user, String password, String token) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UserModel getUser(String name) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UserModel getUserByEmail(String email) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UserModel getUserById(String name) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UserModel addUser(String id, String username) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UserModel addUser(String username) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean removeUser(String name) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public RoleModel getRoleById(String id) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<String> getDefaultRoles() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public ClientModel findClient(String clientId) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Map<String, ApplicationModel> getApplicationNameMap() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<ApplicationModel> getApplications() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public ApplicationModel addApplication(String name) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public ApplicationModel addApplication(String id, String name) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean removeApplication(String id) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public ApplicationModel getApplicationById(String id) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public ApplicationModel getApplicationByName(String name) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void updateRequiredCredentials(Set<String> creds) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UserModel getUserBySocialLink(SocialLinkModel socialLink) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Set<SocialLinkModel> getSocialLinks(UserModel user) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public SocialLinkModel getSocialLink(UserModel user, String socialProvider) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void addSocialLink(UserModel user, SocialLinkModel socialLink) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean removeSocialLink(UserModel user, String socialProvider) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public AuthenticationLinkModel getAuthenticationLink(UserModel user) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setAuthenticationLink(UserModel user, AuthenticationLinkModel authenticationLink) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean isSocial() {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setSocial(boolean social) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean isUpdateProfileOnInitialSocialLogin() {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setUpdateProfileOnInitialSocialLogin(boolean updateProfileOnInitialSocialLogin) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UsernameLoginFailureModel getUserLoginFailure(String username) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UsernameLoginFailureModel addUserLoginFailure(String username) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<UsernameLoginFailureModel> getAllUserLoginFailures() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<UserModel> getUsers() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<UserModel> searchForUser(String search) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public OAuthClientModel addOAuthClient(String name) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public OAuthClientModel addOAuthClient(String id, String name) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public OAuthClientModel getOAuthClient(String name) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public OAuthClientModel getOAuthClientById(String id) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean removeOAuthClient(String id) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<OAuthClientModel> getOAuthClients() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Map<String, String> getSmtpConfig() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setSmtpConfig(Map<String, String> smtpConfig) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Map<String, String> getSocialConfig() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setSocialConfig(Map<String, String> socialConfig) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Map<String, String> getLdapServerConfig() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setLdapServerConfig(Map<String, String> ldapServerConfig) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<AuthenticationProviderModel> getAuthenticationProviders() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setAuthenticationProviders(List<AuthenticationProviderModel> authenticationProviders) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Set<RoleModel> getRealmRoleMappings(UserModel user) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Set<RoleModel> getRealmScopeMappings(ClientModel client) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public String getLoginTheme() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setLoginTheme(String name) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public String getAccountTheme() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setAccountTheme(String name) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public String getAdminTheme() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setAdminTheme(String name) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public String getEmailTheme() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setEmailTheme(String name) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean hasScope(ClientModel client, RoleModel role) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public int getNotBefore() {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setNotBefore(int notBefore) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean removeRoleById(String id) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean isAuditEnabled() {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setAuditEnabled(boolean enabled) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public long getAuditExpiration() {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setAuditExpiration(long expiration) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Set<String> getAuditListeners() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setAuditListeners(Set<String> listeners) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public ApplicationModel getMasterAdminApp() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void setMasterAdminApp(ApplicationModel app) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UserSessionModel createUserSession(UserModel user, String ipAddress) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public UserSessionModel getUserSession(String id) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<UserSessionModel> getUserSessions(UserModel user) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void removeUserSession(UserSessionModel session) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void removeUserSessions(UserModel user) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void removeExpiredUserSessions() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public ClientModel findClientById(String id) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void removeUserSessions() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public RoleModel getRole(String name) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public RoleModel addRole(String name) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public RoleModel addRole(String id, String name) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean removeRole(RoleModel role) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public boolean hasRole(UserModel user, RoleModel role) {
+        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void grantRole(UserModel user, RoleModel role) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Set<RoleModel> getRoleMappings(UserModel user) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void deleteRoleMapping(UserModel user, RoleModel role) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public Set<RoleModel> getScopeMappings(ClientModel client) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void addScopeMapping(ClientModel client, RoleModel role) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public void deleteScopeMapping(ClientModel client, RoleModel role) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+}
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
new file mode 100755
index 0000000..1e7a17f
--- /dev/null
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCache.java
@@ -0,0 +1,59 @@
+package org.keycloak.models.cache;
+
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.KeycloakTransaction;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.cache.entities.CachedRealm;
+import org.keycloak.provider.ProviderSession;
+import org.keycloak.provider.ProviderSessionFactory;
+
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SimpleCache implements KeycloakCache {
+
+    protected ConcurrentHashMap<String, CachedRealm> realmCache = new ConcurrentHashMap<String, CachedRealm>();
+    protected ConcurrentHashMap<String, CachedRealm> realmCacheByName = new ConcurrentHashMap<String, CachedRealm>();
+
+    @Override
+    public void clear() {
+        realmCache.clear();
+        realmCacheByName.clear();
+    }
+
+    @Override
+    public CachedRealm getCachedRealm(String id) {
+        return realmCache.get(id);
+    }
+
+    @Override
+    public void invalidateCachedRealm(CachedRealm realm) {
+        realmCache.remove(realm.getId());
+        realmCacheByName.remove(realm.getName());
+    }
+
+    @Override
+    public void invalidateCachedRealmById(String id) {
+        CachedRealm cached = realmCache.remove(id);
+        if (cached != null) realmCacheByName.remove(cached.getName());
+    }
+
+
+    @Override
+    public void addCachedRealm(CachedRealm realm) {
+        realmCache.put(realm.getId(), realm);
+        realmCache.put(realm.getName(), realm);
+
+    }
+
+    @Override
+    public CachedRealm getCachedRealmByName(String name) {
+        return realmCacheByName.get(name);
+    }
+}
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 f51ed94..39d03a4 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
@@ -32,6 +32,7 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 @NamedQueries({
+        @NamedQuery(name="getRealmUserById", query="select u from UserEntity u where u.id = :id and u.realm = :realm"),
         @NamedQuery(name="getRealmUserByLoginName", query="select u from UserEntity u where u.loginName = :loginName and u.realm = :realm"),
         @NamedQuery(name="getRealmUserByEmail", query="select u from UserEntity u where u.email = :email and u.realm = :realm"),
         @NamedQuery(name="getRealmUserByLastName", query="select u from UserEntity u where u.lastName = :lastName and u.realm = :realm"),
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
index 36aabd6..98b0745 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
@@ -73,6 +73,38 @@ public class JpaKeycloakSession implements KeycloakSession {
     }
 
     @Override
+    public UserModel getUserById(String id, String realmId) {
+        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserById", UserEntity.class);
+        query.setParameter("id", id);
+        RealmEntity realm = em.getReference(RealmEntity.class, realmId);
+        query.setParameter("realm", realm);
+        List<UserEntity> entities = query.getResultList();
+        if (entities.size() == 0) return null;
+        return new UserAdapter(em, entities.get(0));
+    }
+
+    @Override
+    public UserModel getUserByUsername(String username, String realmId) {
+        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByLoginName", UserEntity.class);
+        query.setParameter("loginName", username);
+        RealmEntity realm = em.getReference(RealmEntity.class, realmId);
+        query.setParameter("realm", realm);
+        List<UserEntity> results = query.getResultList();
+        if (results.size() == 0) return null;
+        return new UserAdapter(em, results.get(0));
+    }
+
+    @Override
+    public UserModel getUserByEmail(String email, String realmId) {
+        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByEmail", UserEntity.class);
+        query.setParameter("email", email);
+        RealmEntity realm = em.getReference(RealmEntity.class, realmId);
+        query.setParameter("realm", realm);
+        List<UserEntity> results = query.getResultList();
+        return results.isEmpty() ? null : new UserAdapter(em, results.get(0));
+    }
+
+    @Override
     public boolean removeRealm(String id) {
         RealmEntity realm = em.find(RealmEntity.class, id);
         if (realm == null) {
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 1c4cae0..5af777d 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
@@ -429,7 +429,7 @@ public class RealmAdapter implements RealmModel {
         query.setParameter("realm", realm);
         List<UserEntity> results = query.getResultList();
         if (results.size() == 0) return null;
-        return new UserAdapter(results.get(0));
+        return new UserAdapter(em, results.get(0));
     }
 
     @Override
@@ -470,7 +470,7 @@ public class RealmAdapter implements RealmModel {
         query.setParameter("email", email);
         query.setParameter("realm", realm);
         List<UserEntity> results = query.getResultList();
-        return results.isEmpty() ? null : new UserAdapter(results.get(0));
+        return results.isEmpty() ? null : new UserAdapter(em, results.get(0));
     }
 
     @Override
@@ -479,7 +479,7 @@ public class RealmAdapter implements RealmModel {
 
         // Check if user belongs to this realm
         if (entity == null || !this.realm.equals(entity.getRealm())) return null;
-        return new UserAdapter(entity);
+        return new UserAdapter(em, entity);
     }
 
     @Override
@@ -495,7 +495,7 @@ public class RealmAdapter implements RealmModel {
         entity.setRealm(realm);
         em.persist(entity);
         em.flush();
-        UserModel userModel = new UserAdapter(entity);
+        UserModel userModel = new UserAdapter(em, entity);
 
         for (String r : getDefaultRoles()) {
             grantRole(userModel, getRole(r));
@@ -706,7 +706,7 @@ public class RealmAdapter implements RealmModel {
                     ", socialUserId=" + socialLink.getSocialUserId() + ", results=" + results);
         } else {
             UserEntity user = results.get(0);
-            return new UserAdapter(user);
+            return new UserAdapter(em, user);
         }
     }
 
@@ -808,7 +808,7 @@ public class RealmAdapter implements RealmModel {
         query.setParameter("realm", realm);
         List<UserEntity> results = query.getResultList();
         List<UserModel> users = new ArrayList<UserModel>();
-        for (UserEntity entity : results) users.add(new UserAdapter(entity));
+        for (UserEntity entity : results) users.add(new UserAdapter(em, entity));
         return users;
     }
 
@@ -819,7 +819,7 @@ public class RealmAdapter implements RealmModel {
         query.setParameter("search", "%" + search.toLowerCase() + "%");
         List<UserEntity> results = query.getResultList();
         List<UserModel> users = new ArrayList<UserModel>();
-        for (UserEntity entity : results) users.add(new UserAdapter(entity));
+        for (UserEntity entity : results) users.add(new UserAdapter(em, entity));
         return users;
     }
 
@@ -851,7 +851,7 @@ public class RealmAdapter implements RealmModel {
         TypedQuery<UserEntity> query = em.createQuery(q, UserEntity.class);
         List<UserEntity> results = query.getResultList();
         List<UserModel> users = new ArrayList<UserModel>();
-        for (UserEntity entity : results) users.add(new UserAdapter(entity));
+        for (UserEntity entity : results) users.add(new UserAdapter(em, entity));
         return users;
     }
 
@@ -1218,9 +1218,10 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean validatePassword(UserModel user, String password) {
-        for (CredentialEntity cred : ((UserAdapter) user).getUser().getCredentials()) {
+        for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
             if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
                 return new Pbkdf2PasswordEncoder(cred.getSalt()).verify(password, cred.getValue());
+
             }
         }
         return false;
@@ -1229,7 +1230,7 @@ public class RealmAdapter implements RealmModel {
     @Override
     public boolean validateTOTP(UserModel user, String password, String token) {
         if (!validatePassword(user, password)) return false;
-        for (CredentialEntity cred : ((UserAdapter) user).getUser().getCredentials()) {
+        for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
             if (cred.getType().equals(UserCredentialModel.TOTP)) {
                 return new TimeBasedOTP().validate(token, cred.getValue().getBytes());
             }
@@ -1238,81 +1239,6 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
-    public void updateCredential(UserModel user, UserCredentialModel cred) {
-        UserEntity userEntity = ((UserAdapter) user).getUser();
-        CredentialEntity credentialEntity = getCredentialEntity(userEntity, cred.getType());
-
-        if (credentialEntity == null) {
-            credentialEntity = new CredentialEntity();
-            credentialEntity.setType(cred.getType());
-            credentialEntity.setDevice(cred.getDevice());
-            credentialEntity.setUser(userEntity);
-            em.persist(credentialEntity);
-            userEntity.getCredentials().add(credentialEntity);
-        }
-        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-            byte[] salt = getSalt();
-            credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue()));
-            credentialEntity.setSalt(salt);
-        } else {
-            credentialEntity.setValue(cred.getValue());
-        }
-        credentialEntity.setDevice(cred.getDevice());
-        em.flush();
-    }
-
-    private CredentialEntity getCredentialEntity(UserEntity userEntity, String credType) {
-        for (CredentialEntity entity : userEntity.getCredentials()) {
-            if (entity.getType().equals(credType)) {
-                return entity;
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public List<UserCredentialValueModel> getCredentialsDirectly(UserModel user) {
-        UserEntity userEntity = ((UserAdapter) user).getUser();
-        List<CredentialEntity> credentials = new ArrayList<CredentialEntity>(userEntity.getCredentials());
-        List<UserCredentialValueModel> result = new ArrayList<UserCredentialValueModel>();
-
-        if (credentials != null) {
-            for (CredentialEntity credEntity : credentials) {
-                UserCredentialValueModel credModel = new UserCredentialValueModel();
-                credModel.setType(credEntity.getType());
-                credModel.setDevice(credEntity.getDevice());
-                credModel.setValue(credEntity.getValue());
-                credModel.setSalt(credEntity.getSalt());
-
-                result.add(credModel);
-            }
-        }
-
-        return result;
-    }
-
-    @Override
-    public void updateCredentialDirectly(UserModel user, UserCredentialValueModel credModel) {
-        UserEntity userEntity = ((UserAdapter) user).getUser();
-        CredentialEntity credentialEntity = getCredentialEntity(userEntity, credModel.getType());
-
-        if (credentialEntity == null) {
-            credentialEntity = new CredentialEntity();
-            credentialEntity.setType(credModel.getType());
-            credentialEntity.setUser(userEntity);
-            em.persist(credentialEntity);
-            userEntity.getCredentials().add(credentialEntity);
-        }
-
-        credentialEntity.setValue(credModel.getValue());
-        credentialEntity.setSalt(credModel.getSalt());
-        credentialEntity.setDevice(credModel.getDevice());
-
-        em.flush();
-    }
-
-    @Override
     public PasswordPolicy getPasswordPolicy() {
         if (passwordPolicy == null) {
             passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy());
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 9857062..1683cfd 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
@@ -1,13 +1,22 @@
 package org.keycloak.models.jpa;
 
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
 import org.keycloak.models.UserModel;
+import org.keycloak.models.jpa.entities.CredentialEntity;
 import org.keycloak.models.jpa.entities.UserEntity;
+import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
 
+import javax.persistence.EntityManager;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -15,8 +24,10 @@ import java.util.Set;
 public class UserAdapter implements UserModel {
 
     protected UserEntity user;
+    protected EntityManager em;
 
-    public UserAdapter(UserEntity user) {
+    public UserAdapter(EntityManager em, UserEntity user) {
+        this.em = em;
         this.user = user;
     }
 
@@ -160,6 +171,78 @@ public class UserAdapter implements UserModel {
         user.setNotBefore(notBefore);
     }
 
+    @Override
+    public void updateCredential(UserCredentialModel cred) {
+        CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
+
+        if (credentialEntity == null) {
+            credentialEntity = new CredentialEntity();
+            credentialEntity.setType(cred.getType());
+            credentialEntity.setDevice(cred.getDevice());
+            credentialEntity.setUser(user);
+            em.persist(credentialEntity);
+            user.getCredentials().add(credentialEntity);
+        }
+        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+            byte[] salt = getSalt();
+            credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue()));
+            credentialEntity.setSalt(salt);
+        } else {
+            credentialEntity.setValue(cred.getValue());
+        }
+        credentialEntity.setDevice(cred.getDevice());
+        em.flush();
+    }
+
+    private CredentialEntity getCredentialEntity(UserEntity userEntity, String credType) {
+        for (CredentialEntity entity : userEntity.getCredentials()) {
+            if (entity.getType().equals(credType)) {
+                return entity;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public List<UserCredentialValueModel> getCredentialsDirectly() {
+        List<CredentialEntity> credentials = new ArrayList<CredentialEntity>(user.getCredentials());
+        List<UserCredentialValueModel> result = new ArrayList<UserCredentialValueModel>();
+
+        if (credentials != null) {
+            for (CredentialEntity credEntity : credentials) {
+                UserCredentialValueModel credModel = new UserCredentialValueModel();
+                credModel.setType(credEntity.getType());
+                credModel.setDevice(credEntity.getDevice());
+                credModel.setValue(credEntity.getValue());
+                credModel.setSalt(credEntity.getSalt());
+
+                result.add(credModel);
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public void updateCredentialDirectly(UserCredentialValueModel credModel) {
+        CredentialEntity credentialEntity = getCredentialEntity(user, credModel.getType());
+
+        if (credentialEntity == null) {
+            credentialEntity = new CredentialEntity();
+            credentialEntity.setType(credModel.getType());
+            credentialEntity.setUser(user);
+            em.persist(credentialEntity);
+            user.getCredentials().add(credentialEntity);
+        }
+
+        credentialEntity.setValue(credModel.getValue());
+        credentialEntity.setSalt(credModel.getSalt());
+        credentialEntity.setDevice(credModel.getDevice());
+
+        em.flush();
+    }
+
 
 
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java
index 0c13eb9..d16cdcb 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoKeycloakSession.java
@@ -6,10 +6,12 @@ import com.mongodb.QueryBuilder;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakTransaction;
 import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
 import org.keycloak.models.mongo.api.MongoStore;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.mongo.impl.context.TransactionMongoStoreInvocationContext;
 import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
 import org.keycloak.models.utils.KeycloakModelUtils;
 
 import java.util.ArrayList;
@@ -90,6 +92,48 @@ public class MongoKeycloakSession implements KeycloakSession {
     }
 
     @Override
+    public UserModel getUserById(String id, String realmId) {
+        MongoUserEntity user = getMongoStore().loadEntity(MongoUserEntity.class, id, invocationContext);
+
+        // Check that it's user from this realm
+        if (user == null || !realmId.equals(user.getRealmId())) {
+            return null;
+        } else {
+            return new UserAdapter(user, invocationContext);
+        }
+    }
+
+    @Override
+    public UserModel getUserByUsername(String username, String realmId) {
+        DBObject query = new QueryBuilder()
+                .and("loginName").is(username)
+                .and("realmId").is(realmId)
+                .get();
+        MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
+
+        if (user == null) {
+            return null;
+        } else {
+            return new UserAdapter(user, invocationContext);
+        }
+    }
+
+    @Override
+    public UserModel getUserByEmail(String email, String realmId) {
+        DBObject query = new QueryBuilder()
+                .and("email").is(email)
+                .and("realmId").is(realmId)
+                .get();
+        MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
+
+        if (user == null) {
+            return null;
+        } else {
+            return new UserAdapter(user, invocationContext);
+        }
+    }
+
+    @Override
     public boolean removeRealm(String id) {
         return getMongoStore().removeEntity(MongoRealmEntity.class, id, invocationContext);
     }
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 da20338..8a1d112 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
@@ -994,7 +994,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
 
     @Override
     public boolean validatePassword(UserModel user, String password) {
-        for (CredentialEntity cred : ((UserAdapter) user).getUser().getCredentials()) {
+        for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
             if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
                 return new Pbkdf2PasswordEncoder(cred.getSalt()).verify(password, cred.getValue());
             }
@@ -1005,7 +1005,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     @Override
     public boolean validateTOTP(UserModel user, String password, String token) {
         if (!validatePassword(user, password)) return false;
-        for (CredentialEntity cred : ((UserAdapter) user).getUser().getCredentials()) {
+        for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
             if (cred.getType().equals(UserCredentialModel.TOTP)) {
                 return new TimeBasedOTP().validate(token, cred.getValue().getBytes());
             }
@@ -1014,74 +1014,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     }
 
 
-    @Override
-    public void updateCredential(UserModel user, UserCredentialModel cred) {
-        MongoUserEntity userEntity = ((UserAdapter) user).getUser();
-        CredentialEntity credentialEntity = getCredentialEntity(userEntity, cred.getType());
-
-        if (credentialEntity == null) {
-            credentialEntity = new CredentialEntity();
-            credentialEntity.setType(cred.getType());
-            credentialEntity.setDevice(cred.getDevice());
-            userEntity.getCredentials().add(credentialEntity);
-        }
-        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-            byte[] salt = Pbkdf2PasswordEncoder.getSalt();
-            credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue()));
-            credentialEntity.setSalt(salt);
-        } else {
-            credentialEntity.setValue(cred.getValue());
-        }
-        credentialEntity.setDevice(cred.getDevice());
-
-        getMongoStore().updateEntity(userEntity, invocationContext);
-    }
-
-    private CredentialEntity getCredentialEntity(MongoUserEntity userEntity, String credType) {
-        for (CredentialEntity entity : userEntity.getCredentials()) {
-            if (entity.getType().equals(credType)) {
-                return entity;
-            }
-        }
-
-        return null;
-    }
 
-    @Override
-    public List<UserCredentialValueModel> getCredentialsDirectly(UserModel user) {
-        MongoUserEntity userEntity = ((UserAdapter) user).getUser();
-        List<CredentialEntity> credentials = userEntity.getCredentials();
-        List<UserCredentialValueModel> result = new ArrayList<UserCredentialValueModel>();
-        for (CredentialEntity credEntity : credentials) {
-            UserCredentialValueModel credModel = new UserCredentialValueModel();
-            credModel.setType(credEntity.getType());
-            credModel.setDevice(credEntity.getDevice());
-            credModel.setValue(credEntity.getValue());
-            credModel.setSalt(credEntity.getSalt());
-
-            result.add(credModel);
-        }
-
-        return result;
-    }
-
-    @Override
-    public void updateCredentialDirectly(UserModel user, UserCredentialValueModel credModel) {
-        MongoUserEntity userEntity = ((UserAdapter) user).getUser();
-        CredentialEntity credentialEntity = getCredentialEntity(userEntity, credModel.getType());
-
-        if (credentialEntity == null) {
-            credentialEntity = new CredentialEntity();
-            credentialEntity.setType(credModel.getType());
-            userEntity.getCredentials().add(credentialEntity);
-        }
-
-        credentialEntity.setValue(credModel.getValue());
-        credentialEntity.setSalt(credModel.getSalt());
-        credentialEntity.setDevice(credModel.getDevice());
-
-        getMongoStore().updateEntity(userEntity, invocationContext);
-    }
 
     @Override
     public UserModel getUserBySocialLink(SocialLinkModel socialLink) {
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 c713b9f..7cc178b 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
@@ -1,12 +1,18 @@
 package org.keycloak.models.mongo.keycloak.adapters;
 
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserCredentialValueModel;
 import org.keycloak.models.UserModel;
+import org.keycloak.models.entities.CredentialEntity;
 import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
+import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -168,6 +174,72 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
         updateUser();
     }
 
+    @Override
+    public void updateCredential(UserCredentialModel cred) {
+        CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
+
+        if (credentialEntity == null) {
+            credentialEntity = new CredentialEntity();
+            credentialEntity.setType(cred.getType());
+            credentialEntity.setDevice(cred.getDevice());
+            user.getCredentials().add(credentialEntity);
+        }
+        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+            byte[] salt = Pbkdf2PasswordEncoder.getSalt();
+            credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue()));
+            credentialEntity.setSalt(salt);
+        } else {
+            credentialEntity.setValue(cred.getValue());
+        }
+        credentialEntity.setDevice(cred.getDevice());
+
+        getMongoStore().updateEntity(user, invocationContext);
+    }
+
+    private CredentialEntity getCredentialEntity(MongoUserEntity userEntity, String credType) {
+        for (CredentialEntity entity : userEntity.getCredentials()) {
+            if (entity.getType().equals(credType)) {
+                return entity;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public List<UserCredentialValueModel> getCredentialsDirectly() {
+        List<CredentialEntity> credentials = user.getCredentials();
+        List<UserCredentialValueModel> result = new ArrayList<UserCredentialValueModel>();
+        for (CredentialEntity credEntity : credentials) {
+            UserCredentialValueModel credModel = new UserCredentialValueModel();
+            credModel.setType(credEntity.getType());
+            credModel.setDevice(credEntity.getDevice());
+            credModel.setValue(credEntity.getValue());
+            credModel.setSalt(credEntity.getSalt());
+
+            result.add(credModel);
+        }
+
+        return result;
+    }
+
+    @Override
+    public void updateCredentialDirectly(UserCredentialValueModel credModel) {
+        CredentialEntity credentialEntity = getCredentialEntity(user, credModel.getType());
+
+        if (credentialEntity == null) {
+            credentialEntity = new CredentialEntity();
+            credentialEntity.setType(credModel.getType());
+            user.getCredentials().add(credentialEntity);
+        }
+
+        credentialEntity.setValue(credModel.getValue());
+        credentialEntity.setSalt(credModel.getSalt());
+        credentialEntity.setDevice(credModel.getDevice());
+
+        getMongoStore().updateEntity(user, invocationContext);
+    }
+
     protected void updateUser() {
         super.updateMongoEntity();
     }
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java b/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
index 84d4586..d6d5e7b 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
@@ -133,7 +133,7 @@ public class AdapterTest extends AbstractModelTest {
         UserCredentialModel cred = new UserCredentialModel();
         cred.setType(CredentialRepresentation.PASSWORD);
         cred.setValue("geheim");
-        realmModel.updateCredential(user, cred);
+        user.updateCredential(cred);
         Assert.assertTrue(realmModel.validatePassword(user, "geheim"));
     }
 
@@ -166,7 +166,7 @@ public class AdapterTest extends AbstractModelTest {
         UserCredentialModel cred = new UserCredentialModel();
         cred.setType(CredentialRepresentation.PASSWORD);
         cred.setValue("password");
-        realmModel.updateCredential(user, cred);
+        user.updateCredential(cred);
 
         commit();
 
@@ -208,7 +208,7 @@ public class AdapterTest extends AbstractModelTest {
         UserCredentialModel cred = new UserCredentialModel();
         cred.setType(CredentialRepresentation.PASSWORD);
         cred.setValue("password");
-        realmModel.updateCredential(user, cred);
+        user.updateCredential(cred);
 
         OAuthClientModel client = realmModel.addOAuthClient("client");
 
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java b/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java
index a603226..24e894f 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java
@@ -107,7 +107,7 @@ public class AuthenticationManagerTest extends AbstractModelTest {
         credential.setType(CredentialRepresentation.TOTP);
         credential.setValue(totpSecret);
 
-        realm.updateCredential(user, credential);
+        user.updateCredential(credential);
 
         user.setTotp(true);
 
@@ -175,7 +175,7 @@ public class AuthenticationManagerTest extends AbstractModelTest {
         credential.setType(CredentialRepresentation.PASSWORD);
         credential.setValue("password");
 
-        realm.updateCredential(user, credential);
+        user.updateCredential(credential);
 
         formData = new MultivaluedMapImpl<String, String>();
         formData.add("username", "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 5d28b60..961b674 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
@@ -63,7 +63,7 @@ public class AuthProvidersExternalModelTest extends AbstractModelTest {
         UserCredentialModel credential = new UserCredentialModel();
         credential.setType(CredentialRepresentation.PASSWORD);
         credential.setValue("password");
-        realm1.updateCredential(john, credential);
+        john.updateCredential(credential);
 
         am = new AuthenticationManager(providerSession);
     }
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersLDAPTest.java b/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersLDAPTest.java
index 24317a8..083a967 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersLDAPTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersLDAPTest.java
@@ -112,7 +112,7 @@ public class AuthProvidersLDAPTest extends AbstractModelTest {
         UserCredentialModel credential = new UserCredentialModel();
         credential.setType(CredentialRepresentation.PASSWORD);
         credential.setValue("pass");
-        realm.updateCredential(realmUser, credential);
+        realmUser.updateCredential(credential);
 
         // User doesn't exists
         MultivaluedMap<String, String> formData = AuthProvidersExternalModelTest.createFormData("invalid", "invalid");
diff --git a/model/tests/src/test/java/org/keycloak/model/test/MultipleRealmsTest.java b/model/tests/src/test/java/org/keycloak/model/test/MultipleRealmsTest.java
index 35a0981..26dff19 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/MultipleRealmsTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/MultipleRealmsTest.java
@@ -37,8 +37,8 @@ public class MultipleRealmsTest extends AbstractModelTest {
         Assert.assertNotEquals(r1user1.getId(), r2user1.getId());
 
         // Test password
-        realm1.updateCredential(r1user1, UserCredentialModel.password("pass1"));
-        realm2.updateCredential(r2user1, UserCredentialModel.password("pass2"));
+        r1user1.updateCredential(UserCredentialModel.password("pass1"));
+        r2user1.updateCredential(UserCredentialModel.password("pass2"));
 
         Assert.assertTrue(realm1.validatePassword(r1user1, "pass1"));
         Assert.assertFalse(realm1.validatePassword(r1user1, "pass2"));
diff --git a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
index 653cdc6..121dec7 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
@@ -71,7 +71,7 @@ public class ApplianceBootstrap {
         UserCredentialModel password = new UserCredentialModel();
         password.setType(UserCredentialModel.PASSWORD);
         password.setValue("admin");
-        realm.updateCredential(adminUser, password);
+        adminUser.updateCredential(password);
         adminUser.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
 
         RoleModel adminRole = realm.getRole(AdminRoles.ADMIN);
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index c897d77..73634cf 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -569,7 +569,7 @@ public class RealmManager {
         if (userRep.getCredentials() != null) {
             for (CredentialRepresentation cred : userRep.getCredentials()) {
                 UserCredentialModel credential = fromRepresentation(cred);
-                newRealm.updateCredential(user, credential);
+                user.updateCredential(credential);
             }
         }
         if (userRep.getAuthenticationLink() != null) {
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index a9ee774..3ba8d16 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -402,7 +402,7 @@ public class AccountService {
         UserCredentialModel credentials = new UserCredentialModel();
         credentials.setType(CredentialRepresentation.TOTP);
         credentials.setValue(totpSecret);
-        realm.updateCredential(user, credentials);
+        user.updateCredential(credentials);
 
         user.setTotp(true);
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index 8297e7f..f26c8d7 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -766,7 +766,7 @@ public class UsersResource {
         }
 
         UserCredentialModel cred = RealmManager.fromRepresentation(pass);
-        realm.updateCredential(user, cred);
+        user.updateCredential(cred);
         user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java b/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java
index 335b10b..7132d6e 100755
--- a/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java
@@ -171,7 +171,7 @@ public class RequiredActionsService {
         UserCredentialModel credentials = new UserCredentialModel();
         credentials.setType(CredentialRepresentation.TOTP);
         credentials.setValue(totpSecret);
-        realm.updateCredential(user, credentials);
+        user.updateCredential(credentials);
 
         user.setTotp(true);
 
diff --git a/testsuite/integration/src/main/resources/log4j.properties b/testsuite/integration/src/main/resources/log4j.properties
index bc27773..5700df4 100755
--- a/testsuite/integration/src/main/resources/log4j.properties
+++ b/testsuite/integration/src/main/resources/log4j.properties
@@ -4,4 +4,4 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
 log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] %m%n
 
-log4j.logger.org.keycloak=debug
\ No newline at end of file
+log4j.logger.org.keycloak=warn
\ No newline at end of file
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
index 7bec7a7..359b287 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
@@ -87,7 +87,7 @@ public class AccountTest {
             UserCredentialModel creds = new UserCredentialModel();
             creds.setType(CredentialRepresentation.PASSWORD);
             creds.setValue("password");
-            appRealm.updateCredential(user2, creds);
+            user2.updateCredential(creds);
         }
     });
 
@@ -153,7 +153,7 @@ public class AccountTest {
                 cred.setType(CredentialRepresentation.PASSWORD);
                 cred.setValue("password");
 
-                appRealm.updateCredential(user, cred);
+                user.updateCredential(cred);
             }
         });
     }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
index eee56e0..cf86b18 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
@@ -64,7 +64,7 @@ public class ProfileTest {
             UserCredentialModel creds = new UserCredentialModel();
             creds.setType(CredentialRepresentation.PASSWORD);
             creds.setValue("password");
-            appRealm.updateCredential(user2, creds);
+            user2.updateCredential(creds);
 
             ApplicationModel app = appRealm.getApplicationNameMap().get("test-app");
             appRealm.addScopeMapping(app, accountApp.getRole(AccountRoles.VIEW_PROFILE));
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
index c354f0d..fb29613 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
@@ -77,12 +77,12 @@ public class CompositeRoleTest {
 
             final UserModel realmComposite1User = realm.addUser("REALM_COMPOSITE_1_USER");
             realmComposite1User.setEnabled(true);
-            realm.updateCredential(realmComposite1User, UserCredentialModel.password("password"));
+            realmComposite1User.updateCredential(UserCredentialModel.password("password"));
             realm.grantRole(realmComposite1User, realmComposite1);
 
             final UserModel realmRole1User = realm.addUser("REALM_ROLE_1_USER");
             realmRole1User.setEnabled(true);
-            realm.updateCredential(realmRole1User, UserCredentialModel.password("password"));
+            realmRole1User.updateCredential(UserCredentialModel.password("password"));
             realm.grantRole(realmRole1User, realmRole1);
 
             final ApplicationModel realmComposite1Application = new ApplicationManager(manager).createApplication(realm, "REALM_COMPOSITE_1_APPLICATION");
@@ -116,12 +116,12 @@ public class CompositeRoleTest {
 
             final UserModel realmAppCompositeUser = realm.addUser("REALM_APP_COMPOSITE_USER");
             realmAppCompositeUser.setEnabled(true);
-            realm.updateCredential(realmAppCompositeUser, UserCredentialModel.password("password"));
+            realmAppCompositeUser.updateCredential(UserCredentialModel.password("password"));
             realm.grantRole(realmAppCompositeUser, realmAppCompositeRole);
 
             final UserModel realmAppRoleUser = realm.addUser("REALM_APP_ROLE_USER");
             realmAppRoleUser.setEnabled(true);
-            realm.updateCredential(realmAppRoleUser, UserCredentialModel.password("password"));
+            realmAppRoleUser.updateCredential(UserCredentialModel.password("password"));
             realm.grantRole(realmAppRoleUser, appRole2);
 
             final ApplicationModel appCompositeApplication = new ApplicationManager(manager).createApplication(realm, "APP_COMPOSITE_APPLICATION");
@@ -139,7 +139,7 @@ public class CompositeRoleTest {
 
             final UserModel appCompositeUser = realm.addUser("APP_COMPOSITE_USER");
             appCompositeUser.setEnabled(true);
-            realm.updateCredential(appCompositeUser, UserCredentialModel.password("password"));
+            appCompositeUser.updateCredential(UserCredentialModel.password("password"));
             realm.grantRole(appCompositeUser, realmAppCompositeRole);
             realm.grantRole(appCompositeUser, realmComposite1);
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AuthProvidersIntegrationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AuthProvidersIntegrationTest.java
index cd367c9..1ad65e4 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AuthProvidersIntegrationTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AuthProvidersIntegrationTest.java
@@ -104,7 +104,7 @@ public class AuthProvidersIntegrationTest {
         creds.setType(CredentialRepresentation.PASSWORD);
         creds.setValue(password);
 
-        realm.updateCredential(user, creds);
+        user.updateCredential(creds);
         return user;
     }
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTest.java
old mode 100644
new mode 100755
index af561d1..277bc7a
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTest.java
@@ -61,7 +61,7 @@ public class LoginTest {
             creds.setType(CredentialRepresentation.PASSWORD);
             creds.setValue("password");
 
-            appRealm.updateCredential(user, creds);
+            user.updateCredential(creds);
         }
     });
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java
index 15710b1..eadf367 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java
@@ -63,7 +63,7 @@ public class LoginTotpTest {
             UserCredentialModel credentials = new UserCredentialModel();
             credentials.setType(CredentialRepresentation.TOTP);
             credentials.setValue("totpSecret");
-            appRealm.updateCredential(user, credentials);
+            user.updateCredential(credentials);
 
             user.setTotp(true);
             appRealm.setAuditListeners(Collections.singleton("dummy"));
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java
index ae5cfce..0946727 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java
@@ -72,7 +72,7 @@ public class ResetPasswordTest {
             creds.setType(CredentialRepresentation.PASSWORD);
             creds.setValue("password");
 
-            appRealm.updateCredential(user, creds);
+            user.updateCredential(creds);
             appRealm.setAuditListeners(Collections.singleton("dummy"));
         }
     }));
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 f0b9318..c5d3a02 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
@@ -22,14 +22,20 @@
 package org.keycloak.testsuite.perf;
 
 import org.apache.http.NameValuePair;
+import org.apache.http.client.CookieStore;
+import org.apache.http.client.HttpClient;
 import org.apache.http.client.utils.URLEncodedUtils;
+import org.apache.http.cookie.Cookie;
+import org.apache.http.impl.client.DefaultHttpClient;
 import org.jboss.resteasy.client.jaxrs.ResteasyClient;
 import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
+import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;
 import org.junit.Assert;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
+import org.keycloak.adapters.HttpClientBuilder;
 import org.keycloak.audit.Details;
 import org.keycloak.audit.Errors;
 import org.keycloak.audit.Event;
@@ -53,6 +59,8 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 
 import java.net.URI;
+import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -72,15 +80,22 @@ public class AccessTokenPerfTest {
 
     public static class BrowserLogin implements Runnable
     {
+
+        private WebDriver driver;
+
+        public BrowserLogin() {
+            driver = WebRule.createWebDriver();
+        }
+
         @Override
         public void run() {
-            WebDriver driver = WebRule.createWebDriver();
+            driver.manage().deleteAllCookies();
             OAuthClient oauth = new OAuthClient(driver);
             oauth.doLogin("test-user@localhost", "password");
             String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
             AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
             Assert.assertEquals(200, response.getStatusCode());
-            driver.close();
+            count.incrementAndGet();
 
         }
     }
@@ -105,7 +120,30 @@ public class AccessTokenPerfTest {
 
 
         public JaxrsClientLogin() {
-            this.client = new ResteasyClientBuilder().build();
+            DefaultHttpClient httpClient = (DefaultHttpClient) new HttpClientBuilder().build();
+            httpClient.setCookieStore(new CookieStore() {
+                @Override
+                public void addCookie(Cookie cookie) {
+                    //To change body of implemented methods use File | Settings | File Templates.
+                }
+
+                @Override
+                public List<Cookie> getCookies() {
+                    return Collections.emptyList();
+                }
+
+                @Override
+                public boolean clearExpired(Date date) {
+                    return false;  //To change body of implemented methods use File | Settings | File Templates.
+                }
+
+                @Override
+                public void clear() {
+                    //To change body of implemented methods use File | Settings | File Templates.
+                }
+            });
+            ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
+            this.client = new ResteasyClientBuilder().httpEngine(engine).build();
         }
 
         public String getLoginFormUrl(String state) {
@@ -142,7 +180,7 @@ public class AccessTokenPerfTest {
 
         @Override
         public void run() {
-            this.client = new ResteasyClientBuilder().build();
+            //this.client = new ResteasyClientBuilder().build();
             String state = "42";
             Response response = client.target(getLoginFormUrl(state)).request().get();
             URI uri = null;
@@ -173,7 +211,7 @@ public class AccessTokenPerfTest {
                     .header(HttpHeaders.AUTHORIZATION, authorization)
                     .post(Entity.form(form), String.class);
             count.incrementAndGet();
-            client.close();
+            //client.close();
         }
 
         public String getCode(URI uri) {
@@ -196,7 +234,7 @@ public class AccessTokenPerfTest {
     @Test
     public void perfJaxrsClientLogin()
     {
-        long ITERATIONS = 1;
+        long ITERATIONS = 100;
         JaxrsClientLogin login = new JaxrsClientLogin();
         long start = System.currentTimeMillis();
         for (int i = 0; i < ITERATIONS; i++) {
@@ -207,12 +245,13 @@ public class AccessTokenPerfTest {
     }
 
     @Test
-    public void perfBrowserLogin() throws Exception
+    public void perfBrowserLogin()
     {
-        long ITERATIONS = 1;
+        long ITERATIONS = 100;
         long start = System.currentTimeMillis();
+        BrowserLogin login = new BrowserLogin();
         for (int i = 0; i < ITERATIONS; i++) {
-            new BrowserLogin().run();
+            login.run();
         }
         long end = System.currentTimeMillis() - start;
         System.out.println("took: " + end);
@@ -220,7 +259,7 @@ public class AccessTokenPerfTest {
 
     @Test
     public void multiThread() throws Exception {
-        int num_threads = 1;
+        int num_threads = 20;
         Thread[] threads = new Thread[num_threads];
         for (int i = 0; i < num_threads; i++) {
             threads[i] = new Thread(new Runnable() {
diff --git a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateUsersWorker.java b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateUsersWorker.java
index 62d22af..ae7795d 100755
--- a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateUsersWorker.java
+++ b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateUsersWorker.java
@@ -83,7 +83,7 @@ public class CreateUsersWorker implements Worker {
             UserCredentialModel password = new UserCredentialModel();
             password.setType(CredentialRepresentation.PASSWORD);
             password.setValue(username);
-            realm.updateCredential(user, password);
+            user.updateCredential(password);
         }
 
         // Creating some socialLinks