Session Management#
Inrupt’s Java Client Libraries provide a Session interface to handle session objects. In multi-user contexts, multiple sessions in a single application must be managed to ensure that one user’s session is not used by another user.
The following content provides some recommendations for managing sessions in multi-user applications.
Session Scope#
Avoid Application-Scoped Sessions#
For multi-user applications, the general guidance is to avoid making a session scoped to the entire application. That is, when using dependency injection framework such as Spring or JakartaEE:
Do NOT use
@ApplicationScope
,@ApplicationScoped
, or equivalent scope.Do NOT use
@Singleton
or equivalent scope.
Use Request-Scoped Sessions#
For applications where a session is used by different components, instantiating an independent session inside each component introduces unnecessary overhead. Instead, in cases where these applications also use dependency injection framework such as Spring or JakartaEE, consider using request scopes:
@RequestScope
in Spring,@RequestScoped
in JakartaEE, orthe equivalent annotation in your framework.
Warning
For the session object:
Do NOT use
@ApplicationScope
,@ApplicationScoped
, or equivalent.Do NOT use
@Singleton
or equivalent.
import com.inrupt.client.auth.Session;
import com.inrupt.client.openid.OpenIdSession;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
// ...
@RequestScoped
public class SessionManager {
private Session session;
@Inject
JsonWebToken jwt
Session getSession() {
if (session == null) {
session = OpenIdSession.ofIdToken(jwt.getRawToken());
}
return session;
}
}
With request scoped session, the Java runtime automatically removes references to that session at the end of a request.
Application Scoped Clients#
Disambiguation
The following refers to the client object (i.e. SolidClient, SolidSyncClient) and not the session object (Session).
Do NOT use application/singleton scope (or equivalents) with sessions.
For the client object (i.e. SolidClient, SolidSyncClient),
When possible, use application/singleton scope for clients.
import com.inrupt.client.solid.SolidSyncClient;
import jakarta.enterprise.context.ApplicationScoped;
// ...
@ApplicationScoped
public class ClientManager {
private SolidSyncClient client = SolidSyncClient.getClient();
@Produces
SolidSyncClient getClient() {
return client;
}
}
Then, a Web component (e.g., DataEndpoint
in the following code
block) of this application can use the application-scoped client and
the request-scoped session in the following manner:
@ApplicationScoped
@Path("/data")
public class DataEndpoint {
@Inject
SolidSyncClient solidClient; // ClientManager class is ApplicationScoped. See above.
@Inject
SessionManager sessionMgr; // SessionManager class is RequestScoped. See above.
@GET
public DataObject fetch() {
var client = solidClient.session(sessionMgr.getSession());
var uri = URI.create(...);
try (var data = client.read(uri, DataObject.class)) {
return data;
}
}
}