Fixup documentation and samples.

This commit is contained in:
John Blum
2017-07-26 01:35:27 -07:00
parent e3cc3e7388
commit 04168ef1b3
28 changed files with 1110 additions and 1291 deletions

View File

@@ -23,14 +23,14 @@ def versions = dependencyManagement.managedVersions
asciidoctor {
def ghTag = snapshotBuild ? 'master' : project.version
def ghUrl = "https://github.com/spring-projects/spring-session/tree/$ghTag"
def ghUrl = "https://github.com/spring-projects/spring-session-data-geode/tree/$ghTag"
attributes 'version-snapshot': snapshotBuild,
'version-milestone': milestoneBuild,
'version-release': releaseBuild,
'gh-url': ghUrl,
'gh-samples-url': "$ghUrl/samples/",
'download-url' : "https://github.com/spring-projects/spring-session/archive/${ghTag}.zip",
'download-url' : "https://github.com/spring-projects/spring-session-data-geode/archive/${ghTag}.zip",
'spring-version' : versions['org.springframework:spring-core'],
'spring-session-version' : version,
'docs-itest-dir' : rootProject.projectDir.path + '/docs/src/integration-test/java/',

View File

@@ -1,19 +1,21 @@
= Spring Session - HttpSession with GemFire Client/Server using Spring Boot
= Spring Session - HttpSession with Apache Geode Client/Server using Spring Boot
John Blum
:toc:
This guide describes how to build a _Spring Boot_ application configured with _Spring Session_ to transparently leverage
Pivotal GemFire to back a web application's `HttpSession`.
Apache Geode to manage a web application's `javax.servlet.http.HttpSession`.
In this sample, GemFire's client/server topology is employed using a pair of _Spring Boot_ applications, one to
configure and run a GemFire Server and another to configure and run the client, Spring MVC-based web application
In this sample, Apache Geode's client/server topology is employed using a pair of _Spring Boot_ applications, one to
configure and run a Geode Server and another to configure and run the cache client, Spring MVC-based web application
making use of the `HttpSession`.
NOTE: The completed guide can be found in the <<httpsession-gemfire-boot-sample,HttpSession with GemFire using Spring Boot Sample Application>>.
NOTE: The completed guide can be found in the
<<spring-session-sample-boot-geode,Spring Boot Sample Web Application with an Apache Geode managed HttpSession>>.
== Updating Dependencies
Before using _Spring Session_, you must ensure that the required dependencies are included.
If you are using Maven, include the following `dependencies` in your _pom.xml_:
If you are using _Maven_, include the following `dependencies` in your `pom.xml`:
.pom.xml
[source,xml]
@@ -24,8 +26,8 @@ If you are using Maven, include the following `dependencies` in your _pom.xml_:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-gemfire</artifactId>
<version>{spring-session-version}</version>
<artifactId>spring-session-data-geode</artifactId>
<version>${spring-session-data-geode-version}</version>
<type>pom</type>
</dependency>
<dependency>
@@ -36,8 +38,8 @@ If you are using Maven, include the following `dependencies` in your _pom.xml_:
----
ifeval::["{version-snapshot}" == "true"]
Since we are using a SNAPSHOT version, we need to add the Spring Snapshot Maven Repository.
If you are using Maven, include the following `repository` declaration in your _pom.xml_:
Since we are using a SNAPSHOT version, we need to add the _Spring_ Snapshot Maven Repository.
If you are using _Maven_, include the following `repository` declaration in your `pom.xml`:
.pom.xml
[source,xml]
@@ -54,8 +56,8 @@ If you are using Maven, include the following `repository` declaration in your _
endif::[]
ifeval::["{version-milestone}" == "true"]
Since we are using a Milestone version, we need to add the Spring Milestone Maven Repository.
If you are using Maven, include the following `repository` declaration in your _pom.xml_:
Since we are using a Milestone version, we need to add the _Spring_ Milestone Maven Repository.
If you are using _Maven_, include the following `repository` declaration in your `pom.xml`:
.pom.xml
[source,xml]
@@ -75,127 +77,124 @@ endif::[]
[[httpsession-spring-java-configuration-gemfire-boot]]
== Spring Boot Configuration
After adding the required dependencies and repository declarations, we can create our Spring configuration
for both the GemFire client and server using _Spring Boot_. The Spring configuration is responsible for
creating a Servlet Filter that replaces the `HttpSession` with an implementation backed by _Spring Session_
and GemFire.
After adding the required dependencies and repository declarations, we can create the _Spring_ configuration
for both our Apache Geode client and server using _Spring Boot_. The _Spring_ configuration is responsible for
creating a `Servlet Filter` that replaces the `HttpSession` with an implementation backed by _Spring Session_
and Apace Geode.
=== Spring Boot-based GemFire Server
=== Spring Boot, Apache Geode Cache Server
We start with the _Spring Boot_ application for configuring and bootstrapping a GemFire Server process...
We start with a _Spring Boot_ application to configure and bootstrap the Apache Geode Server process...
[source,java]
----
include::{samples-dir}boot/gemfire/src/main/java/sample/server/GemFireServer.java[tags=class]
----
<1> The `@EnableGemFireHttpSession` annotation is used on the GemFire Server to mainly define the corresponding
Region (e.g. `ClusteredSpringSessions`, the default) in which Session state information will be stored
and managed by GemFire. As well, we have specified an arbitrary expiration attribute (i.e. `maxInactiveIntervalInSeconds`)
for when the Session will timeout, which is triggered by a GemFire Region entry expiration event that also invalidates
the Session object in the Region.
<2> Next, we define a few `Properties` that allow us to configure certain aspects of the GemFire Server using
http://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html[GemFire's System properties].
<3> Then, we create an instance of the GemFire `Cache` using our defined `Properties`.
<4> Finally, we configure and start a `CacheServer` running in the GemFire Server to listen for connections
from cache clients. The `CacheServer's` `Socket` will be used to connect our GemFire cache client,
_Spring Boot_ web application to the server.
<1> First, we annotate the Apache Geode Server configuration class with `@SpringBootApplication` to indicate that
this will be a _Spring Boot_ application in order to leverage all of _Spring Boot's_ features (e.g. _auto-configuration_).
<2> Next, we use the **new** _Spring Data Geode_ configuration annotation `@CacheServerApplication` to simplify
the creation of a peer cache instance along with a `CacheServer` for cache clients to connect.
<3> (Optional) Then, the `@EnableGemFireHttpSession` annotation is declared to create the necessary server-side `Region`
(by default, "_ClusteredSpringSessions_") used to store the `HttpSessions` state. This step is optional since the
Session `Region` could be created manually, perhaps using external means. Using `@EnableGemFireHttpSession` is convenient.
<4> Additionally, we enable the Apache Geode Manager embedded service, which allows JMX clients (e.g. Apache Geode's
_Gfsh_ shell tool) to connect to the server and inspect the configuration.
<5> Finally, we adjust the port that the `CacheServer` will use to listen for cache clients by declaring
a `CacheServerConfigurer` bean to modify the SDG `CacheServerFactoryBean` using property placeholders.
The sample also makes use of a `PropertySourcesPlaceholderConfigurer` bean in order to externalize the sample application
configuration to affect GemFire and application configuration/behavior from the command-line (e.g. such as GemFire's
`log-level` using the `gemfire.log.level` System property; more details below).
The sample also makes use of _Spring's_ `PropertySourcesPlaceholderConfigurer` in order to externalize
the sample application's configuration using a properties file or with JVM System properties, which ever.
=== Spring Boot-based GemFire cache client Web application
=== Spring Boot, Apache Geode Cache Client Web application
Now, we create our _Spring Boot_ Web application exposing our Web service with Spring MVC, running as a
GemFire cache client connected to our _Spring Boot_-based GemFire Server, using Spring Session backed by GemFire
to manage Session state in a clustered, replicated fashion.
Now, we create a _Spring Boot_ Web application to expose our Web service with _Spring_ MVC, running as an Apache Geode
cache client connected to our _Spring Boot_, Apache Geode Server. The Web application will use _Spring Session_
backed by Apache Geode to manage Session state in a clustered (distributed), replicated fashion.
[source,java]
----
include::{samples-dir}boot/gemfire/src/main/java/sample/client/Application.java[tags=class]
----
<1> Here, again, we use the `@EnableGemFireHttpSession` annotation to not only configure the GemFire cache client,
but to also override the (HTTP) Web application container's `HttpSession` and replace it with a Session implementation
backed by _Spring Session_ and GemFire. Also notice, we did not define any Session expiration timeout with the
`maxInactiveIntervalInSeconds` attribute this time. That is because the Session expiration is managed by GemFire,
on the server, which will appropriately notify the cache client when the Session times out. Again, we have just
resorted to using the default named Region, `ClusteredSpringSessions`. Of course, we can change the Region name,
but we must do so on both the client and the server. That is a GemFire requirement, not a
_Spring Session Data GemFire_ requirement.
<2> Similarly to the server configuration, we set a few basic GemFire System `Properties` on the client.
<3> Although, this time, an instance of `ClientCache` is created with the `ClientCacheFactoryBean`
from _Spring Data GemFire_.
<4> However, in order to connect to the GemFire Server we must define a GemFire `Pool` bean containing a
pool of connections to the server. Whenever a client Region entry operation corresponding to a Session update occurs,
the client-side Region will use an existing, pooled connection to route the operation to the server.
<5> The following _Spring_ `BeanPostProcessor` (along with some utility methods) are only needed for testing purposes
and are not required by any production code. Specifically, the `BeanPostProcessor` along with the code referenced in *6*
is useful in integration test cases where the client and server processes are forked by the test framework. It is pretty
easy to figure out that a race condition is imminent without proper coordination between the client and the server,
therefore, the BPP and `ClientMembershipListener` help sync the interaction between the client and the server
on startup during automated testing.
<6> Navigates the Web application to the home page (`index.html`), which uses **Thymeleaf** templates for server-side
pages.
<7> Heartbeat Web service endpoint (useful for manual testing purposes).
<8> Web service endpoint allowing the user to add a Session attribute using the Web application UI. In addition,
the webapp stores an additional Session attribute (`requestCount`) to keep track of how many HTTP requests the user
has sent during the current "session".
<1> Again, we declare our Web application to be a _Spring Boot_ application by annotating our application class
with the `@SpringBootApplication` annotation.
<2> `@Controller` is a _Spring_ Web MVC annotation enabling our MVC handler mapping methods (i.e. methods annotated
with `@RequestMapping`) to process HTTP requests (e.g. <6>)
<3> We also declare our Web application to be a Geode cache client by annotating our application class with
`@ClientCacheApplication`. Additionally, we adjust a few basic, "DEFAULT" `Pool` settings.
<4> Next, we declare that the Web application will use _Spring Session_ backed by Apache Geode by annotating the
`ClientCacheConfiguration` class with `@EnableGemFireHttpSession`. This will create the necessary client-side `Region`
(by default, "ClusteredSpringSessions`, which is a `PROXY` `Region`) corresponding to the same server-side `Region`
by name. All Session state will be sent from the cache client Web application to the server through `Region`
data access operations. The client-side `Region` will use the "DEFAULT" `Pool`.
<5> Then, we adjust the port used by the cache client `Pool` to connect to the `CacheServer`
using a SDG `ClientCacheConfigurer`.
<6> We adjust the _Spring_ Web MVC configuration to set the home page, and...
<7> Finally, we declare the `/sessions` HTTP request handler method to set a HTTP Session attribute and increment
a count for the number of HTTP requests.
There are many other utility methods, so please refer to the actual source code for full details.
There are many other useful utility methods, so please refer to the actual source code for full details.
TIP: In typical GemFire deployments, where the cluster includes potentially hundreds or thousands of GemFire data nodes
(servers), it is more common for clients to connect to one or more GemFire Locators running in the cluster. A Locator
passes meta-data to clients about the servers available, their load and which servers have the client's data of interest,
which is particularly important in direct, single-hop data access and latency-sensitive operations. See more details
about the http://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html[Client/Server Topology in GemFire's User Guide].
TIP: In typical Geode production deployments, where the cluster includes potentially hundreds or thousands
of Geode servers (data nodes), it is more common for clients to connect to 1 or more Geode Locators running
in the cluster. A Locator passes meta-data to clients about the servers available in the cluster, the server load
and which servers have the client's data of interest, which is particularly important for direct, single-hop data access
and latency-sensitive operations. See more details about the
http://geode.apache.org/docs/guide/12/topologies_and_comm/cs_configuration/standard_client_server_deployment.html[Client/Server Deployment]
in the Apache Geode User Guide.
NOTE: For more information on configuring _Spring Data GemFire_, refer to the http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
NOTE: For more information on configuring _Spring Data Geode, refer to the
http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[Reference Guide].
The `@EnableGemFireHttpSession` annotation enables a developer to configure certain aspects of both _Spring Session_
and GemFire out-of-the-box using the following attributes:
`@EnableGemFireHttpSession` enables a developer to configure certain aspects of both _Spring Session_ and Apache Geode
out-of-the-box using the following attributes:
* `clientRegionShortcut` - specifies Apache Geode http://geode.apache.org/docs/guide/12/developing/region_options/region_types.html[data management policy]
on the client with a Geode http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
(default is `PROXY`). This attribute is only used when configuring client `Region`.
* `indexableSessionAttributes` - Identifies the Session attributes by name that should be indexed for querying operations.
Only Session attributes identified by name will be indexed.
* `maxInactiveIntervalInSeconds` - controls _HttpSession_ idle-timeout expiration (defaults to **30 minutes**).
* `regionName` - specifies the name of the GemFire Region used to store `HttpSession` state (defaults is "*ClusteredSpringSessions*").
* `clientRegionShort` - specifies GemFire's http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html[data management policy]
with a GemFire http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
(default is `PROXY`). This attribute is only used when configuring client Region.
* `poolName` - name of the dedicated GemFire Pool used to connect a client to the cluster of servers. The attribute
is only used when the application is a GemFire cache client. Defaults to `gemfirePool`.
* `serverRegionShort` - specifies GemFire's http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html[data management policy]
using a GemFire http://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/org/apache/geode/cache/RegionShortcut.html[RegionShortcut]
(default is `PARTITION`). This attribute is only used when configuring server Regions, or when a p2p topology is employed.
* `poolName` - name of the dedicated Apache Geode `Pool` used to connect a client to the cluster of servers. The attribute
is only used when the application is a cache client. Defaults to `gemfirePool`.
* `regionName` - specifies the name of the Apache Geode `Region` used to store and manage `HttpSession` state
(default is "*ClusteredSpringSessions*").
* `serverRegionShortcut` - specifies Apache Geode http://geode.apache.org/docs/guide/12/developing/region_options/region_types.html[data management policy]
on the server using a Geode http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/RegionShortcut.html[RegionShortcut]
(default is `PARTITION`). This attribute is only used when configuring server `Regions`, or when a P2P topology is employed.
NOTE: It is important to remember that the GemFire client Region name must match a server Region by the same name if
the client Region is a `PROXY` or `CACHING_PROXY`. Client and server Region names are not required to match if
the client Region used to store Spring Sessions is `LOCAL`. However, keep in mind that your session state will not
be propagated to the server and you lose all the benefits of using GemFire to store and manage distributed, replicated
session state information in a cluster.
NOTE: It is important to remember that the Apache Geode client `Region` name must match a server `Region`
by the same name if the client `Region` is a `PROXY` or `CACHING_PROXY`. Client and server `Region` names
are not required to match if the client `Region` used to store Sessions is `LOCAL`. However, keep in mind
that Session state will not be propagated to the server and you lose all the benefits of using Apache Geode
to store and manage distributed, replicated Session state information on the servers in a cluster.
[[httpsession-gemfire-boot-sample]]
== HttpSession with GemFire using Spring Boot Sample Application
[[spring-session-sample-boot-geode]]
== Spring Boot Sample Web Application with an Apache Geode managed HttpSession
=== Running the httpsession-gemfire-boot Sample Application
=== Running the Boot Sample Application
You can run the sample by obtaining the {download-url}[source code] and invoking the following commands.
First, you must run the server:
----
$ ./gradlew :samples:httpsession-gemfire-boot:run [-Dgemfire.log-level=config]
$ ./gradlew :spring-session-sample-boot-gemfire:run [-Dgemfire.log-level=config]
----
Then, in a separate terminal, run the client:
----
$ ./gradlew :samples:httpsession-gemfire-boot:bootRun [-Dgemfire.log-level=config]
$ ./gradlew :spring-session-sample-boot-gemfire:bootRun [-Dgemfire.log-level=config]
----
You should now be able to access the application at http://localhost:8080/. In this sample, the web application
is the client cache and the server is standalone.
You should now be able to access the application at http://localhost:8080/.
=== Exploring the httpsession-gemfire-boot Sample Application
In this sample, the Web application is the _Spring Boot_, Apache Geode cache client
and the server is standalone, separate (JVM) process.
=== Exploring the Boot Sample Application
Try using the application. Fill out the form with the following information:
@@ -207,9 +206,10 @@ along with an additional attribute (`requestCount`) indicating the number of Ses
=== How does it work?
We interact with the standard `HttpSession` in the the Spring MVC web service endpoint, shown here for convenience:
We interact with the standard `javax.servlet.http.HttpSession` in the the Spring Web MVC service endpoint,
shown here for convenience:
.src/main/java/sample/SessionServlet.java
.src/main/java/sample/client/Application.java
[source,java]
----
@RequestMapping(method = RequestMethod.POST, path = "/session")
@@ -224,24 +224,22 @@ public String session(HttpSession session, ModelMap modelMap,
}
----
Instead of using the embedded HTTP server's `HttpSession`, we are actually persisting the Session state in GemFire.
_Spring Session_ creates a cookie named SESSION in your browser that contains the id of your session.
Instead of using the embedded HTTP server's `HttpSession`, we are actually persisting the Session state in Apache Geode.
_Spring Session_ creates a cookie named SESSION in your browser that contains the id of your Session.
Go ahead and view the cookies (click for help with https://developer.chrome.com/devtools/docs/resources#cookies[Chrome]
or https://getfirebug.com/wiki/index.php/Cookies_Panel#Cookies_List[Firefox]).
NOTE: The following instructions assume you have a local GemFire installation. For more information on installation,
see http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
NOTE: The following instructions assume you have a local Apache Geode installation. For more information on installation,
see http://geode.apache.org/docs/guide/12/prereq_and_install.html[Prerequisites and Installation Instructions].
NOTE: In order to run the following, you must uncomment the lines in the `GemFireServer` class, `gemfireProperties` bean
for the following GemFire System properties: `jmx-manager` and `jmx-manager-start`.
If you like, you can easily remove the Session using `gfsh`.
If you like, you can easily remove the session using `gfsh`. For example, on a Linux-based system type the following
at the command-line:
For example, on a Linux-based system type the following at the command-line:
$ gfsh
Then, enter the following commands in _Gfsh_ ensuring to replace `70002719-3c54-4c20-82c3-e7faa6b718f3` with the value
of your SESSION cookie, or the session ID returned by the GemFire OQL query (which should match):
Then, enter the following commands in _Gfsh_, ensuring to replace `70002719-3c54-4c20-82c3-e7faa6b718f3` with the value
of your SESSION cookie, or the Session id returned by the Apache Geode OQL query (which should match):
....
gfsh>connect --jmx-manager=localhost[1099]
@@ -262,9 +260,10 @@ NEXT_STEP_NAME : END
gfsh>remove --region=/ClusteredSpringSessions --key="70002719-3c54-4c20-82c3-e7faa6b718f3"
....
NOTE: The _GemFire User Guide_ has more detailed instructions on using http://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
NOTE: The _Apache Geode User Guide_ contains more detailed instructions on using
http://geode.apache.org/docs/guide/12/tools_modules/gfsh/chapter_overview.html[gfsh].
Now visit the application at http://localhost:8080/ again and observe that the attribute we added is no longer displayed.
Now visit the application at `http://localhost:8080/` again and observe the attribute we added is no longer displayed.
Alternatively, you can wait **20 seconds** for the session to expire and timeout, and then refresh the page. The attribute
we added should no longer be displayed in the table.
Alternatively, you can wait **20 seconds** for the Session to timeout and expire and then refresh the page.
The attribute we added should no longer be displayed in the table.

View File

@@ -1,15 +1,17 @@
= Spring Session - HttpSession with GemFire Client/Server (Quick Start)
= Spring Session - HttpSession with Apache Geode Client/Server using Java configuration
John Blum
:toc:
This guide describes how to configure Spring Session to transparently leverage Pivotal GemFire to back a web application's
`HttpSession` using Java Configuration.
This guide describes how to configure _Spring Session_ to transparently leverage Apache Geode to manage
a Web application's `javax.servlet.http.HttpSession` using Java Configuration.
NOTE: The completed guide can be found in the <<httpsession-gemfire-clientserver-java-sample-app,HttpSession with GemFire (Client/Server) Sample Application>>.
NOTE: The completed guide can be found in the
<<spring-session-sample-java-geode-clientserver,HttpSession managed by a Java configured, Apache Geode Client/Server Sample Application>>.
== Updating Dependencies
Before using Spring Session, you must ensure that the required dependencies are included.
If you are using Maven, include the following `dependencies` in your _pom.xml_:
Before using _Spring Session_, you must ensure that the required dependencies are included.
If you are using _Maven_, include the following `dependencies` in your `pom.xml`:
.pom.xml
[source,xml]
@@ -20,21 +22,21 @@ If you are using Maven, include the following `dependencies` in your _pom.xml_:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-gemfire</artifactId>
<version>{spring-session-version}</version>
<artifactId>spring-session-data-geode</artifactId>
<version>{spring-session-data-geode-version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-web</artifactId>
<version>{spring-version}</version>
<version>${spring-version}</version>
</dependency>
</dependencies>
----
ifeval::["{version-snapshot}" == "true"]
Since we are using a SNAPSHOT version, we need to add the Spring Snapshot Maven Repository.
If you are using Maven, include the following `repository` declaration in your _pom.xml_:
Since we are using a SNAPSHOT version, we need to add the _Spring_ Snapshot Maven Repository.
If you are using _Maven_, include the following `repository` declaration in your `pom.xml`:
.pom.xml
[source,xml]
@@ -51,8 +53,8 @@ If you are using Maven, include the following `repository` declaration in your _
endif::[]
ifeval::["{version-milestone}" == "true"]
Since we are using a Milestone version, we need to add the Spring Milestone Maven Repository.
If you are using Maven, include the following `repository` declaration in your _pom.xml_:
Since we are using a Milestone version, we need to add the _Spring_ Milestone Maven Repository.
If you are using _Maven_, include the following `repository` declaration in your `pom.xml`:
.pom.xml
[source,xml]
@@ -69,105 +71,102 @@ If you are using Maven, include the following `repository` declaration in your _
endif::[]
// tag::config[]
[[httpsession-spring-java-configuration-gemfire-clientserver]]
[[httpsession-spring-java-configuration]]
== Spring Java Configuration
After adding the required dependencies and repository declarations, we can create our Spring configuration.
The Spring configuration is responsible for creating a Servlet Filter that replaces the `HttpSession`
with an implementation backed by Spring Session and GemFire.
After adding the required dependencies and repository declarations, we can create the _Spring_ configuration.
The _Spring_ configuration is responsible for creating a `Servlet Filter` that replaces the `HttpSession`
with an implementation backed by _Spring Session_ and Apache Geode.
Add the following Spring Configuration:
=== Client Configuration
Add the following _Spring_ configuration:
[source,java]
----
include::{samples-dir}javaconfig/gemfire-clientserver/src/main/java/sample/ClientConfig.java[tags=class]
----
<1> The `@EnableGemFireHttpSession` annotation creates a Spring bean named `springSessionRepositoryFilter` that
implements `Filter`. The filter is what replaces the `HttpSession` with an implementation backed by Spring Session
and GemFire.
<2> Next, we register a `Properties` bean that allows us to configure certain aspects of the GemFire client cache
using http://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html[GemFire's System properties].
<3> We use the `Properties` to configure an instance of a GemFire `ClientCache`.
<4> Then, we configure a `Pool` of client connections to talk to the GemFire Server in our Client/Server topology. In our
configuration, we have used sensible settings for timeouts, number of connections and so on. Also, the `Pool` has been
configured to connect directly to a server. Learn more about various `Pool` configuration settings from the
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/client/PoolFactory.html[PoolFactory API].
<5> Finally, we include a Spring `BeanPostProcessor` to block the client until our GemFire Server is up and running,
listening for and accepting client connections.
<1> First, we declare our Web application to be a Geode cache client by annotating our `ClientConfig` class
with `@ClientCacheApplication`. Additionally, we adjust a few basic, "DEFAULT" `Pool` settings.
<2> `@EnableGemFireHttpSession` creates a _Spring_ bean named `springSessionRepositoryFilter` that implements
`javax.servlet.Filter`. The filter is what replaces the `HttpSession` with an implementation provided by _Spring Session_
and backed by Apache Geode. This will also create the necessary client-side `Region` (by default, "ClusteredSpringSessions`,
which is a `PROXY` `Region`) corresponding to the same server-side `Region` by name. All Session state will be sent
from the cache client Web application to the server through `Region` data access operations. The client-side `Region`
will use the "DEFAULT" `Pool`.
<3> Then, we adjust the port used by the cache client `Pool` to connect to the `CacheServer`
using a SDG `ClientCacheConfigurer`.
The `gemfireCacheServerReadyBeanPostProcessor` is necessary in order to coordinate the client and server in
an automated fashion during testing, but unnecessary in situations where the GemFire cluster is already presently
running, such as in production.
TIP: In typical Geode production deployments, where the cluster includes potentially hundreds or thousands
of Geode servers (data nodes), it is more common for clients to connect to 1 or more Geode Locators running
in the cluster. A Locator passes meta-data to clients about the servers available in the cluster, the server load
and which servers have the client's data of interest, which is particularly important for direct, single-hop data access
and latency-sensitive operations. See more details about the
http://geode.apache.org/docs/guide/12/topologies_and_comm/cs_configuration/standard_client_server_deployment.html[Client/Server Deployment]
in the Apache Geode User Guide.
The `BeanPostProcessor` uses a GemFire http://geode.apache.org/releases/latest/javadoc/org/apache/geode/management/membership/ClientMembershipListener.html[ClientMembershipListener]
that will be notified when the client has successfully connected to the server. Once a connection has been established,
the listener releases the latch that the `BeanPostProcessor` will wait on (up to the specified timeout) in the
`postProcessAfterInitialization` callback to block the client.
NOTE: For more information on configuring _Spring Data Geode, refer to the
http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[Reference Guide].
TIP: In typical GemFire deployments, where the cluster includes potentially hundreds of GemFire data nodes (servers),
it is more common for clients to connect to one or more GemFire Locators running in the cluster. A Locator passes meta-data
to clients about the servers available, load and which servers have the client's data of interest, which is particularly
important for single-hop, direct data access. See more details about the http://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html[Client/Server Topology in GemFire's User Guide].
NOTE: For more information on configuring _Spring Data GemFire_, refer to the http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
The `@EnableGemFireHttpSession` annotation enables a developer to configure certain aspects of both Spring Session
and GemFire out-of-the-box using the following attributes:
`@EnableGemFireHttpSession` enables a developer to configure certain aspects of both _Spring Session_ and Apache Geode
out-of-the-box using the following attributes:
* `clientRegionShortcut` - specifies Apache Geode http://geode.apache.org/docs/guide/12/developing/region_options/region_types.html[data management policy]
on the client with a Geode http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
(default is `PROXY`). This attribute is only used when configuring a client `Region`.
* `indexableSessionAttributes` - Identifies the Session attributes by name that should be indexed for querying operations.
Only Session attributes identified by name will be indexed.
* `maxInactiveIntervalInSeconds` - controls _HttpSession_ idle-timeout expiration (defaults to **30 minutes**).
* `regionName` - specifies the name of the GemFire Region used to store `HttpSession` state (defaults is "*ClusteredSpringSessions*").
* `clientRegionShort` - specifies GemFire's http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html[data management policy]
with a GemFire http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
(default is `PROXY`). This attribute is only used when configuring client Region.
* `poolName` - name of the dedicated GemFire Pool used to connect a client to the cluster of servers. The attribute
is only used when the application is a GemFire cache client. Defaults to `gemfirePool`.
* `serverRegionShort` - specifies GemFire's http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html[data management policy]
using a GemFire http://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/org/apache/geode/cache/RegionShortcut.html[RegionShortcut]
(default is `PARTITION`). This attribute is only used when configuring server Regions, or when a p2p topology is employed.
* `poolName` - name of the dedicated Apache Geode `Pool` used to connect a client to the cluster of servers. The attribute
is only used when the application is a cache client. Defaults to `gemfirePool`.
* `regionName` - specifies the name of the Apache Geode `Region` used to store and manage `HttpSession` state
(default is "*ClusteredSpringSessions*").
* `serverRegionShortcut` - specifies Apache Geode http://geode.apache.org/docs/guide/12/developing/region_options/region_types.html[data management policy]
on the server using a Geode http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/RegionShortcut.html[RegionShortcut]
(default is `PARTITION`). This attribute is only used when configuring server `Regions`, or when a P2P topology is employed.
NOTE: It is important to note that the GemFire client Region name must match a server Region by the same name if
the client Region is a `PROXY` or `CACHING_PROXY`. Names are not required to match if the client Region used to
store Spring Sessions is `LOCAL`, however, keep in mind that your session state will not be propagated to the server
and you lose all benefits of using GemFire to store and manage distributed, replicated session state information
in a cluster.
NOTE: `serverRegionShort` is ignored in a client/server cache configuration and only applies when
a peer-to-peer (P2P) topology, and more specifically, a GemFire peer cache is used.
NOTE: It is important to remember that the Apache Geode client `Region` name must match a server `Region`
by the same name if the client `Region` is a `PROXY` or `CACHING_PROXY`. Client and server `Region` names
are not required to match if the client `Region` used to store Sessions is `LOCAL`. However, keep in mind
that Session state will not be propagated to the server and you lose all the benefits of using Apache Geode
to store and manage distributed, replicated Session state information on the servers in a cluster.
=== Server Configuration
We have only covered one side of the equation. We also need a GemFire Server for our client to talk to and send
session state to the server to manage.
So far, we only covered one side of the equation. We also need an Apache Geode Server for our cache client to talk to
and send Session state to the server to manage.
In this sample, we will use the following GemFire Server Java Configuration:
In this sample, we will use the following Java configuration to spin up an Apache Geode Server:
[source,java]
----
include::{samples-dir}javaconfig/gemfire-clientserver/src/main/java/sample/ServerConfig.java[tags=class]
----
<1> On the server, we also configure Spring Session using the `@EnableGemFireHttpSession` annotation. This ensures
the Region names on both the client and server match (in this sample, we use the default "_ClusteredSpringSessions_").
We have also set the session timeout to **30 seconds**. Later, we will see how this timeout is used.
<2> Next, we configure the GemFire Server using GemFire System Properties very much like our P2P samples.
With the `mcast-port` set to 0 and no `locators` property specified, our server will be standalone. We also allow a
JMX client (e.g. _Gfsh_) to connect to our server with the use of the GemFire-specific JMX System properties.
<3> Then, we create an instance of a GemFire peer `Cache` initialized with our GemFire System Properties.
<4> We also setup a GemFire `CacheServer` instance running on **localhost**, listening to port **12480**,
ready to accept our client connection.
<5> Finally, we declare a `main` method as an entry point for launching and running our GemFire Server
from the command-line.
<1> First, we use the **new** _Spring Data Geode_ configuration annotation `@CacheServerApplication` to simplify
the creation of a peer cache instance along with a `CacheServer` for cache clients to connect.
<2> (Optional) Then, the `ServerConfig` class is annotated with `@EnableGemFireHttpSession` to create the necessary
server-side `Region` (by default, "_ClusteredSpringSessions_") used to store the `HttpSessions` state. This step is
optional since the Session `Region` could be created manually, perhaps using external means.
Using `@EnableGemFireHttpSession` is convenient.
<3> Finally, we adjust the port that the `CacheServer` will use to listen for cache clients by declaring
a `CacheServerConfigurer` bean to modify the SDG `CacheServerFactoryBean` using property placeholders.
The sample makes use of _Spring's_ `PropertySourcesPlaceholderConfigurer` in order to externalize the sample
application's configuration using a properties file or with JVM System properties, which ever.
== Java Servlet Container Initialization
Our <<httpsession-spring-java-configuration,Spring Java Configuration>> created a Spring bean named `springSessionRepositoryFilter`
that implements `Filter`. The `springSessionRepositoryFilter` bean is responsible for replacing the `HttpSession`
with a custom implementation backed by Spring Session and GemFire.
Our <<httpsession-spring-java-configuration,Spring Java Configuration>> created a _Spring_ bean named `springSessionRepositoryFilter`
that implements `javax.servlet.Filter`. The `springSessionRepositoryFilter` bean is responsible for replacing the
`javax.servlet.http.HttpSession` with a custom implementation backed by _Spring Session_ and Apache Geode.
In order for our `Filter` to do its magic, Spring needs to load our `ClientConfig` class. We also need to ensure our
Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request. Fortunately, Spring Session
provides a utility class named `AbstractHttpSessionApplicationInitializer` to make both of these steps extremely easy.
In order for our `Filter` to do its magic, _Spring_ needs to load the `ClientConfig` class. We also need to ensure our
Servlet container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
Fortunately, _Spring Session_ provides a utility class named `AbstractHttpSessionApplicationInitializer` to make both
of these steps extremely easy.
You can find an example below:
@@ -177,36 +176,38 @@ You can find an example below:
include::{samples-dir}javaconfig/gemfire-clientserver/src/main/java/sample/Initializer.java[tags=class]
----
NOTE: The name of our class (`Initializer`) does not matter. What is important is that we extend `AbstractHttpSessionApplicationInitializer`.
NOTE: The name of our class (`Initializer`) does not matter. What is important is that we extend
`AbstractHttpSessionApplicationInitializer`.
<1> The first step is to extend `AbstractHttpSessionApplicationInitializer`.
This ensures that a Spring bean named `springSessionRepositoryFilter` is registered with our Servlet Container
and used for every request.
<2> `AbstractHttpSessionApplicationInitializer` also provides a mechanism to easily allow Spring to load our `ClientConfig`.
<1> The first step is to extend `AbstractHttpSessionApplicationInitializer`. This ensures that a _Spring_ bean named
`springSessionRepositoryFilter` is registered with our Servlet container and used on every HTTP request.
<2> `AbstractHttpSessionApplicationInitializer` also provides a mechanism to easily allow _Spring_ to load
our `ClientConfig`.
// end::config[]
[[httpsession-gemfire-clientserver-java-sample-app]]
== HttpSession with GemFire (Client/Server) Sample Application
[[spring-session-sample-java-geode-clientserver]]
== HttpSession managed by a Java configured, Apache Geode Client/Server Sample Application
=== Running the httpsession-gemfire-clientserver Sample Application
=== Running the Geode Sample Application
You can run the sample by obtaining the {download-url}[source code] and invoking the following commands.
First, you need to run the server using:
----
$ ./gradlew :samples:httpsession-gemfire-clientserver:run [-Dsample.httpsession.gemfire.log-level=info]
$ ./gradlew :spring-session-sample-javaconfig-gemfire-clientserver:run [-gemfire.log-level=info]
----
Then, in a separate terminal, you run the client using:
Then, in a separate terminal, run the client using:
----
$ ./gradlew :samples:httpsession-gemfire-clientserver:tomcatRun [-Dsample.httpsession.gemfire.log-level=info]
$ ./gradlew :spring-session-sample-javaconfig-gemfire-clientserver:tomcatRun [-gemfire.log-level=info]
----
You should now be able to access the application at http://localhost:8080/. In this sample, the web application
is the client cache and the server is standalone.
You should now be able to access the application at http://localhost:8080/.
In this sample, the web application is the Apache Geode cache client
and the server is standalone, separate (JVM) process.
=== Exploring the httpsession-gemfire-clientserver Sample Application
@@ -215,7 +216,7 @@ Try using the application. Fill out the form with the following information:
* **Attribute Name:** _username_
* **Attribute Value:** _john_
Now click the **Set Attribute** button. You should now see the values displayed in the table.
Now click the **Set Attribute** button. You should now see the attribute name and value displayed in the table.
=== How does it work?
@@ -227,21 +228,23 @@ We interact with the standard `HttpSession` in the `SessionServlet` shown below:
include::{samples-dir}javaconfig/gemfire-clientserver/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in GemFire.
Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
Instead of using Tomcat's `HttpSession`, we are actually persisting the Session in Apache Geode.
_Spring Session_ creates a cookie named SESSION in your browser that contains the id of your Session.
Go ahead and view the cookies (click for help with https://developer.chrome.com/devtools/docs/resources#cookies[Chrome]
or https://getfirebug.com/wiki/index.php/Cookies_Panel#Cookies_List[Firefox]).
NOTE: The following instructions assume you have a local GemFire installation. For more information on installation,
see http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
NOTE: The following instructions assume you have a local Apache Geode installation. For more information on installation,
see http://geode.apache.org/docs/guide/12/prereq_and_install.html[Prerequisites and Installation Instructions].
If you like, you can easily remove the session using `gfsh`. For example, on a Linux-based system type the following
at the command-line:
If you like, you can easily remove the Session using `gfsh`.
For example, on a Linux-based system type the following at the command-line:
$ gfsh
Then, enter the following commands in _Gfsh_ ensuring to replace `70002719-3c54-4c20-82c3-e7faa6b718f3` with the value
of your SESSION cookie, or the session ID returned by the GemFire OQL query (which should match):
Then, enter the following commands in _Gfsh_, ensuring to replace `70002719-3c54-4c20-82c3-e7faa6b718f3` with the value
of your SESSION cookie, or the Session id returned by the Apache Geode OQL query (which should match):
....
gfsh>connect --jmx-manager=localhost[1099]
@@ -262,11 +265,12 @@ NEXT_STEP_NAME : END
gfsh>remove --region=/ClusteredSpringSessions --key="70002719-3c54-4c20-82c3-e7faa6b718f3"
....
NOTE: The _GemFire User Guide_ has more detailed instructions on using http://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
NOTE: The _Apache Geode User Guide_ contains more detailed instructions on using
http://geode.apache.org/docs/guide/12/tools_modules/gfsh/chapter_overview.html[gfsh].
Now visit the application at http://localhost:8080/ again and observe that the attribute we added is no longer displayed.
Now visit the application at `http://localhost:8080/` again and observe the attribute we added is no longer displayed.
Alternatively, you can wait **30 seconds** for the session to expire and timeout, and then refresh the page. The attribute
we added should no longer be displayed in the table. However, keep in mind, that by refreshing the page, you will inadvertently
create a new (empty) session. If you run the query again, you will also see two session IDs, the new and the old,
since GemFire keeps a "tombstone" of the old session around.
Alternatively, you can wait **20 seconds** for the Session to timeout and expire and then refresh the page.
The attribute we added should no longer be displayed in the table. However, keep in mind, by refreshing the page,
you will inadvertently create a new (empty) Session. If you run the query again, you will also see two Session ids,
the new and the old, since Apache Geode keeps a "tombstone" of the old Session around.

View File

@@ -1,15 +1,16 @@
= Spring Session - HttpSession with GemFire P2P (Quick Start)
= Spring Session - HttpSession with Apache Geode P2P using Java Configuration
John Blum
:toc:
This guide describes how to configure Pivotal GemFire as a provider in Spring Session to transparently back
a web application's `HttpSession` using Java Configuration.
This guide describes how to configure Apache Geode as a provider in _Spring Session_ to transparently manage
a Web application's `javax.servlet.http.HttpSession` using Java configuration.
NOTE: The completed guide can be found in the <<httpsession-gemfire-p2p-java-sample-app,HttpSession with GemFire (P2P) Sample Application>>.
NOTE: The completed guide can be found in the <<spring-session-sample-java-gemfire-p2p,HttpSession with Apache Geode (P2P) Sample Application>>.
== Updating Dependencies
Before using Spring Session, you must ensure that the required dependencies are included.
If you are using Maven, include the following `dependencies` in your _pom.xml_:
Before using _Spring Session_, you must ensure that the required dependencies are included.
If you are using _Maven_, include the following `dependencies` in your `pom.xml`:
.pom.xml
[source,xml]
@@ -20,21 +21,21 @@ If you are using Maven, include the following `dependencies` in your _pom.xml_:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-gemfire</artifactId>
<version>{spring-session-version}</version>
<artifactId>spring-session-data-geode</artifactId>
<version>{spring-session-data-geode-version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-web</artifactId>
<version>{spring-version}</version>
<version>${spring-version}</version>
</dependency>
</dependencies>
----
ifeval::["{version-snapshot}" == "true"]
Since we are using a SNAPSHOT version, we need to add the Spring Snapshot Maven Repository.
If you are using Maven, include the following `repository` declaration in your _pom.xml_:
Since we are using a SNAPSHOT version, we need to add the _Spring_ Snapshot Maven Repository.
If you are using _Maven_, include the following `repository` declaration in your `pom.xml`:
.pom.xml
[source,xml]
@@ -51,8 +52,8 @@ If you are using Maven, include the following `repository` declaration in your _
endif::[]
ifeval::["{version-milestone}" == "true"]
Since we are using a Milestone version, we need to add the Spring Milestone Maven Repository.
If you are using Maven, include the following `repository` declaration in your _pom.xml_:
Since we are using a Milestone version, we need to add the _Spring_ Milestone Maven Repository.
If you are using _Maven_, include the following `repository` declaration in your `pom.xml`:
.pom.xml
[source,xml]
@@ -72,53 +73,56 @@ endif::[]
[[httpsession-spring-java-configuration-gemfire-p2p]]
== Spring Java Configuration
After adding the required dependencies and repository declarations, we can create our Spring configuration.
The Spring configuration is responsible for creating a Servlet Filter that replaces the `HttpSession`
with an implementation backed by Spring Session and GemFire.
After adding the required dependencies and repository declarations, we can create the _Spring_ configuration.
Add the following Spring Configuration:
The _Spring_ configuration is responsible for creating a `Servlet` `Filter` that replaces the `javax.servlet.http.HttpSession`
with an implementation backed by _Spring Session_ and Apache Geode.
Add the following _Spring_ configuration:
[source,java]
----
include::{samples-dir}javaconfig/gemfire-p2p/src/main/java/sample/Config.java[tags=class]
----
<1> The `@EnableGemFireHttpSession` annotation creates a Spring bean named `springSessionRepositoryFilter` that
implements `Filter`. The filter is what replaces the `HttpSession` with an implementation backed by Spring Session.
In this instance, Spring Session is backed by GemFire.
<2> Then, we configure a GemFire peer cache using standard GemFire System properties. We give the GemFire data node
a name using the `name` property and set `mcast-port` to 0. With the absence of a `locators` property, this data node
will be a standalone server. GemFire's `log-level` is set using an application-specific System property (`sample.httpsession.gemfire.log-level`)
that a user can specify on the command-line when running this sample application using either Maven or Gradle (default is "_warning_").
<3> Finally, we create an instance of the GemFire peer cache that embeds GemFire in the same JVM process as the running
Spring Session sample application.
<1> First, we use the **new** _Spring Data Geode_ configuration annotation `@PeerCacheApplication` to simplify
the creation of a peer cache instance.
<2> Then, the `Config` class is annotated with `@EnableGemFireHttpSession` to create the necessary server-side `Region`
(by default, "_ClusteredSpringSessions_") used to store the `HttpSessions` state.
<3> (Optionally) Finally, we annotated the `Config` class with `@EnableManager` to start an embedded Apache Geode Manager
service to allow JMX clients (e.g. Apache Geode's _Gfsh_ shell tool) to connect and inspect the server.
TIP: Additionally, we have configured this data node (server) as a GemFire Manager as well using GemFire-specific
JMX System properties that enable JMX client (e.g. _Gfsh_) to connect to this running data node.
NOTE: For more information on configuring _Spring Data Geode, refer to the
http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[Reference Guide].
NOTE: For more information on configuring _Spring Data GemFire_, refer to the http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
`@EnableGemFireHttpSession` enables a developer to configure certain aspects of both _Spring Session_ and Apache Geode
out-of-the-box using the following attributes:
The `@EnableGemFireHttpSession` annotation enables a developer to configure certain aspects of Spring Session
and GemFire out-of-the-box using the following attributes:
* `maxInactiveIntervalInSeconds` - controls HttpSession idle-timeout expiration (defaults to **30 minutes**).
* `regionName` - specifies the name of the GemFire Region used to store `HttpSession` state (defaults is "_ClusteredSpringSessions_").
* `serverRegionShort` - specifies GemFire http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html[data management policies]
with a GemFire http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/RegionShortcut.html[RegionShortcut]
(default is `PARTITION`).
NOTE: `clientRegionShort` is ignored in a peer cache configuration and only applies when a client-server topology,
and more specifically, a GemFire client cache is used.
* `clientRegionShortcut` - specifies Apache Geode http://geode.apache.org/docs/guide/12/developing/region_options/region_types.html[data management policy]
on the client with a Geode http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
(default is `PROXY`). This attribute is only used when configuring a client `Region`.
* `indexableSessionAttributes` - Identifies the Session attributes by name that should be indexed for querying operations.
Only Session attributes identified by name will be indexed.
* `maxInactiveIntervalInSeconds` - controls _HttpSession_ idle-timeout expiration (defaults to **30 minutes**).
* `poolName` - name of the dedicated Apache Geode `Pool` used to connect a client to the cluster of servers. The attribute
is only used when the application is a cache client. Defaults to `gemfirePool`.
* `regionName` - specifies the name of the Apache Geode `Region` used to store and manage `HttpSession` state
(default is "*ClusteredSpringSessions*").
* `serverRegionShortcut` - specifies Apache Geode http://geode.apache.org/docs/guide/12/developing/region_options/region_types.html[data management policy]
on the server using a Geode http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/RegionShortcut.html[RegionShortcut]
(default is `PARTITION`). This attribute is only used when configuring server `Regions`, or when a P2P topology is employed.
== Java Servlet Container Initialization
Our <<httpsession-spring-java-configuration,Spring Java Configuration>> created a Spring bean named `springSessionRepositoryFilter`
that implements `Filter`. The `springSessionRepositoryFilter` bean is responsible for replacing the `HttpSession`
with a custom implementation backed by Spring Session and GemFire.
Our <<[httpsession-spring-java-configuration-gemfire-p2p,Spring Java Configuration>> created a _Spring_ bean named
`springSessionRepositoryFilter` that implements `javasx.servlet.Filter`. The `springSessionRepositoryFilter` bean
is responsible for replacing the `javax.servlet.http.HttpSession` with a custom implementation backed by _Spring Session_
and Apache Geode.
In order for our `Filter` to do its magic, Spring needs to load our `Config` class. We also need to ensure our
Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request. Fortunately, Spring Session
provides a utility class named `AbstractHttpSessionApplicationInitializer` to make both of these steps extremely easy.
In order for our `Filter` to do its magic, _Spring_ needs to load our `Config` class. We also need to ensure our Servlet container (i.e. Tomcat) uses our `springSessionRepositoryFilter` on every HTTP request.
Fortunately, _Spring Session_ provides a utility class named `AbstractHttpSessionApplicationInitializer` to make both
of these steps extremely easy.
You can find an example below:
@@ -128,29 +132,29 @@ You can find an example below:
include::{samples-dir}javaconfig/gemfire-p2p/src/main/java/sample/Initializer.java[tags=class]
----
NOTE: The name of our class (`Initializer`) does not matter. What is important is that we extend `AbstractHttpSessionApplicationInitializer`.
NOTE: The name of our class (`Initializer`) does not matter. What is important is that we extend
`AbstractHttpSessionApplicationInitializer`.
<1> The first step is to extend `AbstractHttpSessionApplicationInitializer`.
This ensures that a Spring bean named `springSessionRepositoryFilter` is registered with our Servlet Container
and used for every request.
<2> `AbstractHttpSessionApplicationInitializer` also provides a mechanism to easily allow Spring to load our `Config`.
<1> The first step is to extend `AbstractHttpSessionApplicationInitializer`. This ensures that a _Spring_ bean named
`springSessionRepositoryFilter` is registered with our Servlet container and used on every HTTP request.
<2> `AbstractHttpSessionApplicationInitializer` also provides a mechanism to easily allow _Spring_ to load
our `Config` class.
// end::config[]
[[httpsession-gemfire-p2p-java-sample-app]]
== HttpSession with GemFire (P2P) Sample Application
[[spring-session-sample-java-gemfire-p2p]]
== HttpSession with Apache Geode (P2P) Sample Application
=== Running the httpsession-gemfire-p2p Sample Application
=== Running the Geode P2P Java Sample Application
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
----
$ ./gradlew :samples:httpsession-gemfire-p2p:tomcatRun [-Dsample.httpsession.gemfire.log-level=info]
$ ./gradlew :spring-session-sample-javaconfig-gemfire-p2p:tomcatRun [-Dgemfire.log-level=info]
----
You should now be able to access the application at http://localhost:8080/
You should now be able to access the application at http://localhost:8080/.
=== Exploring the httpsession-gemfire-p2p Sample Application
=== Exploring the Geode P2P Java Sample Application
Try using the application. Fill out the form with the following information:
@@ -169,21 +173,23 @@ We interact with the standard `HttpSession` in the `SessionServlet` shown below:
include::{samples-dir}javaconfig/gemfire-p2p/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in GemFire.
Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
Instead of using Tomcat's `HttpSession`, we are actually persisting the Session in Apache Geode.
_Spring Session_ creates a cookie named SESSION in your browser that contains the id of your Session.
Go ahead and view the cookies (click for help with https://developer.chrome.com/devtools/docs/resources#cookies[Chrome]
or https://getfirebug.com/wiki/index.php/Cookies_Panel#Cookies_List[Firefox]).
NOTE: The following instructions assume you have a local GemFire installation. For more information on installation,
see http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
NOTE: The following instructions assume you have a local Apache Geode installation. For more information on installation,
see http://geode.apache.org/docs/guide/12/prereq_and_install.html[Prerequisites and Installation Instructions].
If you like, you can easily remove the session using `gfsh`. For example, on a Linux-based system type the following
at the command-line:
If you like, you can easily remove the Session using `gfsh`.
For example, on a Linux-based system type the following at the command-line:
$ gfsh
Then, enter the following into _Gfsh_ ensuring to replace `70002719-3c54-4c20-82c3-e7faa6b718f3` with the value
of your SESSION cookie, or the session ID returned by the GemFire OQL query (which should match):
Then, enter the following into _Gfsh_, ensuring to replace `70002719-3c54-4c20-82c3-e7faa6b718f3` with the value
of your SESSION cookie, or the Session id returned by the Apache Geode OQL query (which should match):
....
gfsh>connect --jmx-manager=localhost[1099]
@@ -204,6 +210,7 @@ NEXT_STEP_NAME : END
gfsh>remove --region=/ClusteredSpringSessions --key="70002719-3c54-4c20-82c3-e7faa6b718f3"
....
NOTE: The _GemFire User Guide_ has more detailed instructions on using http://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
NOTE: The _Apache Geode User Guide_ contains more detailed instructions on using
http://geode.apache.org/docs/guide/12/tools_modules/gfsh/chapter_overview.html[gfsh].
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.
Now visit the application at `http://localhost:8080/` again and observe the attribute we added is no longer displayed.

View File

@@ -1,15 +1,16 @@
= Spring Session - HttpSession with GemFire Client/Server using XML (Quick Start)
= Spring Session - HttpSession with Apache Geode Client/Server using XML Configuration
John Blum
:toc:
This guide describes how to configure Spring Session to transparently leverage Pivotal GemFire to back a web application's
`HttpSession` using XML Configuration.
This guide describes how to configure _Spring Session_ to transparently leverage Apache Geode to manage
a Web application's `javax.servlet.http.HttpSession` using XML Configuration.
NOTE: The completed guide can be found in the <<httpsession-gemfire-clientserver-xml-sample-app,HttpSession with GemFire (Client/Server) using XML Sample Application>>.
NOTE: The completed guide can be found in the <<spring-session-sample-xml-geode-clientserver,Spring XML Configuation>>.
== Updating Dependencies
Before using Spring Session, you must ensure that the required dependencies are included.
If you are using Maven, include the following `dependencies` in your _pom.xml_:
Before using _Spring Session_, you must ensure that the required dependencies are included.
If you are using _Maven_, include the following `dependencies` in your `pom.xml`:
.pom.xml
[source,xml]
@@ -20,21 +21,21 @@ If you are using Maven, include the following `dependencies` in your _pom.xml_:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-gemfire</artifactId>
<version>{spring-session-version}</version>
<artifactId>spring-session-data-geode</artifactId>
<version>{spring-session-data-geode-version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-web</artifactId>
<version>{spring-version}</version>
<version>${spring-version}</version>
</dependency>
</dependencies>
----
ifeval::["{version-snapshot}" == "true"]
Since we are using a SNAPSHOT version, we need to add the Spring Snapshot Maven Repository.
If you are using Maven, include the following `repository` declaration in your _pom.xml_:
Since we are using a SNAPSHOT version, we need to add the _Spring_ Snapshot Maven Repository.
If you are using _Maven_, include the following `repository` declaration in your `pom.xml`:
.pom.xml
[source,xml]
@@ -51,8 +52,8 @@ If you are using Maven, include the following `repository` declaration in your _
endif::[]
ifeval::["{version-milestone}" == "true"]
Since we are using a Milestone version, we need to add the Spring Milestone Maven Repository.
If you are using Maven, include the following `repository` declaration in your _pom.xml_:
Since we are using a Milestone version, we need to add the _Spring_ Milestone Maven Repository.
If you are using _Maven_, include the following `repository` declaration in your `pom.xml`:
.pom.xml
[source,xml]
@@ -69,95 +70,87 @@ If you are using Maven, include the following `repository` declaration in your _
endif::[]
// tag::config[]
[[httpsession-spring-xml-configuration-gemfire-clientserver]]
[[spring-session-sample-xml-geode-clientserver]]
== Spring XML Configuration
After adding the required dependencies and repository declarations, we can create our Spring configuration.
The Spring configuration is responsible for creating a Servlet Filter that replaces the `HttpSession`
with an implementation backed by Spring Session and GemFire.
After adding the required dependencies and repository declarations, we can create the _Spring_ configuration.
The _Spring_ configuration is responsible for creating a `Servlet` `Filter` that replaces the `javax.servlet.http.HttpSession`
with an implementation backed by _Spring Session_ and Apache Geode.
Add the following Spring Configuration:
=== Client Configuration
Add the following _Spring_ configuration:
[source,xml]
----
include::{samples-dir}xml/gemfire-clientserver/src/main/webapp/WEB-INF/spring/session-client.xml[tags=beans]
----
<1> Spring annotation configuration support is enabled with `<context:annotation-config/>` element so that any
Spring beans declared in the XML config that are annotated with either Spring or Standard Java annotations supported
by Spring will be configured appropriately.
<2> The `META-INF/spring/application.properties` file are used along with the `PropertySourcesPlaceholderConfigurer`
bean to replace placeholders in the Spring XML configuration meta-data with the approrpriate property values.
<3> Then the `GemFireCacheSeverReadyBeanPostProcessor`is registered to determine whether a GemFire Server
at the designated host/port is running and listening for client connections, blocking client startup until
the server is available and ready.
<4> Next, we include a `Properties` bean to configure certain aspects of the GemFire client cache using
http://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html[GemFire's System Properties].
In this case, we are just setting GemFire's `log-level` from a application-specific System property, defaulting
to `warning` if unspecified.
<5> Then we create a instance of a GemFire `ClientCache` initialized with our `gemfireProperties`.
<6> We configure a Pool of client connections to talk to the GemFire Server in our Client/Server topology.
<1> (Optional) First, we can include a `Properties` bean to configure certain aspects of the Apache Geode `ClientCache`
using http://geode.apache.org/docs/guide/12/reference/topics/gemfire_properties.html[GemFire Properties]. In this case,
we are just setting Apache Geode's "`log-level`" from a application-specific System property, defaulting to "`warning`"
if unspecified.
<2> We must create an instance of an Apache Geode `ClientCache` initialized with our `gemfireProperties`.
<3> Then we configure a `Pool` of client connections to talk to the Apache Geode Server in our Client/Server topology.
In our configuration, we use sensible settings for timeouts, number of connections and so on. Also, our `Pool`
has been configured to connect directly to a server.
<7> Finally, the `GemFireHttpSessionConfiguration` is registered to enable Spring Session functionality.
has been configured to connect directly to the server.
<4> Finally, a `GemFireHttpSessionConfiguration` bean is registered to enable _Spring Session_ functionality.
TIP: In typical GemFire deployments, where the cluster includes potentially hundreds of GemFire data nodes (servers),
it is more common for clients to connect to one or more GemFire Locators running in the cluster. A Locator passes meta-data
to clients about the servers available, load and which servers have the client's data of interest, which is particularly
important for single-hop, direct data access. See more details about the http://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html[Client/Server Topology in GemFire's User Guide].
TIP: In typical Geode production deployments, where the cluster includes potentially hundreds or thousands
of Geode servers (data nodes), it is more common for clients to connect to 1 or more Geode Locators running
in the cluster. A Locator passes meta-data to clients about the servers available in the cluster, the server load
and which servers have the client's data of interest, which is particularly important for direct, single-hop data access
and latency-sensitive operations. See more details about the
http://geode.apache.org/docs/guide/12/topologies_and_comm/cs_configuration/standard_client_server_deployment.html[Client/Server Deployment]
in the Apache Geode User Guide.
NOTE: For more information on configuring _Spring Data GemFire_, refer to the http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
NOTE: For more information on configuring _Spring Data Geode, refer to the
http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[Reference Guide].
=== Server Configuration
We have only covered one side of the equation. We also need a GemFire Server for our client to talk to and send
session state information to the server to manage.
So far, we only covered one side of the equation. We also need an Apache Geode Server for our cache client to talk to
and send Session state to the server to manage.
In this sample, we will use the following GemFire Server Java Configuration:
In this sample, we will use the following XML configuration to spin up an Apache Geode Server:
[source,xml]
----
include::{samples-dir}xml/gemfire-clientserver/src/main/resources/META-INF/spring/session-server.xml[tags=beans]
----
<1> First, we enable Spring annotation config support with the `<context:annotation-config>` element so that any
Spring beans declared in the XML config that are annotated with either Spring or Standard Java annotations supported
by Spring will be configured appropriately.
<2> A `PropertySourcesPlaceholderConfigurer` is registered to replace placeholders in our Spring XML configuration
meta-data with property values in the `META-INF/spring/application.properties` file.
<3> Next, we configure the GemFire Server using GemFire System Properties very much like our P2P samples.
With the `mcast-port` set to 0 and no `locators` property specified, our server will be standalone. We also allow a
JMX client (e.g. _Gfsh_) to connect to our server with the use of the GemFire-specific JMX System properties.
<4> Then we create an instance of a GemFire peer `Cache` initialized with our GemFire System Properties.
<5> We also setup a GemFire `CacheServer` instance running on *localhost*, listening to port **11235**,
ready to accept our client connection.
<6> Finally, we enable the same Spring Session functionality we used on the client by registering an instance of
`GemFireHttpSessionConfiguration`, except that we set the session expiration timeout to **30 seconds**.
We will explain later what this means.
<1> (Optional) First, we can include a `Properties` bean to configure certain aspects of the Apache Geode peer `Cache`
using http://geode.apache.org/docs/guide/12/reference/topics/gemfire_properties.html[GemFire Properties]. In this case,
we are just setting Apache Geode's "`log-level`" from a application-specific System property, defaulting to "`warning`"
if unspecified.
<2> We must configure an Apache Geode peer `Cache` instance initialized with the Apache Geode properties.
<3> Next, we define a `CacheServer` with sensible configuration for `bind-address` and `port` used by our cache client
application to connect to the server to pass Session state.
<4> Finally, we enable the same _Spring Session_ functionality we declared in the client XML configuration
by registering an instance of `GemFireHttpSessionConfiguration`, except we set the Session expiration timeout
to **30 seconds**. We explain what this means later.
The GemFire Server configuration gets bootstrapped with the following:
The Apache Geode Server gets bootstrapped with the following:
[source,java]
----
include::{samples-dir}xml/gemfire-clientserver/src/main/java/sample/Application.java[tags=class]
include::{samples-dir}xml/gemfire-clientserver/src/main/java/sample/ServerConfig.java[tags=class]
----
TIP: Instead of a simple Java class with a main method, you could also use _Spring Boot_.
TIP: Rather than defining a simple Java class with a `main` method, you might consider using _Spring Boot_ instead.
<1> The `@Configuration` annotation designates this Java class as a source for Spring configuration meta-data using
Spring's annotation configuration support.
<2> Primarily, the configuration comes from the `META-INF/spring/session-server.xml` file, which is also the reason
why _Spring Boot_ was not used in this sample, since using XML seemingly defeats the purpose and benefits
of using Spring Boot. However, this sample is about demonstrating how to use Spring XML to configure
the GemFire client and server.
<1> The `@Configuration` annotation designates this Java class as a source of _Spring_ configuration meta-data using
7.9. Annotation-based container configuration[_Spring's_ annotation configuration support].
<2> Primarily, the configuration comes from the `META-INF/spring/session-server.xml` file.
== XML Servlet Container Initialization
Our <<httpsession-spring-xml-configuration,Spring XML Configuration>> created a Spring bean named `springSessionRepositoryFilter`
that implements `Filter`. The `springSessionRepositoryFilter` bean is responsible for replacing the `HttpSession` with
a custom implementation that is backed by Spring Session and GemFire.
Our <<httpsession-spring-xml-configuration,Spring XML Configuration>> created a _Spring_ bean named `springSessionRepositoryFilter`
that implements `javax.servlet.Filter` intervace. The `springSessionRepositoryFilter` bean is responsible for replacing
the `javax.servlet.http.HttpSession` with a custom implementation that is provided by _Spring Session_ and Apache Geode.
In order for our `Filter` to do its magic, we need to instruct _Spring_ to load our `session-client.xml` configuration file.
In order for our `Filter` to do its magic, we need to instruct Spring to load our `session-client.xml` configuration file.
We do this with the following configuration:
.src/main/webapp/WEB-INF/web.xml
@@ -170,7 +163,7 @@ include::{samples-dir}xml/gemfire-clientserver/src/main/webapp/WEB-INF/web.xml[t
The http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-create[ContextLoaderListener]
reads the `contextConfigLocation` context parameter value and picks up our _session-client.xml_ configuration file.
Finally, we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter`
Finally, we need to ensure that our Servlet container (i.e. Tomcat) uses our `springSessionRepositoryFilter`
for every request.
The following snippet performs this last step for us:
@@ -182,12 +175,12 @@ include::{samples-dir}xml/gemfire-clientserver/src/main/webapp/WEB-INF/web.xml[t
----
The http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[DelegatingFilterProxy]
will look up a bean by the name of `springSessionRepositoryFilter` and cast it to a `Filter`. For every request that `DelegatingFilterProxy`
is invoked, the `springSessionRepositoryFilter` will be invoked.
will look up a bean by the name of `springSessionRepositoryFilter` and cast it to a `Filter`. For every HTTP request,
the `DelegatingFilterProxy` is invoked, which delegates to the `springSessionRepositoryFilter`.
// end::config[]
[[httpsession-gemfire-clientserver-xml-sample-app]]
== HttpSession with GemFire (Client/Server) using XML Sample Application
== HttpSession with Apache Geode (Client/Server) using XML Sample Application
=== Running the httpsession-gemfire-clientserver-xml Sample Application
@@ -197,17 +190,19 @@ You can run the sample by obtaining the {download-url}[source code] and invoking
First, you need to run the server using:
----
$ ./gradlew :samples:httpsession-gemfire-clientserver-xml:run [-Dsample.httpsession.gemfire.log-level=info]
$ ./gradlew :spring-session-sample-javaconfig-gemfire-clientserver:run [-Dgemfire.log-level=info]
----
Now, in a separate terminal, you can run the client using:
----
$ ./gradlew :samples:httpsession-gemfire-clientserver-xml:tomcatRun [-Dsample.httpsession.gemfire.log-level=info]
$ ./gradlew :spring-session-sample-javaconfig-gemfire-clientserver:tomcatRun [-gemfire.log-level=info]
----
You should now be able to access the application at http://localhost:8080/. In this sample, the web application
is the client cache and the server is standalone.
You should now be able to access the application at http://localhost:8080/.
In this sample, the web application is the Apache Geode cache client
and the server is standalone, separate (JVM) process.
=== Exploring the httpsession-gemfire-clientserver-xml Sample Application
@@ -228,21 +223,23 @@ We interact with the standard `HttpSession` in the `SessionServlet` shown below:
include::{samples-dir}xml/gemfire-clientserver/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in GemFire.
Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
Instead of using Tomcat's `HttpSession`, we are actually persisting the Session in Apache Geode.
_Spring Session_ creates a cookie named SESSION in your browser that contains the id of your Session.
Go ahead and view the cookies (click for help with https://developer.chrome.com/devtools/docs/resources#cookies[Chrome]
or https://getfirebug.com/wiki/index.php/Cookies_Panel#Cookies_List[Firefox]).
NOTE: The following instructions assume you have a local GemFire installation. For more information on installation,
see http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
NOTE: The following instructions assume you have a local Apache Geode installation. For more information on installation,
see http://geode.apache.org/docs/guide/12/prereq_and_install.html[Prerequisites and Installation Instructions].
If you like, you can easily remove the session using `gfsh`. For example, on a Linux-based system type the following
at the command-line:
If you like, you can easily remove the session using `gfsh`.
For example, on a Linux-based system type the following at the command-line:
$ gfsh
Then, enter the following commands in _Gfsh_ ensuring to replace `70002719-3c54-4c20-82c3-e7faa6b718f3` with the value
of your SESSION cookie, or the session ID returned by the GemFire OQL query (which should match):
Then, enter the following commands in _Gfsh_, ensuring to replace `70002719-3c54-4c20-82c3-e7faa6b718f3` with the value
of your SESSION cookie, or the Session id returned by the Apache Geode OQL query (which should match):
....
gfsh>connect --jmx-manager=localhost[1099]
@@ -263,11 +260,12 @@ NEXT_STEP_NAME : END
gfsh>remove --region=/ClusteredSpringSessions --key="70002719-3c54-4c20-82c3-e7faa6b718f3"
....
NOTE: The _GemFire User Guide_ has more detailed instructions on using http://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
NOTE: The _Apache Geode User Guide_ contains more detailed instructions on using
http://geode.apache.org/docs/guide/12/tools_modules/gfsh/chapter_overview.html[gfsh].
Now visit the application at http://localhost:8080/ again and observe that the attribute we added is no longer displayed.
Now visit the application at `http://localhost:8080/` again and observe the attribute we added is no longer displayed.
Alternatively, you can wait *30 seconds* for the session to timeout (i.e. expire) and refresh the page. Again, the
attribute we added should no longer be displayed in the table. However, keep in mind, that by refreshing the page,
you will inadvertently create a new (empty) session. If you run the query again, you will also see two session IDs,
the new and the old, since GemFire keeps a "tombstone" of the old session around.
Alternatively, you can wait **20 seconds** for the Session to timeout and expire and then refresh the page.
The attribute we added should no longer be displayed in the table. However, keep in mind, by refreshing the page,
you will inadvertently create a new (empty) Session. If you run the query again, you will also see two Session ids,
the new and the old, since Apache Geode keeps a "tombstone" of the old Session around.

View File

@@ -1,15 +1,17 @@
= Spring Session - HttpSession with GemFire P2P using XML (Quick Start)
= Spring Session - HttpSession with Apache Geode P2P using XML Configuration
John Blum
:toc:
This guide describes how to configure Pivotal GemFire as a provider in Spring Session to transparently back
a web application's `HttpSession` using XML Configuration.
This guide describes how to configure Apache Geode as a provider in _Spring Session_ to transparently manage
a Web application's `javax.servlet.http.HttpSession` using XML configuration.
NOTE: The completed guide can be found in the <<httpsession-gemfire-p2p-xml-sample-app,HttpSession with GemFire (P2P) using XML Sample Application>>.
NOTE: The completed guide can be found in the
<<spring-session-sample-xml-gemfire-p2p,HttpSession with Apache Geode (P2P) using XML Sample Application>>.
== Updating Dependencies
Before using Spring Session, you must ensure that the required dependencies are included.
If you are using Maven, include the following `dependencies` in your _pom.xml_:
Before using _Spring Session_, you must ensure that the required dependencies are included.
If you are using _Maven_, include the following `dependencies` in your `pom.xml`:
.pom.xml
[source,xml]
@@ -20,21 +22,21 @@ If you are using Maven, include the following `dependencies` in your _pom.xml_:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-gemfire</artifactId>
<version>{spring-session-version}</version>
<artifactId>spring-session-data-geode</artifactId>
<version>{spring-session-data-geode-version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-web</artifactId>
<version>{spring-version}</version>
<version>${spring-version}</version>
</dependency>
</dependencies>
----
ifeval::["{version-snapshot}" == "true"]
Since we are using a SNAPSHOT version, we need to add the Spring Snapshot Maven Repository.
If you are using Maven, include the following `repository` declaration in your _pom.xml_:
Since we are using a SNAPSHOT version, we need to add the _Spring_ Snapshot Maven Repository.
If you are using _Maven_, include the following `repository` declaration in your `pom.xml`:
.pom.xml
[source,xml]
@@ -51,8 +53,8 @@ If you are using Maven, include the following `repository` declaration in your _
endif::[]
ifeval::["{version-milestone}" == "true"]
Since we are using a Milestone version, we need to add the Spring Milestone Maven Repository.
If you are using Maven, include the following `repository` declaration in your _pom.xml_:
Since we are using a Milestone version, we need to add the _Spring_ Milestone Maven Repository.
If you are using _Maven_, include the following `repository` declaration in your `pom.xml`:
.pom.xml
[source,xml]
@@ -69,14 +71,15 @@ If you are using Maven, include the following `repository` declaration in your _
endif::[]
// tag::config[]
[[httpsession-spring-xml-configuration-gemfire-p2p]]
[[httpsession-spring-xml-configuration]]
== Spring XML Configuration
After adding the required dependencies and repository declarations, we can create our Spring configuration.
The Spring configuration is responsible for creating a Servlet Filter that replaces the `HttpSession`
with an implementation backed by Spring Session and GemFire.
After adding the required dependencies and repository declarations, we can create the _Spring_ configuration.
Add the following Spring Configuration:
The _Spring_ configuration is responsible for creating a `Servlet` `Filter` that replaces the `javax.servlet.http.HttpSession`
with an implementation backed by _Spring Session_ and Apache Geode.
Add the following Spring configuration:
.src/main/webapp/WEB-INF/spring/session.xml
[source,xml,indent=0]
@@ -84,31 +87,27 @@ Add the following Spring Configuration:
include::{samples-dir}xml/gemfire-p2p/src/main/webapp/WEB-INF/spring/session.xml[tags=beans]
----
<1> We use the combination of `<context:annotation-config/>` and `GemFireHttpSessionConfiguration` because Spring Session
does not yet provide XML Namespace support (see https://github.com/spring-projects/spring-session/issues/104[gh-104]).
This creates a Spring bean with the name of `springSessionRepositoryFilter` that implements `Filter`. The filter is what
replaces the `HttpSession` with an implementation backed by Spring Session.
In this instance, Spring Session is backed by GemFire.
<2> Then, we configure a GemFire peer cache using standard GemFire System properties. We give the GemFire data node
a name using the `name` property and set `mcast-port` to 0. With the absence of a `locators` property, this data node
will be a standalone server. GemFire's `log-level` is set using an application-specific System property
(`sample.httpsession.gemfire.log-level`) that a user can specify on the command-line when running this application
using either Maven or Gradle (default is "_warning_").
<3> Finally, we create an instance of the GemFire peer cache that embeds GemFire in the same JVM process as the running
Spring Session sample application.
<1> (Optional) First, we can include a `Properties` bean to configure certain aspects of the Apache Geode peer `Cache`
using http://geode.apache.org/docs/guide/12/reference/topics/gemfire_properties.html[GemFire Properties]. In this case,
we are just setting Apache Geode's "`log-level`" from a application-specific System property, defaulting to "`warning`"
if unspecified.
<2> We must configure an Apache Geode peer `Cache` instance initialized with the Apache Geode properties.
<3> Finally, we enable _Spring Session_ functionality by registering an instance of `GemFireHttpSessionConfiguration`.
TIP: Additionally, we have configured this data node (server) as a GemFire Manager as well using GemFire-specific
JMX System properties that enable JMX client (e.g. _Gfsh_) to connect to this running data node.
TIP: Additionally, we have configured this data node (server) as a Apache Geode Manager as well using Geode-specific
JMX properties that enable JMX client (e.g. _Gfsh_) to connect to this running server.
NOTE: For more information on configuring _Spring Data GemFire_, refer to the http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
NOTE: For more information on configuring _Spring Data Geode, refer to the
http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[Reference Guide].
== XML Servlet Container Initialization
Our <<httpsession-spring-xml-configuration,Spring XML Configuration>> created a Spring bean named `springSessionRepositoryFilter`
that implements `Filter`. The `springSessionRepositoryFilter` bean is responsible for replacing the `HttpSession` with
a custom implementation that is backed by Spring Session and GemFire.
The <<httpsession-spring-xml-configuration,Spring XML Configuration>> created a _Spring_ bean named `springSessionRepositoryFilter`
that implements `javax.servlet.Filter`. The `springSessionRepositoryFilter` bean is responsible for replacing
the `javax.servlet.http.HttpSession` with a custom implementation that is backed by _Spring Session_ and Apache Geode.
In order for our `Filter` to do its magic, we need to instruct _Spring_ to load our `session.xml` configuration file.
In order for our `Filter` to do its magic, we need to instruct Spring to load our `session.xml` configuration file.
We do this with the following configuration:
.src/main/webapp/WEB-INF/web.xml
@@ -121,8 +120,8 @@ include::{samples-dir}xml/gemfire-p2p/src/main/webapp/WEB-INF/web.xml[tags=liste
The http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-create[ContextLoaderListener]
reads the `contextConfigLocation` context parameter value and picks up our _session.xml_ configuration file.
Finally, we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter`
for every request.
Finally, we need to ensure that our Servlet container (i.e. Tomcat) uses our `springSessionRepositoryFilter`
for every HTTP request.
The following snippet performs this last step for us:
@@ -133,25 +132,24 @@ include::{samples-dir}xml/gemfire-p2p/src/main/webapp/WEB-INF/web.xml[tags=sprin
----
The http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[DelegatingFilterProxy]
will look up a bean by the name of `springSessionRepositoryFilter` and cast it to a `Filter`. For every request that `DelegatingFilterProxy`
is invoked, the `springSessionRepositoryFilter` will be invoked.
will look up a bean by the name of `springSessionRepositoryFilter` and cast it to a `Filter`. For every HTTP request
the `DelegatingFilterProxy` is invoked, delegating to the `springSessionRepositoryFilter`.
// end::config[]
[[httpsession-gemfire-p2p-xml-sample-app]]
== HttpSession with GemFire (P2P) using XML Sample Application
[[spring-session-sample-xml-gemfire-p2p]]
== HttpSession with Apache Geode (P2P) using XML Sample Application
=== Running the httpsession-gemfire-p2p-xml Sample Application
=== Running the Geode XML Sample Application
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
----
$ ./gradlew :samples:httpsession-gemfire-p2p-xml:tomcatRun [-Dsample.httpsession.gemfire.log-level=info]
$ ./gradlew :spring-session-sample-xml-gemfire-p2p:tomcatRun [-Dgemfire.log-level=info]
----
You should now be able to access the application at http://localhost:8080/
You should now be able to access the application at http://localhost:8080/.
=== Exploring the httpsession-gemfire-p2p-xml Sample Application
=== Exploring the Geode XML Sample Application
Try using the application. Fill out the form with the following information:
@@ -170,21 +168,23 @@ We interact with the standard `HttpSession` in the `SessionServlet` shown below:
include::{samples-dir}xml/gemfire-p2p/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in GemFire.
Spring Session creates a cookie named SESSION in your browser that contains the id of your session.
Instead of using Tomcat's `HttpSession`, we are actually persisting the Session in Apache Geode.
_Spring Session_ creates a cookie named SESSION in your browser that contains the id of your session.
Go ahead and view the cookies (click for help with https://developer.chrome.com/devtools/docs/resources#cookies[Chrome]
or https://getfirebug.com/wiki/index.php/Cookies_Panel#Cookies_List[Firefox]).
NOTE: The following instructions assume you have a local GemFire installation. For more information on installation,
see http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
NOTE: The following instructions assume you have a local Apache Geode installation. For more information on installation,
see http://geode.apache.org/docs/guide/12/prereq_and_install.html[Prerequisites and Installation Instructions].
If you like, you can easily remove the session using `gfsh`. For example, on a Linux-based system type the following
at the command-line:
If you like, you can easily remove the session using `gfsh`.
For example, on a Linux-based system type the following at the command-line:
$ gfsh
Then, enter the following into _Gfsh_ ensuring to replace `70002719-3c54-4c20-82c3-e7faa6b718f3` with the value
of your SESSION cookie, or the session ID returned by the GemFire OQL query (which should match):
Then, enter the following into _Gfsh_, ensuring to replace `70002719-3c54-4c20-82c3-e7faa6b718f3` with the value
of your SESSION cookie, or the Session id returned by the Apache Geode OQL query (which should match):
....
gfsh>connect --jmx-manager=localhost[1099]
@@ -205,6 +205,7 @@ NEXT_STEP_NAME : END
gfsh>remove --region=/ClusteredSpringSessions --key="70002719-3c54-4c20-82c3-e7faa6b718f3"
....
NOTE: The _GemFire User Guide_ has more detailed instructions on using http://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
NOTE: The _Apache Geode User Guide_ contains more detailed instructions on using
http://geode.apache.org/docs/guide/12/tools_modules/gfsh/chapter_overview.html[gfsh].
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.
Now visit the application at `http://localhost:8080/` again and observe the attribute we added is no longer displayed.

View File

@@ -13,43 +13,33 @@ _Spring Session_ provides an API and implementations for managing a user's sessi
_Spring Session_ provides an API and implementations for managing a user's session information.
It also provides transparent integration with:
* <<httpsession,HttpSession>> - allows replacing the HttpSession in an application container (e.g. Tomcat) neutral way.
* <<httpsession,HttpSession>> - allows replacing the `javax.servlet.http.HttpSession` in an application container
(e.g. Tomcat) neutral way.
Additional features include:
** **Clustered Sessions** - _Spring Session_ makes it trivial to support <<httpsession-gemfire,clustered sessions>>
without being tied to an application container specific solution.
** **Multiple Browser Sessions** - _Spring Session_ supports <<httpsession-multi,managing multiple users' sessions>>
in a single browser instance (i.e. multiple authenticated accounts similar to Google).
** **RESTful APIs** - _Spring Session_ allows providing session ids in headers to work
with <<httpsession-rest,RESTful APIs>>
* <<websocket,WebSocket>> - provides the ability to keep the `HttpSession` alive when receiving WebSocket messages
** **Multiple Browser Sessions** - _Spring Session_ supports managing _multiple user sessions_ in a single browser
instance (i.e. multiple authenticated accounts similar to Google).
** **REST API** - _Spring Session_ allows providing the session ID in headers to work with REST APIs.
** **WebSocket** - provides the ability to keep the `javax.servlet.http.HttpSession` alive
when receiving `WebSocket` messages
[[samples]]
== Samples and Guides (Start Here)
If you are looking to get started with Spring Session, the best place to start is our Sample Applications.
If you are looking to get started with _Spring Session_ right of way, the best place to start
is with our Sample Applications.
.Sample Applications using Spring Boot
|===
| Source | Description | Guide
| {gh-samples-url}boot/gemfire[HttpSession with GemFire]
| Demonstrates how to use Spring Session to replace the `HttpSession` with GemFire using a Client/Server topology.
| link:guides/boot-gemfire.html[HttpSession with GemFire Guide]
| {gh-samples-url}boot/findbyusername[Find by Username]
| Demonstrates how to use Spring Session to find sessions by username.
| link:guides/boot-findbyusername.html[Find by Username Guide]
| {gh-samples-url}boot/websocket[WebSockets]
| Demonstrates how to use Spring Session with WebSockets.
| link:guides/boot-websocket.html[WebSockets Guide]
| {gh-samples-url}boot/redis-json[HttpSession with Redis JSON serialization]
| Demonstrates how to use Spring Session to replace the `HttpSession` with Redis using JSON serialization.
| TBD
| {gh-samples-url}boot/gemfire[HttpSession with Spring Boot and Apache Geode]
| Demonstrates how to use _Spring Session_ to manage the `HttpSession` with Apache Geode in a _Spring Boot_ application
using a Client/Server topology.
| link:guides/boot-gemfire.html[HttpSession with Spring Boot and Apache Geode Guide]
|===
@@ -57,13 +47,13 @@ If you are looking to get started with Spring Session, the best place to start i
|===
| Source | Description | Guide
| {gh-samples-url}javaconfig/gemfire-clientserver[HttpSession with GemFire (Client/Server)]
| Demonstrates how to use Spring Session to replace the `HttpSession` with GemFire using a Client/Server topology.
| link:guides/java-gemfire-clientserver.html[HttpSession with GemFire (Client/Server) Guide]
| {gh-samples-url}javaconfig/gemfire-clientserver[HttpSession with Apache Geode (Client/Server)]
| Demonstrates how to use _Spring Session_ to manage the `HttpSession` with Apache Geode using a Client/Server topology.
| link:guides/java-gemfire-clientserver.html[HttpSession with Apache Geode (Client/Server) Guide]
| {gh-samples-url}javaconfig/gemfire-p2p[HttpSession with GemFire (P2P)]
| Demonstrates how to use Spring Session to replace the `HttpSession` with GemFire using a P2P topology.
| link:guides/java-gemfire-p2p.html[HttpSession with GemFire (P2P) Guide]
| {gh-samples-url}javaconfig/gemfire-p2p[HttpSession with Apache Geode (P2P)]
| Demonstrates how to use _Spring Session_ to manage the `HttpSession` with Apache Geode using a P2P topology.
| link:guides/java-gemfire-p2p.html[HttpSession with Apache Geode (P2P) Guide]
|===
@@ -71,66 +61,67 @@ If you are looking to get started with Spring Session, the best place to start i
|===
| Source | Description | Guide
| {gh-samples-url}xml/gemfire-clientserver[HttpSession with GemFire (Client/Server)]
| Demonstrates how to use Spring Session to replace the `HttpSession` with GemFire using a Client/Server topology.
| link:guides/xml-gemfire-clientserver.html[HttpSession with GemFire (Client/Server) Guide]
| {gh-samples-url}xml/gemfire-clientserver[HttpSession with Apache Geode (Client/Server)]
| Demonstrates how to use _Spring Session_ to manage the `HttpSession` with Apache Geode using a Client/Server topology.
| link:guides/xml-gemfire-clientserver.html[HttpSession with Apache Geode (Client/Server) Guide]
| {gh-samples-url}xml/gemfire-p2p[HttpSession with GemFire (P2P)]
| Demonstrates how to use Spring Session to replace the `HttpSession` with GemFire using a P2P topology.
| link:guides/xml-gemfire-p2p.html[HttpSession with GemFire (P2P) Guide]
| {gh-samples-url}xml/gemfire-p2p[HttpSession with Apache Geode (P2P)]
| Demonstrates how to use _Spring Session_ to manage the `HttpSession` with Apache Geode using a P2P topology.
| link:guides/xml-gemfire-p2p.html[HttpSession with Apache Geode (P2P) Guide]
|===
[[httpsession]]
== HttpSession Integration
_Spring Session_ provides transparent integration with `HttpSession`. This means that developers
can switch the `HttpSession` implementation out with an implementation that is backed by _Spring Session_.
_Spring Session_ provides transparent integration with `HttpSession`. This means that developers can switch
the `javax.servlet.http.HttpSession` implementation out with an implementation that is backed by _Spring Session_.
[[httpsession-why]]
=== Why Spring Session & HttpSession?
We have already mentioned that _Spring Session_ provides transparent integration with `HttpSession`,
but what benefits do we get out of this?
We already mentioned that _Spring Session_ provides transparent integration with `HttpSession`, but what benefits
do we get out of this?
* **Clustered Sessions** - _Spring Session_ makes it trivial to support <<httpsession-gemfire,clustered sessions>>
without being tied to an application container specific solution.
* **Multiple Browser Sessions** - _Spring Session_ supports <<httpsession-multi,managing multiple users' sessions>>
in a single browser instance (i.e. multiple authenticated accounts similar to Google).
* **RESTful APIs** - _Spring Session_ allows providing session ids in headers to work
with <<httpsession-rest,RESTful APIs>>
* **Multiple Browser Sessions** - _Spring Session_ supports _multiple user sessions_ in a single browser instance
(i.e. multiple authenticated accounts similar to Google).
* **RESTful APIs** - _Spring Session_ allows providing the session ID in headers to work with REST APIs.
* **WebSocket** - provides the ability to keep the `javax.servlet.http.HttpSession` alive
when receiving `WebSocket` messages
[[httpsession-gemfire]]
=== HttpSession with Pivotal GemFire
=== HttpSession with Apache Geode
When https://pivotal.io/big-data/pivotal-gemfire[Pivotal GemFire] is used with _Spring Session_, a web application's
`HttpSession` can be replaced with a **clustered** implementation managed by _Pivotal GemFire_ and conveniently
accessed with _Spring Session's_ API.
When http://geode.apache.org/[Apache Geode] is used with _Spring Session_, a web application's
`javax.servlet.http.HttpSession` can be replaced with a **clustered** implementation managed by _Apache Geode_
and conveniently accessed using _Spring Session's_ API.
The two most common topologies to manage _Spring Sessions_ using _Pivotal GemFire_ include:
The two most common topologies to manage _Spring Sessions_ using _Apache Geode_ include:
* <<httpsession-gemfire-clientserver,Client-Server>>
* <<httpsession-gemfire-p2p,Peer-To-Peer (P2P)>>
Additionally, _Pivotal GemFire_ supports site-to-site replication using
http://gemfire.docs.pivotal.io/docs-gemfire/topologies_and_comm/multi_site_configuration/chapter_overview.html[WAN functionality].
The ability to configure and use _Pivotal GemFire's_ WAN support is independent of _Spring Session_,
and is beyond the scope of this document.
Additionally, _Apache Geode_ supports site-to-site replication using
http://geode.apache.org/docs/guide/12/topologies_and_comm/multi_site_configuration/chapter_overview.html[WAN technology].
The ability to configure and use _Apache Geode's_ WAN support is independent of _Spring Session_,
and beyond the scope of this document.
More details on _Pivotal GemFire_ WAN functionality can be found
More details on configuring _Apache Geode_ WAN functionality using _Spring Data Geode_ can be found
http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/#bootstrap:gateway[here].
[[httpsession-gemfire-clientserver]]
==== Pivotal GemFire Client-Server
==== Apache Geode Client-Server
The http://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html[Client-Server]
topology will probably be the more common configuration preference for users when using GemFire as a provider in
Spring Session since a GemFire server will have significantly different and unique JVM heap requirements when compared
to the application. Using a client-server topology enables an application to manage (e.g. replicate) application state
The http://geode.apache.org/docs/guide/12/topologies_and_comm/cs_configuration/chapter_overview.html[Client-Server]
topology will probably be the more common configuration choice among users when using Apache Geode as a provider in
_Spring Session_ since a Geode server will have significantly different and unique JVM heap requirements as compared
to the application. Using a Client-Server topology enables an application to manage (e.g. replicate) application state
independently from other application processes.
In a client-server topology, an application using Spring Session will open a client cache connection to a (remote)
GemFire server cluster to manage and provide consistent access to all `HttpSession` state.
In a Client-Server topology, an application using _Spring Session_ will open 1 or more connections to a remote cluster
of Geode servers that will manage access to all `HttpSession` state.
You can configure a Client-Server topology with either:
@@ -138,46 +129,47 @@ You can configure a Client-Server topology with either:
* <<httpsession-gemfire-clientserver-xml,XML-based Configuration>>
[[httpsession-gemfire-clientserver-java]]
===== Pivotal GemFire Client-Server Java-based Configuration
===== Apache Geode Client-Server Java-based Configuration
This section describes how to use GemFire's Client-Server topology to back an `HttpSession` with Java-based configuration.
This section describes how to configure Apache Geode's Client-Server topology with Java-based configuration.
NOTE: The <<samples,HttpSession with GemFire (Client-Server) Sample>> provides a working sample on how to integrate
Spring Session and GemFire to replace the HttpSession using Java configuration. You can read the basic steps for
integration below, but you are encouraged to follow along with the detailed HttpSession with GemFire (Client-Server)
Guide when integrating with your own application.
NOTE: The <<samples,HttpSession with Apache Geode (Client-Server)>> provides a working sample demonstrating how to
integrate _Spring Session_ with Apache Geode to manage the `HttpSession` using Java configuration. You can read
through the basic steps of integration below, but you are encouraged to follow along in the detailed _`HttpSession`
with Apache Geode (Client-Server) Guide_ when integrating with your own application.
include::guides/java-gemfire-clientserver.adoc[tags=config,leveloffset=+3]
[[http-session-gemfire-clientserver-xml]]
===== Pivotal GemFire Client-Server XML-based Configuration
===== Apache Geode Client-Server XML-based Configuration
This section describes how to use GemFire's Client-Server topology to back an `HttpSession` with XML-based configuration.
This section describes how to use Apache Geode's Client-Server topology to back an `HttpSession`
with XML-based configuration.
NOTE: The <<samples,HttpSession with GemFire (Client-Server) using XML Sample>> provides a working sample on how to
integrate Spring Session and GemFire to replace the `HttpSession` using XML configuration. You can read the basic steps
for integration below, but you are encouraged to follow along with the detailed HttpSession with GemFire (Client-Server)
using XML Guide when integrating with your own application.
NOTE: The <<samples,HttpSession with Apache Geode (Client-Server) using XML>> provides a working sample demonstrating
how to integrate _Spring Session_ with Apache Geode to manage the `HttpSession` using XML configuration. You can read
through the basic steps of integration below, but you are encouraged to follow along in the detailed _`HttpSession`
with Apache Geode (Client-Server) using XML Guide_ when integrating with your own application.
include::guides/xml-gemfire-clientserver.adoc[tags=config,leveloffset=+3]
[[httpsession-gemfire-p2p]]
==== Pivotal GemFire Peer-To-Peer (P2P)
==== Apache Geode Peer-To-Peer (P2P)
Perhaps less common would be to configure the Spring Session application as a peer member in the GemFire cluster using
the http://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/p2p_configuration/chapter_overview.html[Peer-To-Peer (P2P)] topology.
In this configuration, a Spring Session application would be an actual data node (server) in the GemFire cluster,
Perhaps a less common approach is to configure the _Spring Session_ application as a peer member in the Geode cluster
using the http://geode.apache.org/docs/guide/12/topologies_and_comm/p2p_configuration/chapter_overview.html[Peer-To-Peer (P2P)] topology.
In this configuration, the _Spring Session_ application would be an actual server (data node) in the Geode cluster,
and **not** a cache client as before.
One advantage to this approach is the proximity of the application to the application's state (i.e. it's data). However,
there are other effective means of accomplishing similar data dependent computations, such as using GemFire's
http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/function_exec/chapter_overview.html[Function Execution].
Any of GemFire's other http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/product_intro.html[features]
can be used when GemFire is serving as a provider in Spring Session.
One advantage to this approach is the proximity of the application to the application's state (i.e. its data). However,
there are other effective means of accomplishing similar data dependent computations, such as using Geode's
http://geode.apache.org/docs/guide/12/developing/function_exec/chapter_overview.html[Function Execution].
Any of Geode's other http://geode.apache.org/docs/guide/12/getting_started/product_intro.html[features] can be used
when Geode is serving as a provider in _Spring Session_.
P2P is very useful for both testing purposes as well as smaller, more focused and self-contained applications,
such as those found in a microservices architecture, and will most certainly improve on your application's latency,
throughput and consistency needs.
P2P is very useful for testing purposes as well as for smaller, more focused and self-contained applications,
such as those found in a microservices architecture, and will most certainly improve on your application's perceived
latency, throughput and consistency needs.
You can configure a Peer-To-Peer (P2P) topology with either:
@@ -185,39 +177,44 @@ You can configure a Peer-To-Peer (P2P) topology with either:
* <<httpsession-gemfire-p2p-xml,XML-based Configuration>>
[[httpsession-gemfire-p2p-java]]
===== Pivotal GemFire Peer-To-Peer (P2P) Java-based Configuration
===== Apache Geode Peer-To-Peer (P2P) Java-based Configuration
This section describes how to use GemFire's Peer-To-Peer (P2P) topology to back an `HttpSession` using Java-based configuration.
This section describes how to configure Apache Geode's Peer-To-Peer (P2P) topology to manage an `HttpSession`
using Java-based configuration.
NOTE: The <<samples, HttpSession with GemFire (P2P) Sample>> provides a working sample on how to integrate
Spring Session and GemFire to replace the `HttpSession` using Java configuration. You can read the basic steps
for integration below, but you are encouraged to follow along with the detailed HttpSession with GemFire (P2P) Guide
when integrating with your own application.
NOTE: The <<samples, HttpSession with Apache Geode (P2P)>> provides a working sample demonstrating how to
integrate _Spring Session_ with Apache Geode to manage the `HttpSession` using Java configuration. You can read
through the basic steps of integration below, but you are encouraged to follow along in the detailed _`HttpSession`
with Apache Geode (P2P) Guide_ when integrating with your own application.
include::guides/java-gemfire-p2p.adoc[tags=config,leveloffset=+3]
[[httpsession-gemfire-p2p-xml]]
===== Pivotal GemFire Peer-To-Peer (P2P) XML-based Configuration
===== Apache Geode Peer-To-Peer (P2P) XML-based Configuration
This section describes how to use GemFire's Peer-To-Peer (P2P) topology to back an `HttpSession` using XML-based configuration.
This section describes how to use Apache Geode's Peer-To-Peer (P2P) topology to back an `HttpSession`
using XML-based configuration.
NOTE: The <<samples, HttpSession with GemFire (P2P) using XML Sample>> provides a working sample on how to integrate
Spring Session and GemFire to replace the `HttpSession` using XML configuration. You can read the basic steps for
integration below, but you are encouraged to follow along with the detailed HttpSession with GemFire (P2P) using XML
Guide when integrating with your own application.
NOTE: The <<samples, HttpSession with Apache Geode (P2P) using XML>> provides a working sample demonstrating how to
integrate _Spring Session_ with Apache Geode to manage the `HttpSession` using XML configuration. You can read
through the basic steps of integration below, but you are encouraged to follow along in the detailed _`HttpSession`
with Apache Geode (P2P) using XML Guide_ when integrating with your own application.
include::guides/xml-gemfire-p2p.adoc[tags=config,leveloffset=+3]
[[httpsession-how]]
=== How HttpSession Integration Works
Fortunately both `HttpSession` and `HttpServletRequest` (the API for obtaining an `HttpSession`) are both interfaces.
This means that we can provide our own implementations for each of these APIs.
Fortunately both `javax.servlet.http.HttpSession` and `javax.servlet.http.HttpServletRequest` (the API for
obtaining an `HttpSession`) are both interfaces. This means that we can provide our own implementations
for each of these APIs.
NOTE: This section describes how Spring Session provides transparent integration with `HttpSession`. The intent is so that user's can understand what is happening under the covers. This functionality is already integrated and you do NOT need to implement this logic yourself.
NOTE: This section describes how _Spring Session_ provides transparent integration with `javax.servlet.http.HttpSession`.
The intent is so users understand what is happening under the hood. This functionality is already integrated
and you do NOT need to implement this logic yourself.
First we create a custom `HttpServletRequest` that returns a custom implementation of `HttpSession`.
It looks something like the following:
First, we create a custom `javax.servlet.http.HttpServletRequest` that returns a custom implementation of
`javax.servlet.http.HttpSession`. It looks something like the following:
[source, java]
----
@@ -239,10 +236,11 @@ public class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {
}
----
Any method that returns an `HttpSession` is overridden.
All other methods are implemented by `HttpServletRequestWrapper` and simply delegate to the original `HttpServletRequest` implementation.
Any method that returns an `javax.servlet.http.HttpSession` is overridden. All other methods are implemented by
`javax.servlet.http.HttpServletRequestWrapper` and simply delegate to the original `javax.servlet.http.HttpServletRequest`
implementation.
We replace the `HttpServletRequest` implementation using a servlet `Filter` called `SessionRepositoryFilter`.
We replace the `javax.servlet.http.HttpServletRequest` implementation using a Servlet `Filter` called `SessionRepositoryFilter`.
The pseudocode can be found below:
[source, java]
@@ -250,9 +248,10 @@ The pseudocode can be found below:
public class SessionRepositoryFilter implements Filter {
public doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
SessionRepositoryRequestWrapper customRequest =
new SessionRepositoryRequestWrapper(httpRequest);
SessionRepositoryRequestWrapper customRequest = new SessionRepositoryRequestWrapper(httpRequest);
chain.doFilter(customRequest, response, chain);
}
@@ -261,87 +260,107 @@ public class SessionRepositoryFilter implements Filter {
}
----
By passing in a custom `HttpServletRequest` implementation into the `FilterChain` we ensure that anything invoked after our `Filter` uses the custom `HttpSession` implementation.
This highlights why it is important that Spring Session's `SessionRepositoryFilter` must be placed before anything that interacts with the `HttpSession`.
By passing in a custom `javax.servlet.http.HttpServletRequest` implementation into the `FilterChain` we ensure that
anything invoked after our `Filter` uses the custom `javax.servlet.http.HttpSession` implementation.
This highlights why it is important that _Spring Session's_ `SessionRepositoryFilter` must be placed before anything
that interacts with the `javax.servlet.http.HttpSession`.
[[httpsession-httpsessionlistener]]
=== HttpSessionListener
Spring Session supports `HttpSessionListener` by translating `SessionDestroyedEvent` and `SessionCreatedEvent` into `HttpSessionEvent` by declaring `SessionEventHttpSessionListenerAdapter`.
_Spring Session_ supports `HttpSessionListener` by translating `SessionDestroyedEvent` and `SessionCreatedEvent` into
`HttpSessionEvent` by declaring `SessionEventHttpSessionListenerAdapter`.
To use this support, you need to:
* Ensure your `SessionRepository` implementation supports and is configured to fire `SessionDestroyedEvent` and `SessionCreatedEvent`.
* Configure `SessionEventHttpSessionListenerAdapter` as a Spring bean.
* Configure `SessionEventHttpSessionListenerAdapter` as a _Spring_ bean.
* Inject every `HttpSessionListener` into the `SessionEventHttpSessionListenerAdapter`
If you are using the configuration support documented in <<httpsession-redis,HttpSession with Redis>>, then all you need to do is register every `HttpSessionListener` as a bean.
For example, assume you want to support Spring Security's concurrency control and need to use `HttpSessionEventPublisher` you can simply add `HttpSessionEventPublisher` as a bean.
If you are using the configuration support documented in <<httpsession-gemfire,HttpSession with Apache Geode>>,
then all you need to do is register every `HttpSessionListener` as a bean.
For example, assume you want to support _Spring Security's_ concurrency control and need to use `HttpSessionEventPublisher`
you can simply add `HttpSessionEventPublisher` as a bean.
[[api-session]]
=== Session
A `Session` is a simplified `Map` of key value pairs.
[[api-expiringsession]]
=== ExpiringSession
An `ExpiringSession` extends a `Session` by providing attributes related to the `Session` instance's expiration.
If there is no need to interact with the expiration information, prefer using the more simple `Session` API.
A `Session` is a simplified `Map` of key/value pairs with support for expiration.
[[api-sessionrepository]]
=== SessionRepository
A `SessionRepository` is in charge of creating, retrieving, and persisting `Session` instances.
If possible, developers should not interact directly with a `SessionRepository` or a `Session`.
Instead, developers should prefer interacting with `SessionRepository` and `Session` indirectly through the <<httpsession,HttpSession>> and <<websocket,WebSocket>> integration.
If possible, developers should not interact directly with a `SessionRepository` or a `Session`. Instead, developers
should prefer to interact with `SessionRepository` and `Session` indirectly through the `javax.servlet.http.HttpSession`
and `WebSocket` integration.
[[api-findbyindexnamesessionrepository]]
=== FindByIndexNameSessionRepository
Spring Session's most basic API for using a `Session` is the `SessionRepository`.
This API is intentionally very simple, so that it is easy to provide additional implementations with basic functionality.
_Spring Session's_ most basic API for using a `Session` is the `SessionRepository`. The API is intentionally
very simple so that it is easy to provide additional implementations with basic functionality.
Some `SessionRepository` implementations may choose to implement `FindByIndexNameSessionRepository` also.
For example, Spring's Redis support implements `FindByIndexNameSessionRepository`.
For example, _Spring Session's Apache Geode_ support implements `FindByIndexNameSessionRepository`.
The `FindByIndexNameSessionRepository` adds a single method to look up all the sessions for a particular user.
This is done by ensuring that the session attribute with the name `FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME` is populated with the username.
It is the responsibility of the developer to ensure the attribute is populated since Spring Session is not aware of the authentication mechanism being used.
The `FindByIndexNameSessionRepository` provides a single method to look up all the `Sessions` for a particular user.
This is done by ensuring that the session attribute with the name `FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME`
is populated with the username. It is the responsibility of the developer to ensure the attribute is populated
since _Spring Session_ is not aware of the authentication mechanism being used.
[NOTE]
====
Some implementations of `FindByIndexNameSessionRepository` will provide hooks to automatically index other session attributes.
For example, many implementations will automatically ensure the current Spring Security user name is indexed with the index name `FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME`.
For example, many implementations will automatically ensure the current _Spring Security_ user name is indexed with
the index name `FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME`.
====
[[api-enablespringhttpsession]]
=== EnableSpringHttpSession
The `@EnableSpringHttpSession` annotation can be added to an `@Configuration` class to expose the `SessionRepositoryFilter` as a bean named "springSessionRepositoryFilter".
The `@EnableSpringHttpSession` annotation can be added to any `@Configuration` class to expose the `SessionRepositoryFilter`
as a bean in the _Spring_ application context named "springSessionRepositoryFilter".
In order to leverage the annotation, a single `SessionRepository` bean must be provided.
It is important to note that no infrastructure for session expirations is configured for you out of the box.
This is because things like session expiration are highly implementation dependent.
This means if you require cleaning up expired sessions, you are responsible for cleaning up the expired sessions.
[[api-enablegemfirehttpsession]]
=== EnableGemFireHttpSession
The `@EnableGemFireHttpSession` annotation can be added to any `@Configuration` class in place of
the `@EnableSpringHttpSession` annotation to expose the `SessionRepositoryFilter` as a bean
in the _Spring_ application context named "springSessionRepositoryFilter" and to position Apache Geode as a provider
to manage the `javax.servlet.http.HttpSession`.
When using the `@EnableGemFireHttpSession` annotation, additional configuration is imported out-of-the-box
that also provides a Geode specific implementation of the `SessionRepository` interface, the `GemFireOperationsSessionRepository`.
[[api-gemfireoperationssessionrepository]]
=== GemFireOperationsSessionRepository
`GemFireOperationsSessionRepository` is a `SessionRepository` that is implemented using Spring Data's `GemFireOperationsSessionRepository`.
In a web environment, this is typically used in combination with `SessionRepositoryFilter`.
The implementation supports `SessionDestroyedEvent` and `SessionCreatedEvent` through `SessionMessageListener`.
`GemFireOperationsSessionRepository` is a `SessionRepository` implementation that is implemented using _Spring Session Data Geode's_
`GemFireOperationsSessionRepository`.
In a web environment, this repository is used in conjunction with the `SessionRepositoryFilter`.
This implementation supports `SessionCreatedEvents`, `SessionDeletedEvents` and `SessionDestroyedEvents`
through `SessionEventHttpSessionListenerAdapter`.
[[api-gemfireoperationssessionrepository-indexing]]
==== Using Indexes with GemFire
==== Using Indexes with Apache Geode
While best practices concerning the proper definition of indexes that positively impact GemFire's performance is beyond
the scope of this document, it is important to realize that Spring Session Data GemFire creates and uses indexes to
While best practices concerning the proper definition of Indexes that positively impact Geode's performance is beyond
the scope of this document, it is important to realize that _Spring Session Data Geode_ creates and uses Indexes to
query and find Sessions efficiently.
Out-of-the-box, Spring Session Data GemFire creates 1 Hash-typed Index on the principal name. There are two different buit in
strategies for finding the principal name. The first strategy is that the value of the session attribute with the name
`FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME` will be indexed to the same index name. For example:
Out-of-the-box, _Spring Session Data Geode_ creates 1 Hash-typed Index on the principal name. There are two different
built-in strategies for finding the principal name. The first strategy is that the value of the Session attribute
with the name `FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME` will be Indexed to the same index name.
For example:
[source,java,indent=0]
----
@@ -350,11 +369,12 @@ include::{docs-itest-dir}docs/gemfire/indexing/HttpSessionGemFireIndexingIntegra
----
[[api-gemfireoperationssessionrepository-indexing-security]]
==== Using Indexes with GemFire & Spring Security
==== Using Indexes with Apache Geode & Spring Security
Alternatively, Spring Session Data GemFire will map Spring Security's current `Authentication#getName()` to the index
`FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME`. For example, if you are using Spring Security you can
find the current user's sessions using:
Alternatively, _Spring Session Data Geode_ will map _Spring Security's_ current `Authentication#getName()` to the Index
`FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME`.
For example, if you are using _Spring Security_ you can find the current user's sessions using:
[source,java,indent=0]
----
@@ -368,13 +388,13 @@ include::{docs-itest-dir}docs/gemfire/indexing/HttpSessionGemFireIndexingIntegra
This enables developers using the `GemFireOperationsSessionRepository` programmatically to query and find all Sessions
with a given principal name efficiently.
Additionally, Spring Session Data GemFire will create a Range-based Index on the implementing Session's Map-type
Additionally, _Spring Session Data Geode_ will create a Range-based Index on the implementing Session's Map-type
`attributes` property (i.e. on any arbitrary Session attribute) when a developer identifies 1 or more named Session
attributes that should be indexed by GemFire.
attributes that should be indexed by Geode.
Sessions attributes to index can be specified with the `indexableSessionAttributes` attribute on the `@EnableGemFireHttpSession`
annotation. A developer adds this annotation to their Spring application `@Configuration` class when s/he wishes to
enable Spring Session support for HttpSession backed by GemFire.
annotation. A developer adds this annotation to their _Spring_ application `@Configuration` class when s/he wishes to
enable _Spring Session's_ support for `HttpSession` backed by Apache Geode.
[source,java,indent=0]
----
@@ -406,17 +426,17 @@ Please find additional information below.
=== Support
You can get help by asking questions on http://stackoverflow.com/questions/tagged/spring-session[StackOverflow with the tag spring-session].
Similarly we encourage helping others by answering questions on StackOverflow.
Similarly we encourage helping others by answering questions on _StackOverflow_.
[[community-source]]
=== Source Code
Our source code can be found on github at https://github.com/spring-projects/spring-session/
The source code can be found on GitHub at https://github.com/spring-projects/spring-session-data-geode
[[community-issues]]
=== Issue Tracking
We track issues in github issues at https://github.com/spring-projects/spring-session/issues
We track issues in GitHub Issues at https://github.com/spring-projects/spring-session-data-geode/issues
[[community-contributing]]
=== Contributing
@@ -426,26 +446,21 @@ We appreciate https://help.github.com/articles/using-pull-requests/[Pull Request
[[community-license]]
=== License
Spring Session is Open Source software released under the http://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license].
[[community-extensions]]
=== Community Extensions
https://github.com/maseev/spring-session-orientdb[Spring Session OrientDB]
http://infinispan.org/docs/dev/user_guide/user_guide.html#externalizing_session_using_spring_session[Spring Session Infinispan]
_Spring Session Data Geode_ and _Spring Session Data GemFire_ are Open Source Software released under the
http://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license].
[[minimum-requirements]]
== Minimum Requirements
The minimum requirements for Spring Session are:
The minimum requirements for _Spring Session_ are:
* Java 5+
* If you are running in a Servlet Container (not required), Servlet 2.5+
* If you are using other Spring libraries (not required), the minimum required version is Spring 3.2.14.
While we re-run all unit tests against Spring 3.2.x, we recommend using the latest Spring 4.x version when possible.
* `@EnableRedisHttpSession` requires Redis 2.8+. This is necessary to support <<api-redisoperationssessionrepository-expiration,Session Expiration>>
* Java 8+
* If you are running in a Servlet container (not required), Servlet 2.5+
* If you are using other _Spring_ libraries (not required), the minimum required version is _Spring Framework_ 5.0.0.RC2.
* `@EnableGemFireHttpSession` requires _Spring Data Geode_ 2.0.0.RC2 and _Spring Data GemFire_ 2.0.0.RC2.
* `@EnableGemFireHttpSession` requires Apache Geode 1.2.0 or Pivotal GemFire 9.1.0.
[NOTE]
====
At its core Spring Session only has a required dependency on `spring-jcl`.
For an example of using Spring Session without any other Spring dependencies, refer to the <<samples,hazelcast sample>> application.
At its core _Spring Session_ only has a required dependency on `spring-jcl`.
====