keycloak-aplcache

concurrency

2/10/2016 5:09:29 PM

Changes

Details

diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/content/standalone/configuration/keycloak-server.json b/distribution/feature-packs/server-feature-pack/src/main/resources/content/standalone/configuration/keycloak-server.json
old mode 100644
new mode 100755
index b96d61b..41dab85
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/content/standalone/configuration/keycloak-server.json
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/content/standalone/configuration/keycloak-server.json
@@ -28,12 +28,6 @@
         }
     },
 
-    "realmCache": {
-        "infinispan" : {
-            "enabled": true
-        }
-    },
-
     "userSessionPersister": {
         "provider": "jpa"
     },
@@ -67,8 +61,16 @@
         }
     },
 
+    "realmCache": {
+        "provider": "infinispan-locking",
+        "infinispan-locking" : {
+            "enabled": true
+        }
+    },
+
     "connectionsInfinispan": {
-        "default" : {
+        "provider": "locking",
+        "locking": {
             "cacheContainer" : "java:comp/env/infinispan/Keycloak"
         }
     }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/counter/RevisionedCacheRealmProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/counter/RevisionedCacheRealmProviderFactory.java
index ae7ca69..d50eb0b 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/counter/RevisionedCacheRealmProviderFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/counter/RevisionedCacheRealmProviderFactory.java
@@ -36,8 +36,6 @@ import org.keycloak.models.cache.CacheRealmProvider;
 import org.keycloak.models.cache.CacheRealmProviderFactory;
 import org.keycloak.models.cache.entities.CachedClient;
 import org.keycloak.models.cache.entities.CachedRealm;
-import org.keycloak.models.cache.infinispan.DefaultCacheRealmProvider;
-import org.keycloak.models.cache.infinispan.InfinispanRealmCache;
 
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -64,7 +62,7 @@ public class RevisionedCacheRealmProviderFactory implements CacheRealmProviderFa
             synchronized (this) {
                 if (realmCache == null) {
                     Cache<String, Object> cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.REALM_CACHE_NAME);
-                    Cache<String, Long> counterCache = session.getProvider(InfinispanConnectionProvider.class).getCache(RevisionedConnectionProviderFactory.COUNTER_CACHE_NAME);
+                    Cache<String, Long> counterCache = session.getProvider(InfinispanConnectionProvider.class).getCache(RevisionedConnectionProviderFactory.VERSION_CACHE_NAME);
                     cache.addListener(new CacheListener());
                     realmCache = new RevisionedRealmCache(cache, counterCache, realmLookup);
                 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/counter/RevisionedConnectionProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/counter/RevisionedConnectionProviderFactory.java
index 4b8c3f6..845a907 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/counter/RevisionedConnectionProviderFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/counter/RevisionedConnectionProviderFactory.java
@@ -26,7 +26,7 @@ import org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFa
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
 public class RevisionedConnectionProviderFactory extends DefaultInfinispanConnectionProviderFactory {
-    public static final String COUNTER_CACHE_NAME = "COUNTER_CACHE";
+    public static final String VERSION_CACHE_NAME = "realmVersions";
 
     protected static final Logger logger = Logger.getLogger(RevisionedConnectionProviderFactory.class);
 
@@ -41,7 +41,7 @@ public class RevisionedConnectionProviderFactory extends DefaultInfinispanConnec
         ConfigurationBuilder counterConfigBuilder = new ConfigurationBuilder();
         Configuration counterCacheConfiguration = counterConfigBuilder.build();
 
-        cacheManager.defineConfiguration(COUNTER_CACHE_NAME, counterCacheConfiguration);
+        cacheManager.defineConfiguration(VERSION_CACHE_NAME, counterCacheConfiguration);
     }
 
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java
index 2009b67..f143ea3 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java
@@ -62,7 +62,7 @@ public class LockingCacheRealmProviderFactory implements CacheRealmProviderFacto
             synchronized (this) {
                 if (realmCache == null) {
                     Cache<String, Object> cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.REALM_CACHE_NAME);
-                    Cache<String, Long> counterCache = session.getProvider(InfinispanConnectionProvider.class).getCache(LockingConnectionProviderFactory.COUNTER_CACHE_NAME);
+                    Cache<String, Long> counterCache = session.getProvider(InfinispanConnectionProvider.class).getCache(LockingConnectionProviderFactory.VERSION_CACHE_NAME);
                     cache.addListener(new CacheListener());
                     realmCache = new LockingRealmCache(cache, counterCache, realmLookup);
                 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingConnectionProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingConnectionProviderFactory.java
index f3e5f29..4a8dfa9 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingConnectionProviderFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingConnectionProviderFactory.java
@@ -28,7 +28,7 @@ import org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFa
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
 public class LockingConnectionProviderFactory extends DefaultInfinispanConnectionProviderFactory {
-    public static final String COUNTER_CACHE_NAME = "COUNTER_CACHE";
+    public static final String VERSION_CACHE_NAME = "realmVersions";
 
     protected static final Logger logger = Logger.getLogger(LockingConnectionProviderFactory.class);
 
@@ -46,7 +46,7 @@ public class LockingConnectionProviderFactory extends DefaultInfinispanConnectio
         counterConfigBuilder.transaction().lockingMode(LockingMode.PESSIMISTIC);
         Configuration counterCacheConfiguration = counterConfigBuilder.build();
 
-        cacheManager.defineConfiguration(COUNTER_CACHE_NAME, counterCacheConfiguration);
+        cacheManager.defineConfiguration(VERSION_CACHE_NAME, counterCacheConfiguration);
     }
 
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/skewed/RepeatableReadWriteSkewRealmCache.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/skewed/RepeatableReadWriteSkewRealmCache.java
index bb0b807..18e5d86 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/skewed/RepeatableReadWriteSkewRealmCache.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/skewed/RepeatableReadWriteSkewRealmCache.java
@@ -113,7 +113,7 @@ public class RepeatableReadWriteSkewRealmCache implements RealmCache {
                 }
             }
         } catch (Exception e) {
-            logger.info("Failed to commit invalidate");
+            logger.trace("Failed to commit invalidate");
         }
         return rtn;
     }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/skewed/RepeatableReadWriteSkewRealmCacheProvider.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/skewed/RepeatableReadWriteSkewRealmCacheProvider.java
index fe7d6c2..5ff2ff8 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/skewed/RepeatableReadWriteSkewRealmCacheProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/skewed/RepeatableReadWriteSkewRealmCacheProvider.java
@@ -221,7 +221,7 @@ public class RepeatableReadWriteSkewRealmCacheProvider implements CacheRealmProv
                     cache.endBatch(true);
                     logger.trace("returning new cached realm");
                 } catch (Exception exception) {
-                    logger.info("failed to add to cache", exception);
+                    logger.trace("failed to add to cache", exception);
                     return model;
                 }
             } else if (realmInvalidations.contains(id)) {
@@ -256,7 +256,7 @@ public class RepeatableReadWriteSkewRealmCacheProvider implements CacheRealmProv
                     cache.endBatch(true);
                     logger.trace("returning new cached realm: " + cached.getName());
                 } catch (Exception exception) {
-                    logger.info("failed to add to cache", exception);
+                    logger.trace("failed to add to cache", exception);
                     return model;
                 }
             } else if (realmInvalidations.contains(cached.getId())) {
@@ -340,7 +340,7 @@ public class RepeatableReadWriteSkewRealmCacheProvider implements CacheRealmProv
                     batchEnded = true;
                     cache.endBatch(true);
                 } catch (Exception exception) {
-                    logger.info("failed to add to cache", exception);
+                    logger.trace("failed to add to cache", exception);
                     return model;
                 }
 
@@ -378,7 +378,7 @@ public class RepeatableReadWriteSkewRealmCacheProvider implements CacheRealmProv
                     batchEnded = true;
                     cache.endBatch(true);
                 } catch (Exception exception) {
-                    logger.info("failed to add to cache", exception);
+                    logger.trace("failed to add to cache", exception);
                     return model;
                 }
 
@@ -416,7 +416,7 @@ public class RepeatableReadWriteSkewRealmCacheProvider implements CacheRealmProv
                     batchEnded = true;
                     cache.endBatch(true);
                 } catch (Exception exception) {
-                    logger.info("failed to add to cache", exception);
+                    logger.trace("failed to add to cache", exception);
                     return model;
                 }
             } else if (appInvalidations.contains(id)) {
@@ -452,7 +452,7 @@ public class RepeatableReadWriteSkewRealmCacheProvider implements CacheRealmProv
                     batchEnded = true;
                     cache.endBatch(true);
                 } catch (Exception exception) {
-                    logger.info("failed to add to cache", exception);
+                    logger.trace("failed to add to cache", exception);
                     return model;
                 }
             } else if (clientTemplateInvalidations.contains(id)) {
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
index d4207d1..311540b 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
@@ -633,7 +633,7 @@ public class ClientAdapter implements ClientModel {
         roleEntity.setClient(entity);
         roleEntity.setClientRole(true);
         roleEntity.setRealmId(realm.getId());
-        //entity.getRoles().add(roleEntity);
+        entity.getRoles().add(roleEntity);
         em.persist(roleEntity);
         em.flush();
         return new RoleAdapter(realm, em, roleEntity);
@@ -650,7 +650,7 @@ public class ClientAdapter implements ClientModel {
         RoleEntity role = RoleAdapter.toRoleEntity(roleModel, em);
         if (!role.isClientRole()) return false;
 
-        //entity.getRoles().remove(role);
+        entity.getRoles().remove(role);
         entity.getDefaultRoles().remove(role);
         String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em);
         em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", role).executeUpdate();
@@ -673,7 +673,6 @@ public class ClientAdapter implements ClientModel {
         for (RoleEntity entity : roles) {
             list.add(new RoleAdapter(realm, em, entity));
         }
-        return list;
         */
         TypedQuery<RoleEntity> query = em.createNamedQuery("getClientRoles", RoleEntity.class);
         query.setParameter("client", entity);
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationExecutionEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationExecutionEntity.java
index 71ecd94..8e759a4 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationExecutionEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationExecutionEntity.java
@@ -19,6 +19,8 @@ package org.keycloak.models.jpa.entities;
 
 import org.keycloak.models.AuthenticationExecutionModel;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
@@ -43,6 +45,7 @@ import javax.persistence.Table;
 public class AuthenticationExecutionEntity {
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @ManyToOne(fetch = FetchType.LAZY)
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationFlowEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationFlowEntity.java
index 886dd43..402acf1 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationFlowEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationFlowEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -44,6 +46,7 @@ import java.util.Collection;
 public class AuthenticationFlowEntity {
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @ManyToOne(fetch = FetchType.LAZY)
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticatorConfigEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticatorConfigEntity.java
index a35c03e..9057683 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticatorConfigEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticatorConfigEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
@@ -40,6 +42,7 @@ import java.util.Map;
 public class AuthenticatorConfigEntity {
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @Column(name="ALIAS")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
index cc9b36a..15544c6 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CascadeType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
@@ -53,6 +55,7 @@ public class ClientEntity {
 
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     private String id;
     @Column(name = "NAME")
     private String name;
@@ -151,8 +154,8 @@ public class ClientEntity {
     @Column(name="NODE_REREG_TIMEOUT")
     private int nodeReRegistrationTimeout;
 
-    //@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, mappedBy = "client")
-    //Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
+    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, mappedBy = "client")
+    Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
 
     @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
     @JoinTable(name="CLIENT_DEFAULT_ROLES", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="ROLE_ID")})
@@ -348,7 +351,6 @@ public class ClientEntity {
         this.managementUrl = managementUrl;
     }
 
-    /*
     public Collection<RoleEntity> getRoles() {
         return roles;
     }
@@ -356,7 +358,6 @@ public class ClientEntity {
     public void setRoles(Collection<RoleEntity> roles) {
         this.roles = roles;
     }
-    */
 
     public Collection<RoleEntity> getDefaultRoles() {
         return defaultRoles;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientTemplateEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientTemplateEntity.java
index 1f27816..280a257 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientTemplateEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientTemplateEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CascadeType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
@@ -48,6 +50,7 @@ public class ClientTemplateEntity {
 
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     private String id;
     @Column(name = "NAME")
     private String name;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java
index 4e54c51..ceb284c 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/CredentialEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
@@ -42,6 +44,7 @@ import javax.persistence.Table;
 public class CredentialEntity {
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @Column(name="TYPE")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/GroupAttributeEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/GroupAttributeEntity.java
index b784d82..a5dbfc4 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/GroupAttributeEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/GroupAttributeEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
@@ -42,6 +44,7 @@ public class GroupAttributeEntity {
 
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @ManyToOne(fetch= FetchType.LAZY)
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/GroupEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/GroupEntity.java
index 420929a..9eadbc8 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/GroupEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/GroupEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -47,6 +49,7 @@ import java.util.Collection;
 public class GroupEntity {
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @Column(name = "NAME")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java
index 6074663..77ca614 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
@@ -44,6 +46,7 @@ public class IdentityProviderEntity {
 
     @Id
     @Column(name="INTERNAL_ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String internalId;
 
     @ManyToOne(fetch = FetchType.LAZY)
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderMapperEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderMapperEntity.java
index a7afa8d..2011e93 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderMapperEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderMapperEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
@@ -39,6 +41,7 @@ public class IdentityProviderMapperEntity {
 
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @Column(name="NAME")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/MigrationModelEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/MigrationModelEntity.java
index 148d009..ce4d845 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/MigrationModelEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/MigrationModelEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
@@ -37,6 +39,7 @@ public class MigrationModelEntity {
     public static final String SINGLETON_ID = "SINGLETON";
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     private String id;
 
     @Column(name="VERSION", length = 36)
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java
index bb51ad9..b6e3071 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
@@ -39,6 +41,7 @@ public class ProtocolMapperEntity {
 
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @Column(name="NAME")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
index 87cc7e5..da369f0 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CascadeType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
@@ -53,6 +55,7 @@ import java.util.Set;
 public class RealmEntity {
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @Column(name="NAME", unique = true)
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredActionProviderEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredActionProviderEntity.java
index 95d3373..d8b43fb 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredActionProviderEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RequiredActionProviderEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
@@ -42,6 +44,7 @@ import java.util.Map;
 public class RequiredActionProviderEntity {
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @Column(name="ALIAS")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
index 6a6ca5f..b94a743 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
@@ -17,6 +17,11 @@
 
 package org.keycloak.models.jpa.entities;
 
+import org.hibernate.annotations.DynamicInsert;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
@@ -37,6 +42,8 @@ import java.util.Collection;
  * @version $Revision: 1 $
  */
 @Entity
+//@DynamicInsert
+//@DynamicUpdate
 @Table(name="KEYCLOAK_ROLE", uniqueConstraints = {
         @UniqueConstraint(columnNames = { "NAME", "CLIENT_REALM_CONSTRAINT" })
 })
@@ -49,6 +56,7 @@ import java.util.Collection;
 public class RoleEntity {
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     private String id;
 
     @Column(name = "NAME")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserAttributeEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserAttributeEntity.java
index e09c1bb..263757f 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserAttributeEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserAttributeEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
@@ -48,6 +50,7 @@ public class UserAttributeEntity {
 
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @ManyToOne(fetch= FetchType.LAZY)
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java
index a349d80..c1098e2 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java
@@ -20,6 +20,8 @@ package org.keycloak.models.jpa.entities;
 import java.util.ArrayList;
 import java.util.Collection;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -51,6 +53,7 @@ public class UserConsentEntity {
 
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @ManyToOne(fetch= FetchType.LAZY)
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 b1c8c04..d110a17 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
@@ -19,6 +19,8 @@ package org.keycloak.models.jpa.entities;
 
 import org.keycloak.models.utils.KeycloakModelUtils;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -59,6 +61,7 @@ import java.util.Collection;
 public class UserEntity {
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @Column(name = "USERNAME")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserFederationMapperEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserFederationMapperEntity.java
index 54989f2..41350f6 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserFederationMapperEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserFederationMapperEntity.java
@@ -19,6 +19,8 @@ package org.keycloak.models.jpa.entities;
 
 import java.util.Map;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
@@ -41,6 +43,7 @@ public class UserFederationMapperEntity {
 
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @Column(name="NAME")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserFederationProviderEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserFederationProviderEntity.java
index 7b841ca..f7cab7f 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserFederationProviderEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserFederationProviderEntity.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.models.jpa.entities;
 
+import javax.persistence.Access;
+import javax.persistence.AccessType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
@@ -39,6 +41,7 @@ public class UserFederationProviderEntity {
 
     @Id
     @Column(name="ID", length = 36)
+    @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity.  This avoids an extra SQL
     protected String id;
 
     @ManyToOne(fetch = FetchType.LAZY)
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ConcurrencyTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ConcurrencyTest.java
index f3bacba..f510f04 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ConcurrencyTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ConcurrencyTest.java
@@ -42,13 +42,12 @@ import static org.junit.Assert.*;
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-@Ignore
 public class ConcurrencyTest extends AbstractClientTest {
 
     private static final Logger log = Logger.getLogger(ConcurrencyTest.class);
 
-    private static final int DEFAULT_THREADS = 10;
-    private static final int DEFAULT_ITERATIONS = 100;
+    private static final int DEFAULT_THREADS = 1;
+    private static final int DEFAULT_ITERATIONS = 5;
 
     // If enabled only one request is allowed at the time. Useful for checking that test is working.
     private static final boolean SYNCHRONIZED = false;
@@ -146,6 +145,8 @@ public class ConcurrencyTest extends AbstractClientTest {
         final String clientId = ApiUtil.getCreatedId(response);
         response.close();
 
+        System.out.println("*********************************************");
+
         run(new KeycloakRunnable() {
             @Override
             public void run(Keycloak keycloak, RealmResource realm, int threadNum, int iterationNum) {
@@ -160,6 +161,7 @@ public class ConcurrencyTest extends AbstractClientTest {
         });
         long end = System.currentTimeMillis() - start;
         System.out.println("createClientRole took " + end);
+        System.out.println("*********************************************");
 
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json
old mode 100644
new mode 100755
index 0978231..5cef402
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json
@@ -26,14 +26,6 @@
         "provider": "${keycloak.userSessionPersister.provider:jpa}"
     },
 
-    "userSessions": {
-        "provider" : "${keycloak.userSessions.provider:infinispan}"
-    },
-
-    "realmCache": {
-        "provider": "${keycloak.realm.cache.provider:infinispan}"
-    },
-
     "userCache": {
         "provider": "${keycloak.user.cache.provider:infinispan}",
         "mem": {
@@ -41,6 +33,10 @@
         }
     },
 
+    "userSessions": {
+        "provider" : "${keycloak.userSessions.provider:infinispan}"
+    },
+
     "timer": {
         "provider": "basic"
     },
@@ -99,6 +95,23 @@
         }
     },
 
+    "realmCache": {
+        "provider": "infinispan-locking",
+        "infinispan-locking" : {
+            "enabled": true
+        }
+    },
+
+    "connectionsInfinispan": {
+        "provider": "locking",
+        "locking": {
+            "clustered": "${keycloak.connectionsInfinispan.clustered:false}",
+            "async": "${keycloak.connectionsInfinispan.async:true}",
+            "sessionsOwners": "${keycloak.connectionsInfinispan.sessionsOwners:2}"
+        }
+    },
+
+
     "truststore": {
         "file": {
             "file": "${keycloak.truststore.file:src/main/keystore/keycloak.truststore}",
diff --git a/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml b/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml
old mode 100644
new mode 100755
index 57cd94b..74fbae3
--- a/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml
+++ b/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml
@@ -30,6 +30,9 @@
                 <local-cache name="sessions"/>
                 <local-cache name="offlineSessions"/>
                 <local-cache name="loginFailures"/>
+                <local-cache name="realmVersions">
+                    <transaction mode="BATCH" locking="PESSIMISTIC"/>
+                </local-cache>
             </cache-container>
             <cache-container name="server" default-cache="default" module="org.wildfly.clustering.server">
                 <local-cache name="default">
@@ -87,6 +90,9 @@
                 <distributed-cache name="sessions" mode="SYNC" owners="1"/>
                 <distributed-cache name="offlineSessions" mode="SYNC" owners="1"/>
                 <distributed-cache name="loginFailures" mode="SYNC" owners="1"/>
+                <local-cache name="realmVersions">
+                    <transaction mode="BATCH" locking="PESSIMISTIC"/>
+                </local-cache>
             </cache-container>
             <cache-container name="server" aliases="singleton cluster" default-cache="default" module="org.wildfly.clustering.server">
                 <transport lock-timeout="60000"/>