Skip to content

findByPrincipalName does not correctly return sessions #3452

Open

Description

@dadeloper

Describe the bug
If you call findByPrincipalName you can get inconstant results, as query listSessionsByPrincipalNameQuery used below does not order results by id. Later, extractor of the result is trying to combine results for the same sessions – but it's calling getLast on list that it's creating, so if results are not ordered, then result list of extractor might have multiple entries for same session. The problem is that later this list is converted to map by id – at this point we will loose some attributes.

To Reproduce
Have two sessions for the same principle name with multiple attributes. Call findByPrincipalName.

Expected behavior
Result should be ordered or extractor should not call getLast but actually look by an id. Also, extractor could return a Set in that case.

Activity

  1. MrEx3cut0r commented on Aug 8, 2025

    @MrEx3cut0r

    Hi, anyone already works on it?

  2. AlexanderReaper7 commented on Oct 6, 2026

    @AlexanderReaper7

    Reproduced with spring-session-jdbc 4.1.1 and PostgreSQL 18.2. The unordered query and adjacency-based extractor are also present on main at b61972a, checked on 2026-10-06.

    A repository-level regression test reproduces the missing attributes without concurrent requests:

    1. Create and save 120 sessions for the same principal. Each has the principal-name index attribute and three string attributes, first, second, and third, each containing "x".repeat(1200).
    2. Load every third session with findById, add later = "x", and save it again. This inserts the new attribute separately from the original rows.
    3. Run ANALYZE spring_session, spring_session_attributes.
    4. Call findByPrincipalName and check that every returned session still contains first, second, and third.

    With the unordered query, all 120 session IDs are returned, but exactly 40 sessions have only ["later"] as their attribute names. The assertion fails with:

    but could not find the following element(s):
      ["first", "second", "third"]
    

    Adding only ORDER BY S.PRIMARY_ID makes the same test pass. The test runs against a real PostgreSQL container: SessionStoreIT.java. The comparison removed only that ORDER BY line from the custom query.

    The failure matches the explanation in this issue. The extractor reuses only the last session object. If a session's rows appear again after another session's rows, it creates a new partial object, and the final map entry replaces the earlier object. PostgreSQL does not guarantee row order without ORDER BY. A separate SQL reproduction using the session schema produced a Hash Right Join with a sequential scan of the attribute table, so the rows need not arrive grouped by session.

    For a logged-in device list, this can produce missing device names or omitted devices when the lifetime attribute is missing. In this reproduction, operations using only the returned session IDs would still have all 120 IDs available.

    This customizer works around the issue using the existing query plus the ordering:

    @Bean
    SessionRepositoryCustomizer<JdbcIndexedSessionRepository> sessionsListedInOrder() {
        return repository -> repository.setListSessionsByPrincipalNameQuery("""
                SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME,
                    S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES
                FROM %TABLE_NAME% S
                LEFT JOIN %TABLE_NAME%_ATTRIBUTES SA
                    ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID
                WHERE S.PRINCIPAL_NAME = ?
                ORDER BY S.PRIMARY_ID
                """);
    }

    The types are org.springframework.session.config.SessionRepositoryCustomizer and org.springframework.session.jdbc.JdbcIndexedSessionRepository. An upstream fix could add this ordering to the default query, or make the extractor collect attributes by session ID regardless of row order.

  3. added a commit that references this issue on Oct 6, 2026
    8e2fba3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions