Using the new Session SDK
Table of Contents
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:
- Getting Session Information - Retrieve session details through
SessionApi.getProjectAuthorizedSessionDetails() - Accessing Session Data - Use
SessionReferenceorSessionDetailsto access session information - 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()withSessionApi.getProjectAuthorizedSessionDetails() - Better typing and null-safety through records
- Access to additional information like
modelIdentifierandisSuperuser - 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
SessionApiis thread-safeSessionReferenceis not thread-safe - use only in single thread contextSessionDetails,UserInfo,PubserverContextare 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 ofgetSession(sessionId)when possible
4. Error Handling
- Always handle
SessionApiExceptionand 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()