keycloak-uncached

Changes

model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/KeycloakRemoteStore.java 176(+0 -176)

model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/KeycloakRemoteStoreConfiguration.java 55(+0 -55)

model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/KeycloakRemoteStoreConfigurationBuilder.java 78(+0 -78)

Details

diff --git a/misc/CrossDataCenter.md b/misc/CrossDataCenter.md
index 21dd586..b5a5670 100644
--- a/misc/CrossDataCenter.md
+++ b/misc/CrossDataCenter.md
@@ -116,64 +116,62 @@ Keycloak servers setup
  <cache-container name="keycloak" jndi-name="infinispan/Keycloak" module="org.keycloak.keycloak-model-infinispan">
 ``` 
 
-3.3) Add the `store` under `work` cache:
+3.3) Add the `remote-store` under `work` cache:
 
 ```xml
 <replicated-cache name="work" mode="SYNC">
-    <store class="org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder" passivation="false" fetch-state="false" purge="false" preload="false" shared="true">   
-        <property name="rawValues">true</property>	
+    <remote-store cache="work" remote-servers="remote-cache" passivation="false" fetch-state="false" purge="false" preload="false" shared="true">
+        <property name="rawValues">true</property>
         <property name="marshaller">org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory</property>
-        <property name="remoteCacheName">work</property> 
-        <property name="sessionCache">false</property>
-    </store>
+    </remote-store>
 </replicated-cache>
 ```
 
-3.5) Add the `store` like this under `sessions` cache:
+3.5) Add the `remote-store` like this under `sessions` cache:
 
 ```xml
 <distributed-cache name="sessions" mode="SYNC" owners="1">
-    <store class="org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder" passivation="false" fetch-state="false" purge="false" preload="false" shared="true">   
-        <property name="remoteCacheName">sessions</property> 
-        <property name="useConfigTemplateFromCache">work</property>
-        <property name="sessionCache">true</property>
-    </store>
+    <remote-store cache="sessions" remote-servers="remote-cache" passivation="false" fetch-state="false" purge="false" preload="false" shared="true">   
+        <property name="rawValues">true</property>
+        <property name="marshaller">org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory</property>
+    </remote-store>
 </distributed-cache>
 ```
 
-3.6) Same for `offlineSessions` and `loginFailures` caches (The only difference from `sessions` cache is, that `remoteCacheName` property value are different:
+3.6) Same for `offlineSessions`, `loginFailures`, and `actionTokens` caches (the only difference from `sessions` cache is that `cache` property value are different):
 
 ```xml
 <distributed-cache name="offlineSessions" mode="SYNC" owners="1">
-    <store class="org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder" passivation="false" fetch-state="false" purge="false" preload="false" shared="true">   
-        <property name="remoteCacheName">offlineSessions</property> 
-        <property name="useConfigTemplateFromCache">work</property>
-        <property name="sessionCache">true</property>
-    </store>
+    <remote-store cache="offlineSessions" remote-servers="remote-cache" passivation="false" fetch-state="false" purge="false" preload="false" shared="true">
+        <property name="rawValues">true</property>
+        <property name="marshaller">org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory</property>
+    </remote-store>
 </distributed-cache>
 
 <distributed-cache name="loginFailures" mode="SYNC" owners="1">
-    <store class="org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder" passivation="false" fetch-state="false" purge="false" preload="false" shared="true">   
-        <property name="remoteCacheName">loginFailures</property> 
-        <property name="useConfigTemplateFromCache">work</property>
-        <property name="sessionCache">true</property>
-    </store>
+    <remote-store cache="loginFailures" remote-servers="remote-cache" passivation="false" fetch-state="false" purge="false" preload="false" shared="true">
+        <property name="rawValues">true</property>
+        <property name="marshaller">org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory</property>
+    </remote-store>
 </distributed-cache>
-```
-
-3.7) The configuration of `actionTokens` cache have different `remoteCacheName`, `sessionCache` and the `preload` attribute:
 
-```xml
 <distributed-cache name="actionTokens" mode="SYNC" owners="2">
     <eviction max-entries="-1" strategy="NONE"/>
     <expiration max-idle="-1" interval="300000"/>
-    <store class="org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder" passivation="false" fetch-state="false" purge="false" preload="true" shared="true">   
-        <property name="remoteCacheName">actionTokens</property> 
-        <property name="useConfigTemplateFromCache">work</property>
-        <property name="sessionCache">false</property>
-    </store>
+    <remote-store cache="actionTokens" remote-servers="remote-cache" passivation="false" fetch-state="false" purge="false" preload="true" shared="true">
+        <property name="rawValues">true</property>
+        <property name="marshaller">org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory</property>
+    </remote-store>
 </distributed-cache>
-```            
+```
+
+3.7) Add outbound socket binding for the remote store into `socket-binding-group` configuration:
+
+```xml
+<outbound-socket-binding name="remote-cache">
+    <remote-destination host="${remote.cache.host:localhost}" port="${remote.cache.port:11222}"/>
+</outbound-socket-binding>
+```
 
 3.8) The configuration of distributed cache `authenticationSessions` and other caches is left unchanged.
 
diff --git a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProvider.java b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProvider.java
index d95e4a4..5513777 100644
--- a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProvider.java
@@ -25,7 +25,7 @@ import org.infinispan.manager.EmbeddedCacheManager;
  */
 public class DefaultInfinispanConnectionProvider implements InfinispanConnectionProvider {
 
-    private EmbeddedCacheManager cacheManager;
+    private final EmbeddedCacheManager cacheManager;
     private final String siteName;
     private final String nodeName;
 
diff --git a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProviderFactory.java
index 6c84385..c657e44 100755
--- a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProviderFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProviderFactory.java
@@ -41,9 +41,9 @@ import org.keycloak.Config;
 import org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder;
 
 import javax.naming.InitialContext;
+import org.infinispan.persistence.remote.configuration.RemoteStoreConfigurationBuilder;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -157,7 +157,7 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
                 this.nodeName = generateNodeName();
             }
 
-            logger.debugv("Using container managed Infinispan cache container, lookup={1}", cacheContainerLookup);
+            logger.debugv("Using container managed Infinispan cache container, lookup={0}", cacheContainerLookup);
         } catch (Exception e) {
             throw new RuntimeException("Failed to retrieve cache container", e);
         }
@@ -354,8 +354,7 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
 
         builder.persistence()
                 .passivation(false)
-                .addStore(KeycloakRemoteStoreConfigurationBuilder.class)
-                    .sessionCache(sessionCache)
+                .addStore(RemoteStoreConfigurationBuilder.class)
                     .fetchPersistentState(false)
                     .ignoreModifications(false)
                     .purgeOnStartup(false)
@@ -382,8 +381,7 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
 
         builder.persistence()
                 .passivation(false)
-                .addStore(KeycloakRemoteStoreConfigurationBuilder.class)
-                    .sessionCache(false)
+                .addStore(RemoteStoreConfigurationBuilder.class)
                     .fetchPersistentState(false)
                     .ignoreModifications(false)
                     .purgeOnStartup(false)
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/CacheDecorators.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/CacheDecorators.java
index e9b3288..23e5fb1 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/CacheDecorators.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/CacheDecorators.java
@@ -26,13 +26,31 @@ import org.infinispan.context.Flag;
  */
 public class CacheDecorators {
 
+    /**
+     * Adds {@link Flag#CACHE_MODE_LOCAL} flag to the cache.
+     * @param cache
+     * @return Cache with the flag applied.
+     */
     public static <K, V> AdvancedCache<K, V> localCache(Cache<K, V> cache) {
         return cache.getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL);
     }
 
+    /**
+     * Adds {@link Flag#SKIP_CACHE_LOAD} and {@link Flag#SKIP_CACHE_STORE} flags to the cache.
+     * @param cache
+     * @return Cache with the flags applied.
+     */
     public static <K, V> AdvancedCache<K, V> skipCacheLoaders(Cache<K, V> cache) {
         return cache.getAdvancedCache().withFlags(Flag.SKIP_CACHE_LOAD, Flag.SKIP_CACHE_STORE);
     }
 
+    /**
+     * Adds {@link Flag#SKIP_CACHE_STORE} flag to the cache.
+     * @param cache
+     * @return Cache with the flags applied.
+     */
+    public static <K, V> AdvancedCache<K, V> skipCacheStore(Cache<K, V> cache) {
+        return cache.getAdvancedCache().withFlags(Flag.SKIP_CACHE_STORE);
+    }
 
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/InfinispanChangelogBasedTransaction.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/InfinispanChangelogBasedTransaction.java
index e5a7a47..1950992 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/InfinispanChangelogBasedTransaction.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/InfinispanChangelogBasedTransaction.java
@@ -27,6 +27,7 @@ import org.jboss.logging.Logger;
 import org.keycloak.models.AbstractKeycloakTransaction;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
+import org.keycloak.models.sessions.infinispan.CacheDecorators;
 import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
 import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
 
@@ -172,17 +173,17 @@ public class InfinispanChangelogBasedTransaction<K, V extends SessionEntity> ext
         switch (operation) {
             case REMOVE:
                 // Just remove it
-                cache
+                CacheDecorators.skipCacheStore(cache)
                         .getAdvancedCache().withFlags(Flag.IGNORE_RETURN_VALUES)
                         .remove(key);
                 break;
             case ADD:
-                cache
+                CacheDecorators.skipCacheStore(cache)
                         .getAdvancedCache().withFlags(Flag.IGNORE_RETURN_VALUES)
                         .put(key, sessionWrapper, task.getLifespanMs(), TimeUnit.MILLISECONDS);
                 break;
             case ADD_IF_ABSENT:
-                SessionEntityWrapper<V> existing = cache.putIfAbsent(key, sessionWrapper);
+                SessionEntityWrapper<V> existing = CacheDecorators.skipCacheStore(cache).putIfAbsent(key, sessionWrapper);
                 if (existing != null) {
                     logger.debugf("Existing entity in cache for key: %s . Will update it", key);
 
@@ -210,7 +211,7 @@ public class InfinispanChangelogBasedTransaction<K, V extends SessionEntity> ext
             SessionEntityWrapper<V> newVersionEntity = generateNewVersionAndWrapEntity(session, oldVersionEntity.getLocalMetadata());
 
             // Atomic cluster-aware replace
-            replaced = cache.replace(key, oldVersionEntity, newVersionEntity);
+            replaced = CacheDecorators.skipCacheStore(cache).replace(key, oldVersionEntity, newVersionEntity);
 
             // Replace fail. Need to load latest entity from cache, apply updates again and try to replace in cache again
             if (!replaced) {
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/SessionEntityWrapper.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/SessionEntityWrapper.java
index 254cd38..0a3a5bf 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/SessionEntityWrapper.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/SessionEntityWrapper.java
@@ -29,6 +29,7 @@ import org.infinispan.commons.marshall.Externalizer;
 import org.infinispan.commons.marshall.MarshallUtil;
 import org.infinispan.commons.marshall.SerializeWith;
 import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
+import org.jboss.logging.Logger;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -36,11 +37,12 @@ import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
 @SerializeWith(SessionEntityWrapper.ExternalizerImpl.class)
 public class SessionEntityWrapper<S extends SessionEntity> {
 
+    private static final Logger log = Logger.getLogger(SessionEntityWrapper.class);
+
     private UUID version;
     private final S entity;
     private final Map<String, String> localMetadata;
 
-
     protected SessionEntityWrapper(UUID version, Map<String, String> localMetadata, S entity) {
         if (version == null) {
             throw new IllegalArgumentException("Version UUID can't be null");
@@ -52,13 +54,34 @@ public class SessionEntityWrapper<S extends SessionEntity> {
     }
 
     public SessionEntityWrapper(Map<String, String> localMetadata, S entity) {
-        this(UUID.randomUUID(),localMetadata, entity);
+        this(UUID.randomUUID(), localMetadata, entity);
     }
 
     public SessionEntityWrapper(S entity) {
         this(new ConcurrentHashMap<>(), entity);
     }
 
+    private SessionEntityWrapper(S entity, boolean forTransport) {
+        if (! forTransport) {
+            throw new IllegalArgumentException("This constructor is only for transport entities");
+        }
+
+        this.version = null;
+        this.localMetadata = null;
+        this.entity = entity;
+    }
+
+    public static <S extends SessionEntity> SessionEntityWrapper<S> forTransport(S entity) {
+        return new SessionEntityWrapper<>(entity, true);
+    }
+
+    public SessionEntityWrapper<S> forTransport() {
+        return new SessionEntityWrapper<>(this.entity, true);
+    }
+
+    private boolean isForTransport() {
+        return this.version == null;
+    }
 
     public UUID getVersion() {
         return version;
@@ -68,16 +91,21 @@ public class SessionEntityWrapper<S extends SessionEntity> {
         this.version = version;
     }
 
-
     public S getEntity() {
         return entity;
     }
 
     public String getLocalMetadataNote(String key) {
+        if (isForTransport()) {
+            throw new IllegalStateException("This entity is only intended for transport");
+        }
         return localMetadata.get(key);
     }
 
     public void putLocalMetadataNote(String key, String value) {
+        if (isForTransport()) {
+            throw new IllegalStateException("This entity is only intended for transport");
+        }
         localMetadata.put(key, value);
     }
 
@@ -87,6 +115,9 @@ public class SessionEntityWrapper<S extends SessionEntity> {
     }
 
     public void putLocalMetadataNoteInt(String key, int value) {
+        if (isForTransport()) {
+            throw new IllegalStateException("This entity is only intended for transport");
+        }
         localMetadata.put(key, String.valueOf(value));
     }
 
@@ -122,31 +153,45 @@ public class SessionEntityWrapper<S extends SessionEntity> {
 
     public static class ExternalizerImpl implements Externalizer<SessionEntityWrapper> {
 
+        private static final int VERSION_1 = 1;
 
         @Override
         public void writeObject(ObjectOutput output, SessionEntityWrapper obj) throws IOException {
-            MarshallUtil.marshallUUID(obj.version, output, false);
-            MarshallUtil.marshallMap(obj.localMetadata, output);
-            output.writeObject(obj.getEntity());
-        }
-
+            output.write(VERSION_1);
 
-        @Override
-        public SessionEntityWrapper readObject(ObjectInput input) throws IOException, ClassNotFoundException {
-            UUID objVersion = MarshallUtil.unmarshallUUID(input, false);
-
-            Map<String, String> localMetadata = MarshallUtil.unmarshallMap(input, new MarshallUtil.MapBuilder<String, String, Map<String, String>>() {
+            final boolean forTransport = obj.isForTransport();
+            output.writeBoolean(forTransport);
 
-                @Override
-                public Map<String, String> build(int size) {
-                    return new ConcurrentHashMap<>(size);
-                }
+            if (! forTransport) {
+                output.writeLong(obj.getVersion().getMostSignificantBits());
+                output.writeLong(obj.getVersion().getLeastSignificantBits());
+                MarshallUtil.marshallMap(obj.localMetadata, output);
+            }
 
-            });
+            output.writeObject(obj.entity);
+        }
 
-            SessionEntity entity = (SessionEntity) input.readObject();
 
-            return new SessionEntityWrapper<>(objVersion, localMetadata, entity);
+        @Override
+        public SessionEntityWrapper readObject(ObjectInput input) throws IOException, ClassNotFoundException {
+            byte version = input.readByte();
+
+            if (version != VERSION_1) {
+                throw new IOException("Invalid version: " + version);
+            }
+            final boolean forTransport = input.readBoolean();
+
+            if (forTransport) {
+                final SessionEntity entity = (SessionEntity) input.readObject();
+                log.debugf("Loaded entity from remote store: %s", entity);
+                return new SessionEntityWrapper(entity);
+            } else {
+                UUID sessionVersion = new UUID(input.readLong(), input.readLong());
+                ConcurrentHashMap<String, String> map = MarshallUtil.unmarshallMap(input, (size) -> new ConcurrentHashMap<>(size));
+                final SessionEntity entity = (SessionEntity) input.readObject();
+                log.debugf("Found entity locally: %s", entity);
+                return new SessionEntityWrapper(sessionVersion, map, entity);
+            }
         }
 
     }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/sessions/LastSessionRefreshListener.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/sessions/LastSessionRefreshListener.java
index 40cbb31..892ecfe 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/sessions/LastSessionRefreshListener.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/sessions/LastSessionRefreshListener.java
@@ -28,6 +28,7 @@ import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
+import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
 import org.keycloak.models.sessions.infinispan.util.InfinispanUtil;
 import org.keycloak.models.utils.KeycloakModelUtils;
 
@@ -43,11 +44,11 @@ public class LastSessionRefreshListener implements ClusterListener {
     private final boolean offline;
 
     private final KeycloakSessionFactory sessionFactory;
-    private final Cache<String, SessionEntityWrapper> cache;
+    private final Cache<String, SessionEntityWrapper<UserSessionEntity>> cache;
     private final boolean distributed;
     private final String myAddress;
 
-    public LastSessionRefreshListener(KeycloakSession session, Cache<String, SessionEntityWrapper> cache, boolean offline) {
+    public LastSessionRefreshListener(KeycloakSession session, Cache<String, SessionEntityWrapper<UserSessionEntity>> cache, boolean offline) {
         this.sessionFactory = session.getKeycloakSessionFactory();
         this.cache = cache;
         this.offline = offline;
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/sessions/LastSessionRefreshStoreFactory.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/sessions/LastSessionRefreshStoreFactory.java
index 21ed476..d7b8559 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/sessions/LastSessionRefreshStoreFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/changes/sessions/LastSessionRefreshStoreFactory.java
@@ -22,6 +22,7 @@ import org.keycloak.cluster.ClusterProvider;
 import org.keycloak.common.util.Time;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
+import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
 import org.keycloak.timer.TimerProvider;
 
 /**
@@ -39,12 +40,12 @@ public class LastSessionRefreshStoreFactory {
     public static final int DEFAULT_MAX_COUNT = 100;
 
 
-    public LastSessionRefreshStore createAndInit(KeycloakSession kcSession, Cache<String, SessionEntityWrapper> cache, boolean offline) {
+    public LastSessionRefreshStore createAndInit(KeycloakSession kcSession, Cache<String, SessionEntityWrapper<UserSessionEntity>> cache, boolean offline) {
         return createAndInit(kcSession, cache, DEFAULT_TIMER_INTERVAL_MS, DEFAULT_MAX_INTERVAL_BETWEEN_MESSAGES_SECONDS, DEFAULT_MAX_COUNT, offline);
     }
 
 
-    public LastSessionRefreshStore createAndInit(KeycloakSession kcSession, Cache<String, SessionEntityWrapper> cache, long timerIntervalMs, int maxIntervalBetweenMessagesSeconds, int maxCount, boolean offline) {
+    public LastSessionRefreshStore createAndInit(KeycloakSession kcSession, Cache<String, SessionEntityWrapper<UserSessionEntity>> cache, long timerIntervalMs, int maxIntervalBetweenMessagesSeconds, int maxCount, boolean offline) {
         String eventKey = offline ? "lastSessionRefreshes-offline" :  "lastSessionRefreshes";
         LastSessionRefreshStore store = createStoreInstance(maxIntervalBetweenMessagesSeconds, maxCount, eventKey);
 
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
index 48d1965..f9e21e1 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
@@ -303,8 +303,9 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
         RemoteCache remoteCache = InfinispanUtil.getRemoteCache(cache);
 
         if (remoteCache != null) {
-            UserSessionEntity remoteSessionEntity = (UserSessionEntity) remoteCache.get(id);
-            if (remoteSessionEntity != null) {
+            SessionEntityWrapper<UserSessionEntity> remoteSessionEntityWrapper = (SessionEntityWrapper<UserSessionEntity>) remoteCache.get(id);
+            if (remoteSessionEntityWrapper != null) {
+                UserSessionEntity remoteSessionEntity = remoteSessionEntityWrapper.getEntity();
                 log.debugf("getUserSessionWithPredicate(%s): remote cache contains session entity %s", id, remoteSessionEntity);
 
                 UserSessionModel remoteSessionAdapter = wrap(realm, remoteSessionEntity, offline);
@@ -399,7 +400,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
 
         FuturesHelper futures = new FuturesHelper();
 
-        // Each cluster node cleanups just local sessions, which are those owned by himself (+ few more taking l1 cache into account)
+        // Each cluster node cleanups just local sessions, which are those owned by itself (+ few more taking l1 cache into account)
         Cache<String, SessionEntityWrapper<UserSessionEntity>> localCache = CacheDecorators.localCache(sessionCache);
 
         Cache<String, SessionEntityWrapper<UserSessionEntity>> localCacheStoreIgnore = CacheDecorators.skipCacheLoaders(localCache);
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProviderFactory.java
index ea37382..ccc9b84 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProviderFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProviderFactory.java
@@ -39,6 +39,7 @@ import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
 import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
 import org.keycloak.models.sessions.infinispan.entities.LoginFailureEntity;
 import org.keycloak.models.sessions.infinispan.entities.LoginFailureKey;
+import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
 import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
 import org.keycloak.models.sessions.infinispan.events.AbstractUserSessionClusterListener;
 import org.keycloak.models.sessions.infinispan.events.ClientRemovedSessionEvent;
@@ -204,7 +205,7 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider
 
         InfinispanConnectionProvider ispn = session.getProvider(InfinispanConnectionProvider.class);
 
-        Cache sessionsCache = ispn.getCache(InfinispanConnectionProvider.SESSION_CACHE_NAME);
+        Cache<String, SessionEntityWrapper<UserSessionEntity>> sessionsCache = ispn.getCache(InfinispanConnectionProvider.SESSION_CACHE_NAME);
         boolean sessionsRemoteCache = checkRemoteCache(session, sessionsCache, (RealmModel realm) -> {
             return realm.getSsoSessionIdleTimeout() * 1000;
         });
@@ -214,7 +215,7 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider
         }
 
 
-        Cache offlineSessionsCache = ispn.getCache(InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME);
+        Cache<String, SessionEntityWrapper<UserSessionEntity>> offlineSessionsCache = ispn.getCache(InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME);
         boolean offlineSessionsRemoteCache = checkRemoteCache(session, offlineSessionsCache, (RealmModel realm) -> {
             return realm.getOfflineSessionIdleTimeout() * 1000;
         });
@@ -223,13 +224,13 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider
             offlineLastSessionRefreshStore = new LastSessionRefreshStoreFactory().createAndInit(session, offlineSessionsCache, true);
         }
 
-        Cache loginFailuresCache = ispn.getCache(InfinispanConnectionProvider.LOGIN_FAILURE_CACHE_NAME);
+        Cache<LoginFailureKey, SessionEntityWrapper<LoginFailureEntity>> loginFailuresCache = ispn.getCache(InfinispanConnectionProvider.LOGIN_FAILURE_CACHE_NAME);
         boolean loginFailuresRemoteCache = checkRemoteCache(session, loginFailuresCache, (RealmModel realm) -> {
             return realm.getMaxDeltaTimeSeconds() * 1000;
         });
     }
 
-    private boolean checkRemoteCache(KeycloakSession session, Cache ispnCache, RemoteCacheInvoker.MaxIdleTimeLoader maxIdleLoader) {
+    private <K, V extends SessionEntity> boolean checkRemoteCache(KeycloakSession session, Cache<K, SessionEntityWrapper<V>> ispnCache, RemoteCacheInvoker.MaxIdleTimeLoader maxIdleLoader) {
         Set<RemoteStore> remoteStores = InfinispanUtil.getRemoteStores(ispnCache);
 
         if (remoteStores.isEmpty()) {
@@ -238,7 +239,7 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider
         } else {
             log.infof("Remote store configured for cache '%s'", ispnCache.getName());
 
-            RemoteCache remoteCache = remoteStores.iterator().next().getRemoteCache();
+            RemoteCache<K, SessionEntityWrapper<V>> remoteCache = (RemoteCache) remoteStores.iterator().next().getRemoteCache();
 
             remoteCacheInvoker.addRemoteCache(ispnCache.getName(), remoteCache, maxIdleLoader);
 
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/RemoteCacheInvoker.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/RemoteCacheInvoker.java
index 8891469..3559c82 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/RemoteCacheInvoker.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/RemoteCacheInvoker.java
@@ -82,23 +82,22 @@ public class RemoteCacheInvoker {
     }
 
 
-    private <K, V extends SessionEntity> void runOnRemoteCache(RemoteCache<K, V> remoteCache, long maxIdleMs, K key, SessionUpdateTask<V> task, SessionEntityWrapper<V> sessionWrapper) {
-        V session = sessionWrapper.getEntity();
+    private <K, V extends SessionEntity> void runOnRemoteCache(RemoteCache<K, SessionEntityWrapper<V>> remoteCache, long maxIdleMs, K key, SessionUpdateTask<V> task, SessionEntityWrapper<V> sessionWrapper) {
+        final V session = sessionWrapper.getEntity();
         SessionUpdateTask.CacheOperation operation = task.getOperation(session);
 
         switch (operation) {
             case REMOVE:
-                // REMOVE already handled at remote cache store level
-                //remoteCache.remove(key);
+                remoteCache.remove(key);
                 break;
             case ADD:
-                remoteCache.put(key, session, task.getLifespanMs(), TimeUnit.MILLISECONDS, maxIdleMs, TimeUnit.MILLISECONDS);
+                remoteCache.put(key, sessionWrapper.forTransport(), task.getLifespanMs(), TimeUnit.MILLISECONDS, maxIdleMs, TimeUnit.MILLISECONDS);
                 break;
             case ADD_IF_ABSENT:
                 final int currentTime = Time.currentTime();
-                SessionEntity existing = remoteCache
+                SessionEntityWrapper<V> existing = remoteCache
                         .withFlags(Flag.FORCE_RETURN_VALUE)
-                        .putIfAbsent(key, session, -1, TimeUnit.MILLISECONDS, maxIdleMs, TimeUnit.MILLISECONDS);
+                        .putIfAbsent(key, sessionWrapper.forTransport(), -1, TimeUnit.MILLISECONDS, maxIdleMs, TimeUnit.MILLISECONDS);
                 if (existing != null) {
                     logger.debugf("Existing entity in remote cache for key: %s . Will update it", key);
 
@@ -116,23 +115,24 @@ public class RemoteCacheInvoker {
     }
 
 
-    private <K, V extends SessionEntity> void replace(RemoteCache<K, V> remoteCache, long lifespanMs, long maxIdleMs, K key, SessionUpdateTask<V> task) {
+    private <K, V extends SessionEntity> void replace(RemoteCache<K, SessionEntityWrapper<V>> remoteCache, long lifespanMs, long maxIdleMs, K key, SessionUpdateTask<V> task) {
         boolean replaced = false;
         while (!replaced) {
-            VersionedValue<V> versioned = remoteCache.getVersioned(key);
+            VersionedValue<SessionEntityWrapper<V>> versioned = remoteCache.getVersioned(key);
             if (versioned == null) {
                 logger.warnf("Not found entity to replace for key '%s'", key);
                 return;
             }
 
-            V session = versioned.getValue();
+            SessionEntityWrapper<V> sessionWrapper = versioned.getValue();
+            final V session = sessionWrapper.getEntity();
 
             // Run task on the remote session
             task.runUpdate(session);
 
             logger.debugf("Before replaceWithVersion. Entity to write version %d: %s", versioned.getVersion(), session);
 
-            replaced = remoteCache.replaceWithVersion(key, session, versioned.getVersion(), lifespanMs, TimeUnit.MILLISECONDS, maxIdleMs, TimeUnit.MILLISECONDS);
+            replaced = remoteCache.replaceWithVersion(key, SessionEntityWrapper.forTransport(session), versioned.getVersion(), lifespanMs, TimeUnit.MILLISECONDS, maxIdleMs, TimeUnit.MILLISECONDS);
 
             if (!replaced) {
                 logger.debugf("Failed to replace entity '%s' version %d. Will retry again", key, versioned.getVersion());
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/RemoteCacheSessionListener.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/RemoteCacheSessionListener.java
index 04e14f5..1639c78 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/RemoteCacheSessionListener.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/RemoteCacheSessionListener.java
@@ -47,7 +47,7 @@ public class RemoteCacheSessionListener<K, V extends SessionEntity>  {
     protected static final Logger logger = Logger.getLogger(RemoteCacheSessionListener.class);
 
     private Cache<K, SessionEntityWrapper<V>> cache;
-    private RemoteCache<K, V> remoteCache;
+    private RemoteCache<K, SessionEntityWrapper<V>> remoteCache;
     private boolean distributed;
     private String myAddress;
     private ClientListenerExecutorDecorator<K> executor;
@@ -57,7 +57,7 @@ public class RemoteCacheSessionListener<K, V extends SessionEntity>  {
     }
 
 
-    protected void init(KeycloakSession session, Cache<K, SessionEntityWrapper<V>> cache, RemoteCache<K, V> remoteCache) {
+    protected void init(KeycloakSession session, Cache<K, SessionEntityWrapper<V>> cache, RemoteCache<K, SessionEntityWrapper<V>> remoteCache) {
         this.cache = cache;
         this.remoteCache = remoteCache;
 
@@ -113,10 +113,10 @@ public class RemoteCacheSessionListener<K, V extends SessionEntity>  {
             replaceRetries++;
             
             SessionEntityWrapper<V> localEntityWrapper = cache.get(key);
-            VersionedValue<V> remoteSessionVersioned = remoteCache.getVersioned(key);
+            VersionedValue<SessionEntityWrapper<V>> remoteSessionVersioned = remoteCache.getVersioned(key);
 
             // Probably already removed
-            if (remoteSessionVersioned == null) {
+            if (remoteSessionVersioned == null || remoteSessionVersioned.getValue() == null) {
                 logger.debugf("Entity '%s' not present in remoteCache. Ignoring replace",
                         key.toString());
                 return;
@@ -134,7 +134,7 @@ public class RemoteCacheSessionListener<K, V extends SessionEntity>  {
                     sleepInterval = sleepInterval << 1;
                 }
             }
-            SessionEntity remoteSession = remoteSessionVersioned.getValue();
+            SessionEntity remoteSession = remoteSessionVersioned.getValue().getEntity();
 
             logger.debugf("Read session entity from the remote cache: %s . replaceRetries=%d", remoteSession.toString(), replaceRetries);
 
@@ -201,7 +201,7 @@ public class RemoteCacheSessionListener<K, V extends SessionEntity>  {
     }
 
 
-    public static <K, V extends SessionEntity> RemoteCacheSessionListener createListener(KeycloakSession session, Cache<K, SessionEntityWrapper<V>> cache, RemoteCache<K, V> remoteCache) {
+    public static <K, V extends SessionEntity> RemoteCacheSessionListener createListener(KeycloakSession session, Cache<K, SessionEntityWrapper<V>> cache, RemoteCache<K, SessionEntityWrapper<V>> remoteCache) {
         /*boolean isCoordinator = InfinispanUtil.isCoordinator(cache);
 
         // Just cluster coordinator will fetch userSessions from remote cache.
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/RemoteCacheSessionsLoader.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/RemoteCacheSessionsLoader.java
index 789fc16..b96b9bd 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/RemoteCacheSessionsLoader.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/remotestore/RemoteCacheSessionsLoader.java
@@ -29,7 +29,6 @@ import org.jboss.logging.Logger;
 import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
-import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
 import org.keycloak.models.sessions.infinispan.initializer.BaseCacheInitializer;
 import org.keycloak.models.sessions.infinispan.initializer.OfflinePersistentUserSessionLoader;
 import org.keycloak.models.sessions.infinispan.initializer.SessionLoader;
@@ -116,9 +115,7 @@ public class RemoteCacheSessionsLoader implements SessionLoader {
         for (Map.Entry<byte[], byte[]> entry : remoteObjects.entrySet()) {
             try {
                 Object key = marshaller.objectFromByteBuffer(entry.getKey());
-                SessionEntity entity = (SessionEntity) marshaller.objectFromByteBuffer(entry.getValue());
-
-                SessionEntityWrapper entityWrapper = new SessionEntityWrapper(entity);
+                SessionEntityWrapper entityWrapper = (SessionEntityWrapper) marshaller.objectFromByteBuffer(entry.getValue());
 
                 decoratedCache.putAsync(key, entityWrapper);
             } catch (Exception e) {
diff --git a/model/infinispan/src/test/java/org/keycloak/cluster/infinispan/ConcurrencyJDGSessionsCacheTest.java b/model/infinispan/src/test/java/org/keycloak/cluster/infinispan/ConcurrencyJDGSessionsCacheTest.java
index a4091a1..5e79226 100644
--- a/model/infinispan/src/test/java/org/keycloak/cluster/infinispan/ConcurrencyJDGSessionsCacheTest.java
+++ b/model/infinispan/src/test/java/org/keycloak/cluster/infinispan/ConcurrencyJDGSessionsCacheTest.java
@@ -39,8 +39,8 @@ import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
 import org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionEntity;
 import org.keycloak.models.sessions.infinispan.entities.SessionEntity;
 import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
-import org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder;
 import org.keycloak.models.sessions.infinispan.util.InfinispanUtil;
+import org.infinispan.persistence.remote.configuration.RemoteStoreConfigurationBuilder;
 
 /**
  * Test concurrency for remoteStore (backed by HotRod RemoteCaches) against external JDG. Especially tests "replaceWithVersion" contract.
@@ -207,7 +207,7 @@ public class ConcurrencyJDGSessionsCacheTest {
 
 
     private static EmbeddedCacheManager createManager(int threadId) {
-        return new TestCacheManagerFactory().createManager(threadId, InfinispanConnectionProvider.SESSION_CACHE_NAME, KeycloakRemoteStoreConfigurationBuilder.class);
+        return new TestCacheManagerFactory().createManager(threadId, InfinispanConnectionProvider.SESSION_CACHE_NAME, RemoteStoreConfigurationBuilder.class);
     }
 
 
diff --git a/model/infinispan/src/test/java/org/keycloak/cluster/infinispan/TestCacheManagerFactory.java b/model/infinispan/src/test/java/org/keycloak/cluster/infinispan/TestCacheManagerFactory.java
index 6b4eec1..0fc8d7e 100644
--- a/model/infinispan/src/test/java/org/keycloak/cluster/infinispan/TestCacheManagerFactory.java
+++ b/model/infinispan/src/test/java/org/keycloak/cluster/infinispan/TestCacheManagerFactory.java
@@ -19,11 +19,12 @@ package org.keycloak.cluster.infinispan;
 
 import org.infinispan.configuration.cache.Configuration;
 import org.infinispan.configuration.cache.ConfigurationBuilder;
+import org.infinispan.configuration.cache.StoreConfigurationBuilder;
 import org.infinispan.configuration.global.GlobalConfigurationBuilder;
 import org.infinispan.manager.DefaultCacheManager;
 import org.infinispan.manager.EmbeddedCacheManager;
 import org.infinispan.persistence.remote.configuration.ExhaustedAction;
-import org.infinispan.persistence.remote.configuration.RemoteStoreConfigurationBuilder;
+import org.infinispan.persistence.remote.configuration.RemoteStoreConfigurationChildBuilder;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -31,7 +32,7 @@ import org.infinispan.persistence.remote.configuration.RemoteStoreConfigurationB
 class TestCacheManagerFactory {
 
 
-    <T extends RemoteStoreConfigurationBuilder> EmbeddedCacheManager createManager(int threadId, String cacheName, Class<T> builderClass) {
+    <T extends StoreConfigurationBuilder<?, T> & RemoteStoreConfigurationChildBuilder<T>> EmbeddedCacheManager createManager(int threadId, String cacheName, Class<T> builderClass) {
         System.setProperty("java.net.preferIPv4Stack", "true");
         System.setProperty("jgroups.tcp.port", "53715");
         GlobalConfigurationBuilder gcb = new GlobalConfigurationBuilder();
@@ -57,7 +58,7 @@ class TestCacheManagerFactory {
     }
 
 
-    private <T extends RemoteStoreConfigurationBuilder> Configuration getCacheBackedByRemoteStore(int threadId, String cacheName, Class<T> builderClass) {
+    private <T extends StoreConfigurationBuilder<?, T> & RemoteStoreConfigurationChildBuilder<T>> Configuration getCacheBackedByRemoteStore(int threadId, String cacheName, Class<T> builderClass) {
         ConfigurationBuilder cacheConfigBuilder = new ConfigurationBuilder();
 
         String host = "localhost";
diff --git a/services/src/main/java/org/keycloak/executors/DefaultExecutorsProviderFactory.java b/services/src/main/java/org/keycloak/executors/DefaultExecutorsProviderFactory.java
index aa8f83b..adc761d 100644
--- a/services/src/main/java/org/keycloak/executors/DefaultExecutorsProviderFactory.java
+++ b/services/src/main/java/org/keycloak/executors/DefaultExecutorsProviderFactory.java
@@ -44,8 +44,8 @@ public class DefaultExecutorsProviderFactory implements ExecutorsProviderFactory
 
     protected static final Logger logger = Logger.getLogger(DefaultExecutorsProviderFactory.class);
 
-    private int DEFAULT_MIN_THREADS = 4;
-    private int DEFAULT_MAX_THREADS = 16;
+    private static final int DEFAULT_MIN_THREADS = 4;
+    private static final int DEFAULT_MAX_THREADS = 16;
 
     private static final String MANAGED_EXECUTORS_SERVICE_JNDI_PREFIX = "java:jboss/ee/concurrency/executor/";
 
diff --git a/testsuite/integration-arquillian/servers/auth-server/jboss/common/crossdc/cross-dc-setup.cli b/testsuite/integration-arquillian/servers/auth-server/jboss/common/crossdc/cross-dc-setup.cli
index 3a0a7b0..3eee2fc 100644
--- a/testsuite/integration-arquillian/servers/auth-server/jboss/common/crossdc/cross-dc-setup.cli
+++ b/testsuite/integration-arquillian/servers/auth-server/jboss/common/crossdc/cross-dc-setup.cli
@@ -8,105 +8,88 @@ echo *** Update jgoups subsystem ***
 echo *** Update infinispan subsystem ***
 /subsystem=infinispan/cache-container=keycloak:write-attribute(name=module, value=org.keycloak.keycloak-model-infinispan)
 
+echo ** Add remote socket binding to infinispan server **
+/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=remote-cache:add(host=${remote.cache.host:localhost}, port=${remote.cache.port:11222})
+
 echo ** Update replicated-cache work element **
-/subsystem=infinispan/cache-container=keycloak/replicated-cache=work/store=custom:add( \
-    class=org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder, \
+/subsystem=infinispan/cache-container=keycloak/replicated-cache=work/store=remote:add( \
     passivation=false, \
     fetch-state=false, \
     purge=false, \
     preload=false, \
-    shared=true \
-)
-
-/subsystem=infinispan/cache-container=keycloak/replicated-cache=work/store=custom:write-attribute( \
-    name=properties, value={ \
+    shared=true, \
+    remote-servers=["remote-cache"], \
+    cache=work, \
+    properties={ \
         rawValues=true, \
-        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory, \
-        remoteCacheName=work, \
-        sessionCache=false \
+        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory \
     } \
 )
 
 /subsystem=infinispan/cache-container=keycloak/replicated-cache=work:write-attribute(name=statistics-enabled,value=true)
 
 echo ** Update distributed-cache sessions element **
-/subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions/store=custom:add( \
-    class=org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder, \
+/subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions/store=remote:add( \
     passivation=false, \
     fetch-state=false, \
     purge=false, \
     preload=false, \
-    shared=true \
-)
-
-/subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions/store=custom:write-attribute( \
-    name=properties, value={ \
-        remoteCacheName=sessions, \
-        useConfigTemplateFromCache=work, \
-        sessionCache=true \
+    shared=true, \
+    remote-servers=["remote-cache"], \
+    cache=sessions, \
+    properties={ \
+        rawValues=true, \
+        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory \
     } \
 )
-
 /subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions:write-attribute(name=statistics-enabled,value=true)
 
 echo ** Update distributed-cache offlineSessions element **
-/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions/store=custom:add( \
-    class=org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder, \
+/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions/store=remote:add( \
     passivation=false, \
     fetch-state=false, \
     purge=false, \
     preload=false, \
-    shared=true \
-)
-
-/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions/store=custom:write-attribute( \
-    name=properties, value={ \
-        remoteCacheName=offlineSessions, \
-        useConfigTemplateFromCache=work, \
-        sessionCache=true \
+    shared=true, \
+    remote-servers=["remote-cache"], \
+    cache=offlineSessions, \
+    properties={ \
+        rawValues=true, \
+        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory \
     } \
 )
-
 /subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions:write-attribute(name=statistics-enabled,value=true)
 
 echo ** Update distributed-cache loginFailures element **
-/subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures/store=custom:add( \
-    class=org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder, \
+/subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures/store=remote:add( \
     passivation=false, \
     fetch-state=false, \
     purge=false, \
     preload=false, \
-    shared=true \
-)
-
-/subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures/store=custom:write-attribute( \
-    name=properties, value={ \
-        remoteCacheName=loginFailures, \
-        useConfigTemplateFromCache=work, \
-        sessionCache=true \
+    shared=true, \
+    remote-servers=["remote-cache"], \
+    cache=loginFailures, \
+    properties={ \
+        rawValues=true, \
+        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory \
     } \
 )
-
 /subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures:write-attribute(name=statistics-enabled,value=true)
 
 echo ** Update distributed-cache actionTokens element **
-/subsystem=infinispan/cache-container=keycloak/distributed-cache=actionTokens/store=custom:add( \
-    class=org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder, \
+/subsystem=infinispan/cache-container=keycloak/distributed-cache=actionTokens/store=remote:add( \
     passivation=false, \
     fetch-state=false, \
     purge=false, \
-    preload=true, \
-    shared=true \
-)
-
-/subsystem=infinispan/cache-container=keycloak/distributed-cache=actionTokens/store=custom:write-attribute( \
-    name=properties, value={ \
-        remoteCacheName=actionTokens, \
-        useConfigTemplateFromCache=work, \
-        sessionCache=false \
+    preload=false, \
+    shared=true, \
+    cache=actionTokens, \
+    remote-servers=["remote-cache"], \
+    properties={ \
+        rawValues=true, \
+        marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory \
     } \
 )
-
 /subsystem=infinispan/cache-container=keycloak/distributed-cache=actionTokens:write-attribute(name=statistics-enabled,value=true)
 
 echo ** Update distributed-cache authenticationSessions element **
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestCacheResource.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestCacheResource.java
index 1954cb8..d1e7be1 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestCacheResource.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestCacheResource.java
@@ -35,6 +35,7 @@ import org.infinispan.remoting.transport.Transport;
 import org.jgroups.JChannel;
 import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
 import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
 import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
 import org.keycloak.models.sessions.infinispan.util.InfinispanUtil;
 import org.keycloak.testsuite.rest.representation.JGroupsStats;
@@ -136,11 +137,11 @@ public class TestCacheResource {
         if (remoteCache == null) {
             return -1;
         } else {
-            UserSessionEntity userSession = (UserSessionEntity) remoteCache.get(userSessionId);
+            SessionEntityWrapper<UserSessionEntity> userSession = (SessionEntityWrapper<UserSessionEntity>) remoteCache.get(userSessionId);
             if (userSession == null) {
                 return -1;
             } else {
-                return userSession.getLastSessionRefresh();
+                return userSession.getEntity().getLastSessionRefresh();
             }
         }
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/BruteForceCrossDCTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/BruteForceCrossDCTest.java
index 3007cab..e7d9026 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/BruteForceCrossDCTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/BruteForceCrossDCTest.java
@@ -222,10 +222,10 @@ public class BruteForceCrossDCTest extends AbstractAdminCrossDCTest {
 
             log.infof("%s: dc0User1=%d, dc0user2=%d, dc1user1=%d, dc1user2=%d, dc0CacheSize=%d, dc1CacheSize=%d", prefixMessage, dc0user1, dc0user2, dc1user1, dc1user2, dc0CacheSize, dc1CacheSize);
 
-            Assert.assertEquals(dc0user1, expectedUser1);
-            Assert.assertEquals(dc0user2, expectedUser2);
-            Assert.assertEquals(dc1user1, expectedUser1);
-            Assert.assertEquals(dc1user2, expectedUser2);
+            Assert.assertEquals(expectedUser1, dc0user1);
+            Assert.assertEquals(expectedUser2, dc0user2);
+            Assert.assertEquals(expectedUser1, dc1user1);
+            Assert.assertEquals(expectedUser2, dc1user2);
 
             Assert.assertEquals(expectedCacheSize, dc0CacheSize);
             Assert.assertEquals(expectedCacheSize, dc1CacheSize);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/session/LastSessionRefreshUnitTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/session/LastSessionRefreshUnitTest.java
index 5b8c559..8946127 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/session/LastSessionRefreshUnitTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/session/LastSessionRefreshUnitTest.java
@@ -34,6 +34,7 @@ import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
 import org.keycloak.models.sessions.infinispan.changes.sessions.LastSessionRefreshStore;
 import org.keycloak.models.sessions.infinispan.changes.sessions.LastSessionRefreshStoreFactory;
 import org.keycloak.models.sessions.infinispan.changes.sessions.SessionData;
+import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.testsuite.AbstractKeycloakTest;
 import org.keycloak.testsuite.Retry;
@@ -168,7 +169,7 @@ public class LastSessionRefreshUnitTest extends AbstractKeycloakTest {
 
             };
 
-            Cache<String, SessionEntityWrapper> cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.SESSION_CACHE_NAME);
+            Cache<String, SessionEntityWrapper<UserSessionEntity>> cache = session.getProvider(InfinispanConnectionProvider.class).getCache(InfinispanConnectionProvider.SESSION_CACHE_NAME);
             return factory.createAndInit(session, cache, timerIntervalMs, maxIntervalBetweenMessagesSeconds, 10, false);
         }