# Session Management

Inrupt’s Java Client Libraries provide a [Session](https://api.docs.inrupt.com/docs/developer-tools/api/java/inrupt-client/latest/com/inrupt/client/auth/Session.html) 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 <mark style="color:red;">**avoid**</mark> making a session scoped to the entire application. That is, when using dependency injection framework such as [Spring](https://spring.io/) or [JakartaEE](https://jakarta.ee/):

* Do <mark style="color:red;">**NOT**</mark> use **`@ApplicationScope`**, **`@ApplicationScoped`**, or equivalent scope.
* Do <mark style="color:red;">**NOT**</mark> 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](https://spring.io/) or [JakartaEE](https://jakarta.ee/), consider using request scopes:

* **`@RequestScope`** in Spring,
* **`@RequestScoped`** in JakartaEE, or
* the equivalent annotation in your framework.

{% hint style="danger" %}
For the session object:

* Do <mark style="color:red;">**NOT**</mark> use **`@ApplicationScope`**, **`@ApplicationScoped`**, or equivalent.
* Do <mark style="color:red;">**NOT**</mark> use **`@Singleton`** or equivalent.
  {% endhint %}

<pre class="language-java"><code class="lang-java">import com.inrupt.client.auth.Session;
import com.inrupt.client.openid.OpenIdSession;
<strong>import jakarta.enterprise.context.RequestScoped;
</strong>import jakarta.inject.Inject;
// ...

<strong>@RequestScoped
</strong>public class SessionManager {
    private Session session;

    @Inject
    JsonWebToken jwt

    Session getSession() {
        if (session == null) {
            session = OpenIdSession.ofIdToken(jwt.getRawToken());
        }
        return session;
    }
}
</code></pre>

With request scoped session, the Java runtime automatically removes references to that session at the end of a request.

### Application Scoped Clients

{% hint style="warning" %}
Disambiguation

The following refers to the client object (i.e. [SolidClient](https://api.docs.inrupt.com/docs/developer-tools/api/java/inrupt-client/latest/com/inrupt/client/solid/SolidClient.html), [SolidSyncClient](https://api.docs.inrupt.com/docs/developer-tools/api/java/inrupt-client/latest/com/inrupt/client/solid/SolidSyncClient.html)) and not the session object ([Session](https://api.docs.inrupt.com/docs/developer-tools/api/java/inrupt-client/latest/com/inrupt/client/auth/Session.html)).

Do <mark style="color:red;">**NOT**</mark> use application/singleton scope (or equivalents) with sessions.
{% endhint %}

For the client object (i.e. [SolidClient](https://api.docs.inrupt.com/docs/developer-tools/api/java/inrupt-client/latest/com/inrupt/client/solid/SolidClient.html), [SolidSyncClient](https://api.docs.inrupt.com/docs/developer-tools/api/java/inrupt-client/latest/com/inrupt/client/solid/SolidSyncClient.html)),

When possible, use application/singleton scope for clients.

<pre class="language-java"><code class="lang-java">import com.inrupt.client.solid.SolidSyncClient;
<strong>import jakarta.enterprise.context.ApplicationScoped;
</strong>// ...

<strong>@ApplicationScoped
</strong>public class ClientManager {
    private SolidSyncClient client = SolidSyncClient.getClient();

    @Produces
    SolidSyncClient getClient() {
        return client;
    }
}
</code></pre>

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:

```java
@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;
        }
    }
}
```
