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, or

  • the 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;
        }
    }
}