diff --git a/common/src/main/java/org/keycloak/common/Profile.java b/common/src/main/java/org/keycloak/common/Profile.java
index f8e85327ad..7bc571d4e5 100755
--- a/common/src/main/java/org/keycloak/common/Profile.java
+++ b/common/src/main/java/org/keycloak/common/Profile.java
@@ -108,8 +108,6 @@ public class Profile {
CLIENT_TYPES("Client Types", Type.EXPERIMENTAL),
- OFFLINE_SESSION_PRELOADING("Offline session preloading", Type.DEPRECATED),
-
HOSTNAME_V1("Hostname Options V1", Type.DEFAULT),
//HOSTNAME_V2("Hostname Options V2", Type.DEFAULT, 2),
diff --git a/docs/documentation/release_notes/topics/17_0_0.adoc b/docs/documentation/release_notes/topics/17_0_0.adoc
index 99b71242a8..a20bfe97e8 100644
--- a/docs/documentation/release_notes/topics/17_0_0.adoc
+++ b/docs/documentation/release_notes/topics/17_0_0.adoc
@@ -24,12 +24,12 @@ A lot of effort went into polishing and improving the Quarkus distribution to ma
* Initial support for Cross-DC
* User-defined profiles are no longer supported but using different configuration files to achieve the same goal
* Quickstarts updated to use the new distribution
+
== Other improvements
-=== Offline sessions lazy loaded
+=== Offline sessions lazily loaded
The offline sessions are now lazily fetched from the database by default instead of preloading during the server startup.
-To change the default behavior, see link:{adminguide_link}#offline-sessions-preloading[{adminguide_name}].
=== Improved User Search
diff --git a/docs/documentation/server_admin/topics.adoc b/docs/documentation/server_admin/topics.adoc
index fcef802a05..424d357066 100644
--- a/docs/documentation/server_admin/topics.adoc
+++ b/docs/documentation/server_admin/topics.adoc
@@ -14,7 +14,6 @@ include::topics/sessions/administering.adoc[]
include::topics/sessions/revocation.adoc[]
include::topics/sessions/timeouts.adoc[]
include::topics/sessions/offline.adoc[]
-include::topics/sessions/preloading.adoc[]
include::topics/sessions/transient.adoc[]
include::topics/assembly-roles-groups.adoc[]
include::topics/authentication.adoc[]
diff --git a/docs/documentation/server_admin/topics/sessions/preloading.adoc b/docs/documentation/server_admin/topics/sessions/preloading.adoc
deleted file mode 100644
index c0d4f6f359..0000000000
--- a/docs/documentation/server_admin/topics/sessions/preloading.adoc
+++ /dev/null
@@ -1,22 +0,0 @@
-[[offline-sessions-preloading]]
-
-=== Offline sessions preloading
-
-In addition to Infinispan caches, offline sessions are stored in a database which means they will be available even after server restart.
-By default, the offline sessions are not preloaded from the database into the Infinispan caches during the server startup, because this
-approach has a drawback if there are many offline sessions to be preloaded. It can significantly slow down the server startup time.
-Therefore, the offline sessions are lazily fetched from the database by default.
-
-However, {project_name} can be configured to preload the offline sessions from the database into the Infinispan caches during the server startup.
-It can be achieved by setting `preloadOfflineSessionsFromDatabase` property in the `userSessions` SPI to `true`.
-
-:tech_feature_name: Offline session preloading
-:tech_feature_id: offline-session-preloading
-include::../templates/deprecated.adoc[]
-
-The following example shows how to configure offline sessions preloading.
-
-[source,bash]
-----
-bin/kc.[sh|bat] start --features-enabled offline-session-preloading --spi-user-sessions-infinispan-preload-offline-sessions-from-database=true
-----
diff --git a/docs/documentation/upgrading/topics/changes/changes-25_0_0.adoc b/docs/documentation/upgrading/topics/changes/changes-25_0_0.adoc
index 9a59da934c..6d9e4d8ebf 100644
--- a/docs/documentation/upgrading/topics/changes/changes-25_0_0.adoc
+++ b/docs/documentation/upgrading/topics/changes/changes-25_0_0.adoc
@@ -26,3 +26,7 @@ bin/kc.[sh|bat] --spi-connections-http-client-default-max-consumed-response-size
= Removed a model module
The module `org.keycloak:keycloak-model-legacy` module was deprecated in a previous release and is removed in this release. Use the `org.keycloak:keycloak-model-storage` module instead.
+
+= Removed offline session preloading
+
+The old behavior to preload offline sessions at startup is now removed after it has been deprecated in the previous release.
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 c1ce04521a..de604041fc 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
@@ -39,7 +39,6 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.UserSessionProvider;
-import org.keycloak.models.UserSessionSpi;
import org.keycloak.models.session.UserSessionPersisterProvider;
import org.keycloak.models.sessions.infinispan.changes.Tasks;
import org.keycloak.models.sessions.infinispan.changes.sessions.CrossDCLastSessionRefreshStore;
@@ -116,8 +115,6 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
protected final RemoteCacheInvoker remoteCacheInvoker;
protected final InfinispanKeyGenerator keyGenerator;
- protected final boolean loadOfflineSessionsFromDatabase;
-
protected final SessionFunction offlineSessionCacheEntryLifespanAdjuster;
protected final SessionFunction offlineClientSessionCacheEntryLifespanAdjuster;
@@ -132,7 +129,6 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
Cache> offlineSessionCache,
Cache> clientSessionCache,
Cache> offlineClientSessionCache,
- boolean loadOfflineSessionsFromDatabase,
SessionFunction offlineSessionCacheEntryLifespanAdjuster,
SessionFunction offlineClientSessionCacheEntryLifespanAdjuster) {
this.session = session;
@@ -154,7 +150,6 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
this.persisterLastSessionRefreshStore = persisterLastSessionRefreshStore;
this.remoteCacheInvoker = remoteCacheInvoker;
this.keyGenerator = keyGenerator;
- this.loadOfflineSessionsFromDatabase = loadOfflineSessionsFromDatabase;
this.offlineSessionCacheEntryLifespanAdjuster = offlineSessionCacheEntryLifespanAdjuster;
this.offlineClientSessionCacheEntryLifespanAdjuster = offlineClientSessionCacheEntryLifespanAdjuster;
@@ -366,7 +361,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
protected Stream getUserSessionsStream(RealmModel realm, UserSessionPredicate predicate, boolean offline) {
- if (offline && loadOfflineSessionsFromDatabase) {
+ if (offline) {
// fetch the offline user-sessions from the persistence provider
UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
@@ -392,16 +387,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
Stream.empty();
}
- if (predicate.getBrokerSessionId() != null) {
- if (!Profile.isFeatureEnabled(Profile.Feature.OFFLINE_SESSION_PRELOADING)) {
- throw new RuntimeException("The deprecated offline session preloading feature is disabled in this configuration. Read the migration guide to learn more.");
- }
- // TODO add support for offline user-session lookup by brokerSessionId
- // currently it is not possible to access the brokerSessionId in offline user-session in a database agnostic way
- throw new ModelException("Dynamic database lookup for offline user-sessions by broker session ID is currently only supported for preloaded sessions. " +
- "Set preloadOfflineSessionsFromDatabase option to \"true\" in " + UserSessionSpi.NAME + " SPI in "
- + InfinispanUserSessionProviderFactory.PROVIDER_ID + " provider to enable the lookup.");
- }
+ throw new ModelException("For offline sessions, only lookup by userId and brokerUserId is supported");
}
Cache> cache = getCache(offline);
@@ -487,7 +473,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
protected Stream getUserSessionsStream(final RealmModel realm, ClientModel client, Integer firstResult, Integer maxResults, final boolean offline) {
- if (offline && loadOfflineSessionsFromDatabase) {
+ if (offline) {
// fetch the actual offline user session count from the database
UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
return persister.loadUserSessionsStream(realm, client, true, firstResult, maxResults);
@@ -569,7 +555,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
@Override
public Map getActiveClientSessionStats(RealmModel realm, boolean offline) {
- if (offline && loadOfflineSessionsFromDatabase) {
+ if (offline) {
UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
return persister.getUserSessionsCountsByClients(realm, true);
}
@@ -589,7 +575,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
protected long getUserSessionsCount(RealmModel realm, ClientModel client, boolean offline) {
- if (offline && loadOfflineSessionsFromDatabase) {
+ if (offline) {
// fetch the actual offline user session count from the database
UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
return persister.getUserSessionsCount(realm, client, true);
@@ -822,15 +808,6 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
return getUserSession(realm, userSessionId, true);
}
- @Override
- public UserSessionModel getOfflineUserSessionByBrokerSessionId(RealmModel realm, String brokerSessionId) {
- if (!Profile.isFeatureEnabled(Profile.Feature.OFFLINE_SESSION_PRELOADING)) {
- throw new RuntimeException("The deprecated offline session preloading feature is disabled in this configuration. Read the migration guide to learn more.");
- }
- return this.getUserSessionsStream(realm, UserSessionPredicate.create(realm.getId()).brokerSessionId(brokerSessionId), true)
- .findFirst().orElse(null);
- }
-
@Override
public Stream getOfflineUserSessionByBrokerUserIdStream(RealmModel realm, String brokerUserId) {
return getUserSessionsStream(realm, UserSessionPredicate.create(realm.getId()).brokerUserId(brokerUserId), true);
@@ -866,12 +843,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
@Override
public Stream getOfflineUserSessionsStream(RealmModel realm, UserModel user) {
-
- if (loadOfflineSessionsFromDatabase) {
- return getUserSessionsFromPersistenceProviderStream(realm, user, true);
- }
-
- return getUserSessionsStream(realm, UserSessionPredicate.create(realm.getId()).user(user.getId()), true);
+ return getUserSessionsFromPersistenceProviderStream(realm, user, true);
}
@Override
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 f3735878cb..7bc470a1a5 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
@@ -23,7 +23,6 @@ import org.infinispan.persistence.remote.RemoteStore;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.cluster.ClusterProvider;
-import org.keycloak.common.Profile;
import org.keycloak.common.util.Environment;
import org.keycloak.common.util.Time;
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
@@ -39,8 +38,6 @@ import org.keycloak.models.sessions.infinispan.changes.sessions.CrossDCLastSessi
import org.keycloak.models.sessions.infinispan.changes.sessions.CrossDCLastSessionRefreshStoreFactory;
import org.keycloak.models.sessions.infinispan.changes.sessions.PersisterLastSessionRefreshStore;
import org.keycloak.models.sessions.infinispan.changes.sessions.PersisterLastSessionRefreshStoreFactory;
-import org.keycloak.models.sessions.infinispan.initializer.CacheInitializer;
-import org.keycloak.models.sessions.infinispan.initializer.DBLockBasedCacheInitializer;
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheInvoker;
import org.keycloak.models.sessions.infinispan.changes.SessionEntityWrapper;
import org.keycloak.models.sessions.infinispan.entities.AuthenticatedClientSessionEntity;
@@ -51,7 +48,6 @@ import org.keycloak.models.sessions.infinispan.events.ClientRemovedSessionEvent;
import org.keycloak.models.sessions.infinispan.events.RealmRemovedSessionEvent;
import org.keycloak.models.sessions.infinispan.events.RemoveUserSessionsEvent;
import org.keycloak.models.sessions.infinispan.initializer.InfinispanCacheInitializer;
-import org.keycloak.models.sessions.infinispan.initializer.OfflinePersistentUserSessionLoader;
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheSessionListener;
import org.keycloak.models.sessions.infinispan.remotestore.RemoteCacheSessionsLoader;
import org.keycloak.models.sessions.infinispan.util.InfinispanKeyGenerator;
@@ -85,8 +81,6 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider
public static final String REMOVE_USER_SESSIONS_EVENT = "REMOVE_USER_SESSIONS_EVENT";
- private boolean preloadOfflineSessionsFromDatabase;
-
private long offlineSessionCacheEntryLifespanOverride;
private long offlineClientSessionCacheEntryLifespanOverride;
@@ -118,7 +112,6 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider
offlineSessionsCache,
clientSessionCache,
offlineClientSessionsCache,
- !preloadOfflineSessionsFromDatabase,
this::deriveOfflineSessionCacheEntryLifespanMs,
this::deriveOfflineClientSessionCacheEntryLifespanOverrideMs
);
@@ -127,11 +120,6 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider
@Override
public void init(Config.Scope config) {
this.config = config;
- preloadOfflineSessionsFromDatabase = config.getBoolean("preloadOfflineSessionsFromDatabase", false);
- if (preloadOfflineSessionsFromDatabase && !Profile.isFeatureEnabled(Profile.Feature.OFFLINE_SESSION_PRELOADING)) {
- throw new RuntimeException("The deprecated offline session preloading feature is disabled in this configuration. Read the migration guide to learn more.");
- }
-
offlineSessionCacheEntryLifespanOverride = config.getInt("offlineSessionCacheEntryLifespanOverride", -1);
offlineClientSessionCacheEntryLifespanOverride = config.getInt("offlineClientSessionCacheEntryLifespanOverride", -1);
}
@@ -203,31 +191,6 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider
@Override
public void run(KeycloakSession session) {
-
- if (preloadOfflineSessionsFromDatabase) {
- // only preload offline-sessions if necessary
- log.debug("Start pre-loading userSessions from persistent storage");
-
- InfinispanConnectionProvider connections = session.getProvider(InfinispanConnectionProvider.class);
- Cache workCache = connections.getCache(InfinispanConnectionProvider.WORK_CACHE_NAME);
- int defaultStateTransferTimeout = (int) (connections.getCache(InfinispanConnectionProvider.OFFLINE_USER_SESSION_CACHE_NAME)
- .getCacheConfiguration().clustering().stateTransfer().timeout() / 1000);
-
- InfinispanCacheInitializer ispnInitializer = new InfinispanCacheInitializer(sessionFactory, workCache,
- new OfflinePersistentUserSessionLoader(sessionsPerSegment), "offlineUserSessions", sessionsPerSegment, maxErrors,
- getStalledTimeoutInSeconds(defaultStateTransferTimeout));
-
- // DB-lock to ensure that persistent sessions are loaded from DB just on one DC. The other DCs will load them from remote cache.
- CacheInitializer initializer = new DBLockBasedCacheInitializer(session, ispnInitializer);
-
- initializer.initCache();
- initializer.loadSessions();
-
- log.debug("Pre-loading userSessions from persistent storage finished");
- } else {
- log.debug("Skipping pre-loading of userSessions from persistent storage");
- }
-
// Initialize persister for periodically doing bulk DB updates of lastSessionRefresh timestamps of refreshed sessions
persisterLastSessionRefreshStore = new PersisterLastSessionRefreshStoreFactory().createAndInit(session, true);
}
@@ -428,7 +391,6 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider
@Override
public Map getOperationalInfo() {
Map info = new HashMap<>();
- info.put("preloadOfflineSessionsFromDatabase", Boolean.toString(preloadOfflineSessionsFromDatabase));
info.put("offlineSessionCacheEntryLifespanOverride", Long.toString(offlineSessionCacheEntryLifespanOverride));
info.put("offlineClientSessionCacheEntryLifespanOverride", Long.toString(offlineClientSessionCacheEntryLifespanOverride));
return info;
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/BaseCacheInitializer.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/BaseCacheInitializer.java
index 10fc37044d..2c3a40f4ae 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/BaseCacheInitializer.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/BaseCacheInitializer.java
@@ -52,12 +52,6 @@ public abstract class BaseCacheInitializer extends CacheInitializer {
@Override
protected boolean isFinished() {
- // Check if we should skipLoadingSessions. This can happen if someone else already did the task (For example in cross-dc environment, it was done by different DC)
- boolean isFinishedAlready = this.sessionLoader.isFinished(this);
- if (isFinishedAlready) {
- return true;
- }
-
InitializerState state = getStateFromCache();
return state != null && state.isFinished();
}
@@ -122,8 +116,4 @@ public abstract class BaseCacheInitializer extends CacheInitializer {
}
}
-
- public Cache getWorkCache() {
- return workCache;
- }
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/DBLockBasedCacheInitializer.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/DBLockBasedCacheInitializer.java
deleted file mode 100644
index 943e1d0564..0000000000
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/DBLockBasedCacheInitializer.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.models.sessions.infinispan.initializer;
-
-import org.jboss.logging.Logger;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.dblock.DBLockManager;
-import org.keycloak.models.dblock.DBLockProvider;
-
-/**
- * Encapsulates preloading of sessions within the DB Lock. This DB-aware lock ensures that "startLoading" is done on single DC and the other DCs need to wait.
- *
- * @author Marek Posolda
- */
-public class DBLockBasedCacheInitializer extends CacheInitializer {
-
- private static final Logger log = Logger.getLogger(DBLockBasedCacheInitializer.class);
-
- private final KeycloakSession session;
- private final CacheInitializer delegate;
-
- public DBLockBasedCacheInitializer(KeycloakSession session, CacheInitializer delegate) {
- this.session = session;
- this.delegate = delegate;
- }
-
-
- @Override
- public void initCache() {
- delegate.initCache();
- }
-
-
- @Override
- protected boolean isFinished() {
- return delegate.isFinished();
- }
-
-
- @Override
- protected boolean isCoordinator() {
- return delegate.isCoordinator();
- }
-
- @Override
- protected int getProgressIndicator() {
- return delegate.getProgressIndicator();
- }
-
- @Override
- protected int getStalledTimeoutInSeconds() {
- return delegate.getStalledTimeoutInSeconds();
- }
-
- /**
- * Just coordinator will run this. And there is DB-lock, so the delegate.startLoading() will be permitted just by the single DC
- */
- @Override
- protected void startLoading() {
- DBLockManager dbLockManager = new DBLockManager(session);
- dbLockManager.checkForcedUnlock();
- DBLockProvider dbLock = dbLockManager.getDBLock();
- dbLock.waitForLock(DBLockProvider.Namespace.OFFLINE_SESSIONS);
- try {
-
- if (isFinished()) {
- log.infof("Task already finished when DBLock retrieved");
- } else {
- delegate.startLoading();
- }
- } finally {
- dbLock.releaseLock();
- }
- }
-}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/OfflinePersistentUserSessionLoader.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/OfflinePersistentUserSessionLoader.java
deleted file mode 100644
index 83d5f1209b..0000000000
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/OfflinePersistentUserSessionLoader.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.models.sessions.infinispan.initializer;
-
-import org.infinispan.Cache;
-import org.infinispan.client.hotrod.exceptions.HotRodClientException;
-import org.infinispan.context.Flag;
-import org.jboss.logging.Logger;
-import org.keycloak.common.util.Retry;
-import org.keycloak.common.util.Time;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.models.session.UserSessionPersisterProvider;
-
-import java.io.Serializable;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * @author Marek Posolda
- */
-public class OfflinePersistentUserSessionLoader implements SessionLoader, Serializable {
-
- // Placeholder String used in the searching conditions to identify very first session
- private static final String FIRST_SESSION_ID = "00000000-0000-0000-0000-000000000000";
-
- private static final Logger log = Logger.getLogger(OfflinePersistentUserSessionLoader.class);
-
- // Cross-DC aware flag
- public static final String PERSISTENT_SESSIONS_LOADED = "PERSISTENT_SESSIONS_LOADED";
-
- // Just local-DC aware flag
- public static final String PERSISTENT_SESSIONS_LOADED_IN_CURRENT_DC = "PERSISTENT_SESSIONS_LOADED_IN_CURRENT_DC";
-
-
- private final int sessionsPerSegment;
-
- public OfflinePersistentUserSessionLoader(int sessionsPerSegment) {
- this.sessionsPerSegment = sessionsPerSegment;
- }
-
-
- @Override
- public void init(KeycloakSession session) {
- }
-
-
- @Override
- public OfflinePersistentLoaderContext computeLoaderContext(KeycloakSession session) {
- UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
- int sessionsCount = persister.getUserSessionsCount(true);
-
- return new OfflinePersistentLoaderContext(sessionsCount, sessionsPerSegment);
- }
-
-
- @Override
- public OfflinePersistentWorkerContext computeWorkerContext(OfflinePersistentLoaderContext loaderCtx, int segment, int workerId, OfflinePersistentWorkerResult previousResult) {
- String lastSessionId;
- if (previousResult == null) {
- lastSessionId = FIRST_SESSION_ID;
- } else {
- lastSessionId = previousResult.getLastSessionId();
- }
-
- // We know the last loaded session. New workers iteration will start from this place
- return new OfflinePersistentWorkerContext(segment, workerId, lastSessionId);
- }
-
-
- @Override
- public OfflinePersistentWorkerResult createFailedWorkerResult(OfflinePersistentLoaderContext loaderContext, OfflinePersistentWorkerContext workerContext) {
- return new OfflinePersistentWorkerResult(false, workerContext.getSegment(), workerContext.getWorkerId(), FIRST_SESSION_ID);
- }
-
-
- @Override
- public OfflinePersistentWorkerResult loadSessions(KeycloakSession session, OfflinePersistentLoaderContext loaderContext, OfflinePersistentWorkerContext ctx) {
- int first = ctx.getWorkerId() * sessionsPerSegment;
-
- log.tracef("Loading sessions for segment=%d lastSessionId=%s first=%d", ctx.getSegment(), ctx.getLastSessionId(), (Object) first);
-
- UserSessionPersisterProvider persister = session.getProvider(UserSessionPersisterProvider.class);
- List sessions = persister
- .loadUserSessionsStream(first, sessionsPerSegment, true, ctx.getLastSessionId())
- .collect(Collectors.toList());
-
- log.tracef("Sessions loaded from DB - segment=%d lastSessionId=%s", ctx.getSegment(), ctx.getLastSessionId());
-
- UserSessionModel lastSession = null;
- if (!sessions.isEmpty()) {
- lastSession = sessions.get(sessions.size() - 1);
-
- // Save to memory/infinispan
- session.sessions().importUserSessions(sessions, true);
- }
-
- String lastSessionId = lastSession==null ? FIRST_SESSION_ID : lastSession.getId();
-
- log.tracef("Sessions imported to infinispan - segment: %d, lastSessionId: %s", ctx.getSegment(), lastSessionId);
-
- return new OfflinePersistentWorkerResult(true, ctx.getSegment(), ctx.getWorkerId(), lastSessionId);
- }
-
-
- @Override
- public boolean isFinished(BaseCacheInitializer initializer) {
- Cache workCache = initializer.getWorkCache();
- Boolean sessionsLoaded = (Boolean) workCache.get(PERSISTENT_SESSIONS_LOADED);
-
- if (sessionsLoaded != null && sessionsLoaded) {
- log.debugf("Persistent sessions loaded already.");
- return true;
- } else {
- log.debugf("Persistent sessions not yet loaded.");
- return false;
- }
- }
-
-
- @Override
- public void afterAllSessionsLoaded(BaseCacheInitializer initializer) {
- Cache workCache = initializer.getWorkCache();
-
- // Will retry few times for the case when backup site not available in cross-dc environment.
- // The site might be taken offline automatically if "take-offline" properly configured
- Retry.executeWithBackoff((int iteration) -> {
-
- try {
- // Cross-DC aware flag
- workCache
- .getAdvancedCache().withFlags(Flag.SKIP_REMOTE_LOOKUP)
- .put(PERSISTENT_SESSIONS_LOADED, true);
-
- } catch (HotRodClientException re) {
- log.warnf(re, "Failed to write flag PERSISTENT_SESSIONS_LOADED in iteration '%d' . Retrying", iteration);
-
- // Rethrow the exception. Retry will take care of handle the exception and eventually retry the operation.
- throw re;
- }
-
- }, 10, 10);
-
- // Just local-DC aware flag
- workCache
- .getAdvancedCache().withFlags(Flag.SKIP_REMOTE_LOOKUP, Flag.SKIP_CACHE_LOAD, Flag.SKIP_CACHE_STORE)
- .put(PERSISTENT_SESSIONS_LOADED_IN_CURRENT_DC, true);
-
-
- log.debugf("Persistent sessions loaded successfully!");
- }
-
-
- @Override
- public String toString() {
- return new StringBuilder("OfflinePersistentUserSessionLoader [ ")
- .append("sessionsPerSegment: ").append(sessionsPerSegment)
- .append(" ]")
- .toString();
- }
-
-}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/SessionLoader.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/SessionLoader.java
index b814d2ea96..af513fcfdb 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/SessionLoader.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/initializer/SessionLoader.java
@@ -83,16 +83,6 @@ public interface SessionLoader workCache = initializer.getWorkCache();
-
- // Check if persistent sessions were already loaded in this DC. This is possible just for offline sessions ATM
- Boolean sessionsLoaded = (Boolean) workCache
- .getAdvancedCache().withFlags(Flag.SKIP_CACHE_LOAD, Flag.SKIP_CACHE_STORE)
- .get(OfflinePersistentUserSessionLoader.PERSISTENT_SESSIONS_LOADED_IN_CURRENT_DC);
-
- if ((cacheName.equals(InfinispanConnectionProvider.OFFLINE_USER_SESSION_CACHE_NAME) || (cacheName.equals(InfinispanConnectionProvider.OFFLINE_CLIENT_SESSION_CACHE_NAME)))
- && sessionsLoaded != null && sessionsLoaded) {
- log.debugf("Sessions already loaded in current DC. Skip sessions loading from remote cache '%s'", cacheName);
- return true;
- } else {
- log.debugf("Sessions maybe not yet loaded in current DC. Will load them from remote cache '%s'", cacheName);
- return false;
- }
- }
-
-
@Override
public void afterAllSessionsLoaded(BaseCacheInitializer initializer) {
}
diff --git a/model/storage-private/src/main/java/org/keycloak/models/dblock/DBLockProvider.java b/model/storage-private/src/main/java/org/keycloak/models/dblock/DBLockProvider.java
index b0a9639430..6031a8b45d 100644
--- a/model/storage-private/src/main/java/org/keycloak/models/dblock/DBLockProvider.java
+++ b/model/storage-private/src/main/java/org/keycloak/models/dblock/DBLockProvider.java
@@ -24,7 +24,7 @@ import org.keycloak.provider.Provider;
* one cluster node at a time.
*
* There are different namespaces that can be locked. The same DBLockProvider
- * (same session in keycloack) can only be used to lock one namespace, a second
+ * (same session in keycloak) can only be used to lock one namespace, a second
* attempt will throw a RuntimeException. The hasLock method
* returns the local namespace locked by this provider.
*
@@ -43,8 +43,9 @@ public interface DBLockProvider extends Provider {
enum Namespace {
DATABASE(1),
- KEYCLOAK_BOOT(1000),
- OFFLINE_SESSIONS(1001);
+ KEYCLOAK_BOOT(1000)
+ // OFFLINE_SESSIONS(1001) -- Not used anymore. Keeping to avoid reusing the number.
+ ;
private final int id;
@@ -55,7 +56,7 @@ public interface DBLockProvider extends Provider {
public int getId() {
return id;
}
- };
+ }
/**
* Try to retrieve DB lock or wait if retrieve was unsuccessful.
diff --git a/server-spi/src/main/java/org/keycloak/models/UserSessionProvider.java b/server-spi/src/main/java/org/keycloak/models/UserSessionProvider.java
index dbde310353..9ff68a5559 100755
--- a/server-spi/src/main/java/org/keycloak/models/UserSessionProvider.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserSessionProvider.java
@@ -175,16 +175,6 @@ public interface UserSessionProvider extends Provider {
*/
Stream getOfflineUserSessionsStream(RealmModel realm, UserModel user);
- /**
- * Search user sessions by the broker session ID.
- * @deprecated
- * Instead of this method, use {@link #getOfflineUserSessionByBrokerUserIdStream(RealmModel, String)} to first get
- * the sessions of a user, and then filter by the broker session ID as needed.
- *
- */
- @Deprecated
- UserSessionModel getOfflineUserSessionByBrokerSessionId(RealmModel realm, String brokerSessionId);
-
/**
* Obtains the offline user sessions associated with the user that matches the specified {@code brokerUserId}.
*
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
index 956014f196..392c5c4296 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
@@ -23,9 +23,7 @@ import static org.keycloak.services.resources.LoginActionsService.SESSION_CODE;
import org.jboss.logging.Logger;
import org.jboss.resteasy.reactive.NoCache;
-import org.keycloak.common.Profile;
import org.keycloak.http.HttpRequest;
-import org.keycloak.Config;
import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.TokenVerifier;
@@ -116,9 +114,6 @@ public class LogoutEndpoint {
private final EventBuilder event;
private final OIDCProviderConfig providerConfig;
- // When enabled we cannot search offline sessions by brokerSessionId. We need to search by federated userId and then filter by brokerSessionId.
- private final boolean offlineSessionsLazyLoadingEnabled;
-
private Cors cors;
public LogoutEndpoint(KeycloakSession session, TokenManager tokenManager, EventBuilder event, OIDCProviderConfig providerConfig) {
@@ -128,10 +123,6 @@ public class LogoutEndpoint {
this.realm = session.getContext().getRealm();
this.event = event;
this.providerConfig = providerConfig;
- this.offlineSessionsLazyLoadingEnabled = !Config.scope("userSessions").scope("infinispan").getBoolean("preloadOfflineSessionsFromDatabase", false);
- if (!this.offlineSessionsLazyLoadingEnabled && !Profile.isFeatureEnabled(Profile.Feature.OFFLINE_SESSION_PRELOADING)) {
- throw new RuntimeException("The deprecated offline session preloading feature is disabled in this configuration. Read the migration guide to learn more.");
- }
this.request = session.getContext().getHttpRequest();
this.headers = session.getContext().getRequestHeaders();
}
@@ -631,11 +622,7 @@ public class LogoutEndpoint {
UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, identityProviderAlias + "." + sessionId);
if (logoutOfflineSessions) {
- if (offlineSessionsLazyLoadingEnabled) {
- logoutOfflineUserSessionByBrokerUserId(identityProviderAlias + "." + federatedUserId, identityProviderAlias + "." + sessionId);
- } else {
- logoutOfflineUserSession(identityProviderAlias + "." + sessionId);
- }
+ logoutOfflineUserSessionByBrokerUserId(identityProviderAlias + "." + federatedUserId, identityProviderAlias + "." + sessionId);
}
if (userSession != null) {
@@ -646,14 +633,6 @@ public class LogoutEndpoint {
return backchannelLogoutResponse.get();
}
- private void logoutOfflineUserSession(String brokerSessionId) {
- UserSessionModel offlineUserSession =
- session.sessions().getOfflineUserSessionByBrokerSessionId(realm, brokerSessionId);
- if (offlineUserSession != null) {
- new UserSessionManager(session).revokeOfflineUserSession(offlineUserSession);
- }
- }
-
private BackchannelLogoutResponse backchannelLogoutFederatedUserId(String federatedUserId,
Stream identityProviderAliases,
boolean logoutOfflineSessions) {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
index 54a0486a05..eef4d00414 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
@@ -419,7 +419,6 @@
"keycloak.connectionsInfinispan.remoteStorePort": "${keycloak.connectionsInfinispan.remoteStorePort:11222}",
"keycloak.connectionsInfinispan.remoteStoreEnabled": "${keycloak.connectionsInfinispan.remoteStoreEnabled:true}",
"keycloak.connectionsInfinispan.hotrodProtocolVersion": "${keycloak.connectionsInfinispan.hotrodProtocolVersion}",
- "keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase": "${keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase:false}",
"keycloak.connectionsJpa.url": "${keycloak.connectionsJpa.url.crossdc:jdbc:h2:mem:test-dc-shared}",
"keycloak.connectionsJpa.driver": "${keycloak.connectionsJpa.driver.crossdc:org.h2.Driver}",
"keycloak.connectionsJpa.driverDialect": "${keycloak.connectionsJpa.driverDialect.crossdc:}"
@@ -446,7 +445,6 @@
"keycloak.connectionsInfinispan.remoteStorePort": "${keycloak.connectionsInfinispan.remoteStorePort:11222}",
"keycloak.connectionsInfinispan.remoteStoreEnabled": "${keycloak.connectionsInfinispan.remoteStoreEnabled:true}",
"keycloak.connectionsInfinispan.hotrodProtocolVersion": "${keycloak.connectionsInfinispan.hotrodProtocolVersion}",
- "keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase": "${keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase:false}",
"keycloak.connectionsJpa.url": "${keycloak.connectionsJpa.url.crossdc:jdbc:h2:mem:test-dc-shared}",
"keycloak.connectionsJpa.driver": "${keycloak.connectionsJpa.driver.crossdc:org.h2.Driver}",
"keycloak.connectionsJpa.driverDialect": "${keycloak.connectionsJpa.driverDialect.crossdc:}"
@@ -474,7 +472,6 @@
"keycloak.connectionsInfinispan.remoteStorePort": "${keycloak.connectionsInfinispan.remoteStorePort.2:11222}",
"keycloak.connectionsInfinispan.remoteStoreEnabled": "${keycloak.connectionsInfinispan.remoteStoreEnabled:true}",
"keycloak.connectionsInfinispan.hotrodProtocolVersion": "${keycloak.connectionsInfinispan.hotrodProtocolVersion}",
- "keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase": "${keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase:false}",
"keycloak.connectionsJpa.url": "${keycloak.connectionsJpa.url.crossdc:jdbc:h2:mem:test-dc-shared}",
"keycloak.connectionsJpa.driver": "${keycloak.connectionsJpa.driver.crossdc:org.h2.Driver}",
"keycloak.connectionsJpa.driverDialect": "${keycloak.connectionsJpa.driverDialect.crossdc:}"
@@ -501,7 +498,6 @@
"keycloak.connectionsInfinispan.remoteStorePort": "${keycloak.connectionsInfinispan.remoteStorePort.2:11222}",
"keycloak.connectionsInfinispan.remoteStoreEnabled": "${keycloak.connectionsInfinispan.remoteStoreEnabled:true}",
"keycloak.connectionsInfinispan.hotrodProtocolVersion": "${keycloak.connectionsInfinispan.hotrodProtocolVersion}",
- "keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase": "${keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase:false}",
"keycloak.connectionsJpa.url": "${keycloak.connectionsJpa.url.crossdc:jdbc:h2:mem:test-dc-shared}",
"keycloak.connectionsJpa.driver": "${keycloak.connectionsJpa.driver.crossdc:org.h2.Driver}",
"keycloak.connectionsJpa.driverDialect": "${keycloak.connectionsJpa.driverDialect.crossdc:}"
diff --git a/testsuite/model/pom.xml b/testsuite/model/pom.xml
index 7f8ae395ef..31d286df09 100644
--- a/testsuite/model/pom.xml
+++ b/testsuite/model/pom.xml
@@ -29,8 +29,6 @@
${h2.version}
file:${project.build.directory}/dependency/log4j.properties
true
- false
- disabled
@@ -160,8 +158,6 @@
${keycloak.connectionsJpa.password}
${keycloak.connectionsJpa.url}
file:${project.build.directory}/test-classes/log4j.properties
- ${keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase}
- ${keycloak.profile.feature.offline_session_preloading}
org.jboss.logmanager.LogManager
log4j
${infinispan.version}
@@ -224,24 +220,6 @@
-
- jpa+cross-dc-infinispan-offline-sessions-preloading
-
- CrossDCInfinispan,Jpa
- enabled
- true
-
-
-
-
- jpa+infinispan-offline-sessions-preloading
-
- Infinispan,Jpa
- enabled
- true
-
-
-
jpa-federation+infinispan
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/DBLockTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/DBLockTest.java
index 2cd4f091a6..65da7705f4 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/DBLockTest.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/DBLockTest.java
@@ -50,7 +50,7 @@ public class DBLockTest extends KeycloakModelTest {
private static final int LOCK_RECHECK_MILLIS = 10;
@Before
- public void before() throws Exception {
+ public void before() {
inComittedTransaction(1, (session , i) -> {
// Set timeouts for testing
DBLockManager lockManager = new DBLockManager(session);
@@ -64,7 +64,7 @@ public class DBLockTest extends KeycloakModelTest {
}
@Test
- public void simpleLockTest() throws Exception {
+ public void simpleLockTest() {
inComittedTransaction(1, (session , i) -> {
DBLockProvider dbLock = new DBLockManager(session).getDBLock();
dbLock.waitForLock(DBLockProvider.Namespace.DATABASE);
@@ -79,7 +79,7 @@ public class DBLockTest extends KeycloakModelTest {
}
@Test
- public void simpleNestedLockTest() throws Exception {
+ public void simpleNestedLockTest() {
inComittedTransaction(1, (session , i) -> {
// first session lock DATABASE
DBLockProvider dbLock1 = new DBLockManager(session).getDBLock();
@@ -89,10 +89,10 @@ public class DBLockTest extends KeycloakModelTest {
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionLC2) -> {
// a second session/dblock-provider can lock another namespace OFFLINE_SESSIONS
DBLockProvider dbLock2 = new DBLockManager(sessionLC2).getDBLock();
- dbLock2.waitForLock(DBLockProvider.Namespace.OFFLINE_SESSIONS);
+ dbLock2.waitForLock(DBLockProvider.Namespace.KEYCLOAK_BOOT);
try {
// getCurrentLock is local, each provider instance has one
- Assert.assertEquals(DBLockProvider.Namespace.OFFLINE_SESSIONS, dbLock2.getCurrentLock());
+ Assert.assertEquals(DBLockProvider.Namespace.KEYCLOAK_BOOT, dbLock2.getCurrentLock());
} finally {
dbLock2.releaseLock();
}
@@ -107,7 +107,7 @@ public class DBLockTest extends KeycloakModelTest {
}
@Test
- public void testLockConcurrentlyGeneral() throws Exception {
+ public void testLockConcurrentlyGeneral() {
inComittedTransaction(1, (session , i) -> {
testLockConcurrentlyInternal(session, DBLockProvider.Namespace.DATABASE);
return null;
@@ -115,23 +115,23 @@ public class DBLockTest extends KeycloakModelTest {
}
@Test
- public void testLockConcurrentlyOffline() throws Exception {
+ public void testLockConcurrentlyKeycloakBoot() {
inComittedTransaction(1, (session , i) -> {
- testLockConcurrentlyInternal(session, DBLockProvider.Namespace.OFFLINE_SESSIONS);
+ testLockConcurrentlyInternal(session, DBLockProvider.Namespace.KEYCLOAK_BOOT);
return null;
});
}
@Test
- public void testTwoLocksCurrently() throws Exception {
+ public void testTwoLocksCurrently() {
inComittedTransaction(1, (session , i) -> {
- testTwoLocksCurrentlyInternal(session, DBLockProvider.Namespace.DATABASE, DBLockProvider.Namespace.OFFLINE_SESSIONS);
+ testTwoLocksCurrentlyInternal(session, DBLockProvider.Namespace.DATABASE, DBLockProvider.Namespace.KEYCLOAK_BOOT);
return null;
});
}
@Test
- public void testTwoNestedLocksCurrently() throws Exception {
+ public void testTwoNestedLocksCurrently() {
inComittedTransaction(1, (session , i) -> {
testTwoNestedLocksCurrentlyInternal(session, DBLockProvider.Namespace.KEYCLOAK_BOOT, DBLockProvider.Namespace.DATABASE);
return null;
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderOfflineModelTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderOfflineModelTest.java
index 48f42523e5..b48dccdb2d 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderOfflineModelTest.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderOfflineModelTest.java
@@ -37,9 +37,7 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.UserProvider;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.UserSessionProvider;
-import org.keycloak.models.UserSessionSpi;
import org.keycloak.models.session.UserSessionPersisterProvider;
-import org.keycloak.models.sessions.infinispan.InfinispanUserSessionProviderFactory;
import org.keycloak.models.sessions.infinispan.changes.sessions.PersisterLastSessionRefreshStoreFactory;
import org.keycloak.models.utils.ResetTimeOffsetEvent;
import org.keycloak.services.managers.UserSessionManager;
@@ -338,12 +336,6 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
@Test
public void testOfflineSessionLazyLoadingPropagationBetweenNodes() throws InterruptedException {
- // This test is only unstable after setting "keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase" to "true" and
- // CrossDC is enabled.
- // This is tracked in https://github.com/keycloak/keycloak/issues/14020 to be resolved.
- Assume.assumeFalse(Objects.equals(CONFIG.scope("userSessions.infinispan").get("preloadOfflineSessionsFromDatabase"), "true") &&
- Objects.equals(CONFIG.scope("connectionsInfinispan.default").get("remoteStoreEnabled"), "true"));
-
// as one thread fills this list and the others read it, ensure that it is synchronized to avoid side effects
List offlineUserSessions = Collections.synchronizedList(new LinkedList<>());
List offlineClientSessions = Collections.synchronizedList(new LinkedList<>());
@@ -476,9 +468,8 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
@Test
public void testOfflineSessionLifespanOverride() {
- // skip the test for CrossDC or when offline session preloading is enabled
- Assume.assumeFalse(Objects.equals(CONFIG.scope("userSessions.infinispan").get("preloadOfflineSessionsFromDatabase"), "true") ||
- Objects.equals(CONFIG.scope("connectionsInfinispan.default").get("remoteStoreEnabled"), "true"));
+ // skip the test for CrossDC
+ Assume.assumeFalse(Objects.equals(CONFIG.scope("connectionsInfinispan.default").get("remoteStoreEnabled"), "true"));
createOfflineSessions("user1", 2, new LinkedList<>(), new LinkedList<>());