Fixup documentation and samples.
This commit is contained in:
@@ -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/',
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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`.
|
||||
====
|
||||
|
||||
Reference in New Issue
Block a user