Skip to main content

Using the new Session SDK

Table of Contents

  1. Introduction
  2. Basic Concepts
  3. Key Classes and Interfaces
  4. Use Cases
  5. Best Practices

Introduction

This document describes how to work with existing user sessions using the new session API from the SessionSDK package. The new API provides improved performance and enhanced ease of use when accessing session information.

Main benefits of the new API:

  • Provider Independence - The new API is independent of Shiro, allowing for easier switching between different session management implementations and better testability.
  • Better Encapsulation - Improved separation of concerns and cleaner abstraction layer over session management.
  • Performance Optimization - Ability to optimize session operations without being tied to legacy implementation details.
  • Legacy Code Removal - Enables gradual removal of deprecated session management code and reduces technical debt.
  • Simplified API - More intuitive and straightforward naming conventions make the code more readable and easier to understand.
  • Type Safety - Better typing and validations through modern Java features

Basic Concepts

Working with Existing Sessions

The SessionSDK provides a simplified way to access information from existing user sessions:

  1. Getting Session Information - Retrieve session details through SessionApi.getProjectAuthorizedSessionDetails()
  2. Accessing Session Data - Use SessionReference or SessionDetails to access session information
  3. Thread Binding - Bind existing sessions to current execution thread when needed

Key Classes and Interfaces

SessionApi

Main interface for working with existing user sessions.

// Getting instance
SessionApi sessionApi = SessionApi.getLocalSessionApi();

// Binding existing session to current thread
sessionApi.bindSessionToCurrentThread(sessionId);

// Getting current session from thread
SessionReference currentSession = sessionApi.getCurrentThreadSession();

// Getting specific session
SessionReference specificSession = sessionApi.getSession(sessionId);

// Validation
boolean isValid = sessionApi.isSessionValid(sessionId);

// Getting authorized session details (replacement for SessionInfo.requireNormalSession)
SessionDetails details = SessionApi.getProjectAuthorizedSessionDetails(sessionId);

SessionReference

Interface representing a reference to a user session with modification capabilities.

SessionReference sessionRef = sessionApi.getSession(sessionId);

// Getting basic data
String sessionId = sessionRef.getSessionId();
String tenant = sessionRef.getTenant();
String login = sessionRef.getLogin();
String realm = sessionRef.getRealm();
String project = sessionRef.getProject();
String language = sessionRef.getLanguage();

// Authorization status
boolean isAuthorized = sessionRef.isAuthorized();

// Setting properties
sessionRef.setLanguage("de");
sessionRef.setAdditionalContext("deu-DE");

// Setting and getting attributes
sessionRef.setAttribute("project", "aio");
sessionRef.setAttribute("userPreferences", userPrefs);

Object value = sessionRef.getAttribute("project");
String stringValue = (String) sessionRef.getAttribute("project");
UserPreferences prefs = (UserPreferences) sessionRef.getAttribute("userPreferences");

// Get all attribute keys for debugging
Set<String> allKeys = sessionRef.getAllAttributeKeys();

// Getting details (immutable)
SessionDetails details = sessionRef.getSessionDetails();

SessionDetails

Immutable record containing details of an authorized session (replacement for SessionInfo).

SessionDetails details = sessionRef.getSessionDetails();

// Basic session info
String sessionId = details.sessionId();
String additionalContext = details.additionalContext();

// User information
UserInfo userInfo = details.userInfo();
String login = userInfo.login();
boolean isSuperuser = userInfo.isSuperuser();

// PubServer context
PubserverContext context = details.pubserverContext();
String tenant = context.tenant();
String project = context.project();
String language = context.language();
String modelIdentifier = context.modelIdentifier();

UserInfo

Record containing user information in session context.

UserInfo userInfo = details.userInfo();
String login = userInfo.login();
boolean isSuperuser = userInfo.isSuperuser();

PubserverContext

Record containing publication server context.

PubserverContext context = details.pubserverContext();
String tenant = context.tenant();
String project = context.project();
String language = context.language();
String modelIdentifier = context.modelIdentifier();

Use Cases

Use Case 1: Getting Session Details

Problem: You need to retrieve information about the current user session.

Before (legacy):

// Getting SessionInfo through legacy API
SessionInfo sessionInfo = SessionInfo.requireNormalSession(sessionId, "planner-engine");

// Accessing data
String login = sessionInfo.getLogin();
String tenant = sessionInfo.getDataSetName();
String project = sessionInfo.getDataSetLabel();

After (SessionSDK):

// Getting SessionDetails through new API (direct replacement)
SessionDetails sessionDetails = SessionApi.getProjectAuthorizedSessionDetails(sessionId);

// Accessing data
String login = sessionDetails.userInfo().login();
String tenant = sessionDetails.pubserverContext().tenant();
String project = sessionDetails.pubserverContext().project();

Change description:

  • Replacing SessionInfo.requireNormalSession() with SessionApi.getProjectAuthorizedSessionDetails()
  • Better typing and null-safety through records
  • Access to additional information like modelIdentifier and isSuperuser
  • Clear separation of user info vs server context

Use Case 2: Binding Session to Thread

Problem: You need to bind a session to the current execution thread and configure its attributes.

Before (Shiro):

// Creating Subject and binding through Shiro
Subject subject = new Subject.Builder().sessionId(sessionId).buildSubject();
subject.getSession().setAttribute("tenant", tenant);
subject.getSession().setAttribute("project", project);
subject.getSession().setAttribute("userPreferences", userPrefs);
SubjectThreadState subThState = new SubjectThreadState(subject);
subThState.bind();

After (SessionSDK):

// Binding through SessionSDK
SessionApi sessionApi = SessionApi.getLocalSessionApi();
SessionReference sessionReference = sessionApi.getSession(sessionId);

// Configure session attributes before binding
sessionReference.setAttribute("tenant", tenant);
sessionReference.setAttribute("project", project);
sessionReference.setAttribute("userPreferences", userPrefs);

// Bind session to current thread
sessionApi.bindSessionToCurrentThread(sessionId);

Change description:

  • Code simplification - less boilerplate
  • Better session attribute management
  • Direct access to SessionApi
  • Ability to configure and retrieve attributes from bound sessions

Use Case 4: Getting Current Session from Thread

Problem: You need to retrieve information about the currently bound session and manage its attributes.

Before (Shiro):

// Getting through Shiro SecurityUtils
Subject currentSubject = SecurityUtils.getSubject();
String sessionId = (String) currentSubject.getSession().getId();
String tenant = (String) currentSubject.getSession().getAttribute("tenant");
String project = (String) currentSubject.getSession().getAttribute("project");

// Setting attributes
currentSubject.getSession().setAttribute("lastActivity", System.currentTimeMillis());

After (SessionSDK):

// Getting through SessionApi
SessionApi sessionApi = SessionApi.getLocalSessionApi();
SessionReference currentSession = sessionApi.getCurrentThreadSession();

// Getting basic session information
String sessionId = currentSession.getSessionId();
String tenant = currentSession.getTenant();
String project = currentSession.getProject();
String login = currentSession.getLogin();
String realm = currentSession.getRealm();

// Setting session attributes
currentSession.setAttribute("lastActivity", System.currentTimeMillis());

Change description:

  • Direct access to session data
  • Better typing (String vs Object)
  • Less boilerplate code
  • Unified API for getting and setting attributes

Use Case 7: Getting User Information

Problem: You need to retrieve information about the logged-in user.

Before (SessionInfo):

SessionInfo sessionInfo = SessionInfo.requireNormalSession(sessionId, "planner-engine");
String login = sessionInfo.getLogin();
String personId = sessionInfo.getPersonId();

After (SessionDetails):

SessionDetails sessionDetails = SessionApi.getProjectAuthorizedSessionDetails(sessionId);

String login = sessionDetails.userInfo().login();

Change description:

  • Better separation of user information
  • Additional information (isSuperuser)
  • Type safety through records

Best Practices

1. Error Handling

// Always handle SessionApiException
try {
SessionDetails details = SessionApi.getProjectAuthorizedSessionDetails(sessionId);
// Use details
} catch (SessionApiException e) {
log.error("Session error: {}", e.getMessage());
// Handle error appropriately
}

2. Using SessionDetails vs SessionReference

// Use SessionDetails for readonly operations
SessionDetails details = sessionRef.getSessionDetails();
String login = details.userInfo().login();

// Use SessionReference for modifications
sessionRef.setAttribute("key", "value");
sessionRef.setLanguage("en");

3. Working with Records

// Records are immutable - use them for data transfer
SessionDetails details = sessionRef.getSessionDetails();
UserInfo userInfo = details.userInfo(); // Immutable record
PubserverContext context = details.pubserverContext(); // Immutable record

// Access record fields directly
String login = userInfo.login();
String tenant = context.tenant();

4. Input Validation

Always validate input before authentication to ensure data integrity and security.

5. Session Binding

Bind session to current thread before performing operations that require session context.

6. Error Handling

Handle different types of exceptions with appropriate error messages and logging.

Notes and Limitations

1. Backward Compatibility

  • Old API is marked as @Deprecated
  • Migration should be gradual
  • Maintain compatibility during transition period

2. Thread Safety

  • SessionApi is thread-safe
  • SessionReference is not thread-safe - use only in single thread context
  • SessionDetails, UserInfo, PubserverContext are immutable records and thread-safe

3. Performance Considerations

  • Records are immutable - cache if used multiple times
  • Avoid frequent calls to SessionApi.getLocalSessionApi()
  • Use getCurrentThreadSession() instead of getSession(sessionId) when possible

4. Error Handling

  • Always handle SessionApiException and its subclasses
  • Check isSessionValid() before operations
  • Log session errors for debugging

5. Record Usage

  • Records are immutable - cannot be modified after creation
  • Use pattern matching for complex record handling (Java 17+)
  • Records provide automatic equals(), hashCode(), and toString()