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 index 9a4065c8f411..83d5f1209b50 100644 --- 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 @@ -94,7 +94,7 @@ public OfflinePersistentWorkerResult createFailedWorkerResult(OfflinePersistentL public OfflinePersistentWorkerResult loadSessions(KeycloakSession session, OfflinePersistentLoaderContext loaderContext, OfflinePersistentWorkerContext ctx) { int first = ctx.getWorkerId() * sessionsPerSegment; - log.tracef("Loading sessions for segment=%d lastSessionId=%s", ctx.getSegment(), ctx.getLastSessionId()); + 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 diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/PaginationUtils.java b/model/jpa/src/main/java/org/keycloak/models/jpa/PaginationUtils.java index f52014acf1fa..cdb64906b0d6 100644 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/PaginationUtils.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/PaginationUtils.java @@ -22,11 +22,11 @@ public class PaginationUtils { public static final int DEFAULT_MAX_RESULTS = Integer.MAX_VALUE >> 1; - + public static TypedQuery paginateQuery(TypedQuery query, Integer first, Integer max) { - if (first != null && first > 0) { + if (first != null && first >= 0) { query = query.setFirstResult(first); - + // Workaround for https://hibernate.atlassian.net/browse/HHH-14295 if (max == null || max < 0) { max = DEFAULT_MAX_RESULTS; diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java index 2d5b3745af3e..935863f9719c 100644 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/session/JpaUserSessionPersisterProvider.java @@ -417,7 +417,6 @@ public AuthenticatedClientSessionModel loadClientSession(RealmModel realm, Clien * @return */ private Stream loadUserSessionsWithClientSessions(TypedQuery query, String offlineStr, boolean useExact) { - List userSessionAdapters = closing(query.getResultStream() .map(this::toAdapter) .filter(Objects::nonNull)) @@ -463,6 +462,8 @@ private Stream loadUserSessionsWithClientSessions(TypedQuery

offlineSessionIds = createOfflineSessions(realmId, userIds); + Map> offlineSessionIdsDetailed = createOfflineSessionsDetailed(realmId, userIds); + Collection offlineSessionIds = offlineSessionIdsDetailed.values().stream().flatMap(Set::stream).collect(Collectors.toCollection(TreeSet::new)); assertOfflineSessionsExist(realmId, offlineSessionIds); // Simulate server restart reinitializeKeycloakSessionFactory(); - List actualOfflineSessionIds = withRealm(realmId, (session, realm) -> session.users().getUsersStream(realm).flatMap(user -> - session.sessions().getOfflineUserSessionsStream(realm, user)).map(UserSessionModel::getId).collect(Collectors.toList())); + Map> actualOfflineSessionIds = withRealm(realmId, (session, realm) -> session.users() + .getUsersStream(realm) + .collect(Collectors.toMap( + UserModel::getId, + user -> session.sessions().getOfflineUserSessionsStream(realm, user).map(UserSessionModel::getId).collect(Collectors.toCollection(TreeSet::new)) + )) + ); - assertThat(actualOfflineSessionIds, containsInAnyOrder(offlineSessionIds.toArray())); + assertThat("User IDs", actualOfflineSessionIds.keySet(), equalTo(offlineSessionIdsDetailed.keySet())); + for (Entry> me : offlineSessionIdsDetailed.entrySet()) { + assertThat("Session IDs", actualOfflineSessionIds.get(me.getKey()), equalTo(me.getValue())); + } } private String createOfflineClientSession(String offlineUserSessionId, String clientId) { @@ -408,6 +421,16 @@ private List createOfflineSessions(String realmId, List userIds) ); } + private Map> createOfflineSessionsDetailed(String realmId, List userIds) { + return withRealm(realmId, (session, realm) -> + userIds.stream() + .collect(Collectors.toMap( + Function.identity(), + userId -> createOfflineSessions(session, realm, userId, us -> {}).map(UserSessionModel::getId).collect(Collectors.toCollection(TreeSet::new)) + )) + ); + } + /** * Creates {@link #OFFLINE_SESSION_COUNT_PER_USER} offline sessions for {@code userId} user. */