[[geode-session]]
== Spring Session
:geode-name: {apache-geode-name}
:pcc-name: {pivotal-cloudcache-name}
:vmw-tas-name: {pivotal-cloudfoundry-name}


This chapter covers auto-configuration of Spring Session for {geode-name} to manage (HTTP) session state in a reliable
(consistent), highly available (replicated), and clustered manner.

{spring-session-website}[Spring Session] provides an API and several implementations for managing a user's session
information. It has the ability to replace the `javax.servlet.http.HttpSession` in an application container-neutral way
and provide session IDs in HTTP headers to work with RESTful APIs.

Furthermore, Spring Session provides the ability to keep the `HttpSession` alive even when working with `WebSockets`
and reactive Spring WebFlux `WebSessions`.

A complete discussion of Spring Session is beyond the scope of this document. You can learn more by reading
the {spring-session-docs}[docs] and reviewing the {spring-session-docs}/#samples[samples].

Spring Boot for {geode-name} provides auto-configuration support to configure {geode-name} as the session management
provider and store when {spring-session-data-gemfire-website}[Spring Session for {geode-name}] is on your Spring Boot
application's classpath.

TIP: You can learn more about Spring Session for {geode-name} in the {spring-session-data-gemfire-docs}[docs].

TIP: See the corresponding sample link:guides/caching-http-session.html.html[guide]
and {github-samples-url}/caching/http-session[code] to see Spring Session for {geode-name} in action.

[[geode-session-configuration]]
=== Configuration

You need do nothing special to use {geode-name} as a Spring Session provider implementation, managing the (HTTP) session
state of your Spring Boot application.

To do so, include the appropriate Spring Session dependency on your Spring Boot application's classpath:

.Maven dependency declaration
====
[source,xml]
[subs="verbatim,attributes"]
----
  <dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-geode</artifactId>
    <version>{spring-session-data-gemfire-version}</version>
  </dependency>
----
====

Alternatively, you may declare the provided `spring-geode-starter-session` dependency in your Spring Boot application
Maven POM (shown here) or Gradle build file:

.Maven dependency declaration
====
[source,xml]
[subs="verbatim,attributes"]
----
  <dependency>
    <groupId>org.springframework.geode</groupId>
    <artifactId>spring-geode-starter-session</artifactId>
    <version>{version}</version>
  </dependency>
----
====

After declaring the required Spring Session dependency, you can begin your Spring Boot application as you normally would:

.Spring Boot Application
====
[source,java]
----
@SpringBootApplication
public class MySpringBootApplication {

  public static void main(String[] args) {
    SpringApplication.run(MySpringBootApplication.class, args);
  }

  // ...
}
----
====

You can then create application-specific Spring Web MVC `Controllers` to interact with the `HttpSession` as needed
by your application:

.Spring Boot Application `Controller` using `HttpSession`
====
[source,java]
----
@Controller
class MyApplicationController {

  @GetRequest("...")
  public String processGet(HttpSession session) {
    // interact with HttpSession
  }
}
----
====

The `HttpSession` is replaced by a Spring managed `Session` that is stored in {geode-name}.

[[geode-session-configuration-custom]]
=== Custom Configuration

By default, Spring Boot for {geode-name} (SBDG) applies reasonable and sensible defaults when configuring {geode-name}
as the provider in Spring Session.

For instance, by default, SBDG sets the session expiration timeout to 30 minutes. It also uses a
`ClientRegionShortcut.PROXY` as the data management policy for the {geode-name} client Region that managing the (HTTP)
session state when the Spring Boot application is using a `ClientCache`, which it does
by <<geode-clientcache-applications,default>>.

However, what if the defaults are not sufficient for your application requirements?

In that case, see the next section.

[[geode-session-configuration-custom-properties]]
==== Custom Configuration using Properties

Spring Session for {geode-name} publishes
{spring-session-data-gemfire-docs}/#httpsession-gemfire-configuration-properties[well-known configuration properties]
for each of the various Spring Session configuration options when you use {geode-name} as the (HTTP) session state
management provider.

You can specify any of these properties in Spring Boot `application.properties` to adjust Spring Session's configuration
when using {geode-name}.

In addition to the properties provided in and by Spring Session for {geode-name}, Spring Boot for {geode-name} also
recognizes and respects the `spring.session.timeout` property and the `server.servlet.session.timeout` property, as
discussed {spring-boot-docs-html}/boot-features-session.html[the Spring Boot documentation].

TIP: `spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds` takes precedence over
`spring.session.timeout`, which takes precedence over `server.servlet.session.timeout` when any combination of
these properties have been simultaneously configured in the Spring `Environment` of your application.

[[geode-session-configuration-custom-configurer]]
==== Custom Configuration using a Configurer

Spring Session for {geode-name} also provides the
{spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/support/SpringSessionGemFireConfigurer.html[`SpringSessionGemFireConfigurer`]
callback interface, which you can declare in your Spring `ApplicationContext` to programmatically control
the configuration of Spring Session when you use {geode-name}.

The `SpringSessionGemFireConfigurer`, when declared in the Spring `ApplicationContext`, takes precedence over any of
the Spring Session (for {geode-name}) configuration properties and effectively overrides them when both are present.

More information on using the `SpringSessionGemFireConfigurer` can be found in the
{spring-session-data-gemfire-docs}/#httpsession-gemfire-configuration-configurer[docs].

[[geode-session-disable]]
=== Disabling Session State Caching

There may be cases where you do not want your Spring Boot application to manage (HTTP) session state by using
{geode-name}.

In certain cases, you may be using another Spring Session provider implementation, such as Redis, to cache and manage
your Spring Boot application's (HTTP) session state. In other cases, you do not want to use Spring Session to manage
your (HTTP) session state at all. Rather, you prefer to use your Web Server's (such as Tomcat's) built-in `HttpSession`
state management capabilities.

Either way, you can specifically call out your Spring Session provider implementation by using
the `spring.session.store-type` property in Spring Boot `application.properties`:

.Use Redis as the Spring Session Provider Implementation
====
[source,txt]
----
#application.properties

spring.session.store-type=redis
...
----
====

If you prefer not to use Spring Session to manage your Spring Boot application's (HTTP) session state at all, you can do
the following:

.Use Web Server Session State Management
====
[source,txt]
----
#application.properties

spring.session.store-type=none
...
----
====

Again, see the Spring Boot {spring-boot-docs-html}/boot-features-session.html[documentation] for more detail.

TIP: You can include multiple provider implementations on the classpath of your Spring Boot application. For instance,
you might use Redis to cache your application's (HTTP) session state while using {geode-name} as your application's
transactional persistent store (System of Record).

NOTE: Spring Boot does not properly recognize `spring.session.store-type=[gemfire|geode]` even though
Spring Boot for {geode-name} is set up to handle either of these property values
(that is, either `gemfire` or `geode`).

[[geode-session-pcc]]
=== Using Spring Session with {pcc-name} (PCC)

Whether you use Spring Session in a Spring Boot, {geode-name} `ClientCache` application to connect to an standalone,
externally managed cluster of {geode-name} servers or to connect to a cluster of servers in a {pcc-name} service
instance managed by a {vmw-tas-name} environment, the setup is the same.

Spring Session for {geode-name} expects there to be a cache Region in the cluster that can store and manage (HTTP)
session state when your Spring Boot application is a `ClientCache` application in the client/server topology.

By default, the cache Region used to store and manage (HTTP) session state is called `ClusteredSpringSessions`.

We recommend that you configure the cache Region name by using the well-known and documented property
in Spring Boot `application.properties`:

.Using properties
====
[source,properties]
----
spring.session.data.gemfire.session.region.name=MySessions
----
====

Alternatively, you can set the name of the cache Region used to store and manage (HTTP) session state by explicitly
declaring the `@EnableGemFireHttpSession` annotation on your main `@SpringBootApplication` class:

.Using `@EnableGemfireHttpSession
====
[source,java]
----
@SpringBootApplication
@EnableGemFireHttpSession(regionName = "MySessions")
class MySpringBootSpringSessionApplication {
	// ...
}
----
====

Once you decide on the cache Region name used to store and manage (HTTP) sessions, you must create the cache Region
in the cluster somehow.

On the client, doing so is simple, since SBDG's auto-configuration automatically creates the client `PROXY` Region
that is used to send and receive (HTTP) session state between the client and server for you when either Spring Session
is on the application classpath (for example, `spring-geode-starter-session`) or you explicitly declare
the `@EnableGemFireHttpSession` annotation on your main `@SpringBootApplication` class.

However, on the server side, you currently have a couple of options.

First, you can manually create the cache Region by using Gfsh:

.Create the Sessions Region using Gfsh
====
[source,txt]
----
gfsh> create region --name=MySessions --type=PARTITION --entry-idle-time-expiration=1800
        --entry-idle-time-expiration-action=INVALIDATE
----
====

You must create the cache Region with the appropriate name and an expiration policy.

In this case, we created an idle expiration policy with a timeout of `1800` seconds (30 minutes), after which the entry
(session object) is `invalidated`.

NOTE: Session expiration is managed by the Expiration Policy set on the cache Region that is used to store session state.
The Servlet container's (HTTP) session expiration configuration is not used, since Spring Session replaces the Servlet
container's session management capabilities with its own, and Spring Session delegates this behavior to the individual
providers, such as {geode-name}.

Alternatively, you could send the definition for the cache Region from your Spring Boot `ClientCache` application
to the cluster by using the SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/config/annotation/EnableClusterAware.html[`@EnableClusterAware`] annotation,
which is meta-annotated with SDG's `@EnableClusterConfiguration` annotation:

.Using `@EnableClusterAware`
====
[source,java]
----
@SpringBootApplication
@EnableClusterAware
class MySpringBootSpringSessionApacheGeodeApplication {
	// ...
}
----
====

TIP: See the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.html[Javadoc]
on the `@EnableClusterConfiguration` annotation and the {spring-data-geode-docs-html}/#bootstrap-annotation-config-cluster[documentation]
for more detail.

However, you cannot currently send expiration policy configuration metadata to the cluster. Therefore, you must manually
alter the cache Region to set the expiration policy:

.Using Gfsh to Alter Region
====
[source,txt]
----
gfsh> alter region --name=MySessions --entry-idle-time-expiration=1800
        --entry-idle-time-expiration-action=INVALIDATE
----
====

Now your Spring Boot `ClientCache` application that uses Spring Session in a client/server topology is configured to
store and manage user (HTTP) session state in the cluster. This works for either standalone, externally managed
{geode-name} clusters or when you use PCC running in a {vmw-tas-name} environment.
