Compare commits
38 Commits
1.3.0.RC1
...
1.3.2.RELE
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e44cd45668 | ||
|
|
7f0de8126e | ||
|
|
d75b03f594 | ||
|
|
ca0fea3a54 | ||
|
|
92af786e6b | ||
|
|
d271a4ad1d | ||
|
|
04c1908378 | ||
|
|
f0e187fbd7 | ||
|
|
2d3001a24e | ||
|
|
f2d1badd60 | ||
|
|
6a6d60d8f8 | ||
|
|
b2cb3f6a3a | ||
|
|
d7ae5785eb | ||
|
|
96eb40439c | ||
|
|
8ed0999ad3 | ||
|
|
b2d2335d73 | ||
|
|
f597c5a824 | ||
|
|
212eca306c | ||
|
|
a64e6d1a9c | ||
|
|
598715f219 | ||
|
|
4d90fcc7a8 | ||
|
|
4f57c6c6c1 | ||
|
|
c210a4a3cf | ||
|
|
a1380d722b | ||
|
|
c029922bf4 | ||
|
|
6b55f3f7d2 | ||
|
|
6668e41b0a | ||
|
|
304e32eef5 | ||
|
|
288c622012 | ||
|
|
3827ae1e72 | ||
|
|
9067f8235d | ||
|
|
19928e6b7f | ||
|
|
1df1a76069 | ||
|
|
17e397212d | ||
|
|
39503a21a7 | ||
|
|
ebbc10b2b4 | ||
|
|
9a51cb9ca7 | ||
|
|
5e0ee5077a |
14
build.gradle
14
build.gradle
@@ -51,12 +51,14 @@ sonarqube {
|
||||
}
|
||||
}
|
||||
|
||||
task configDocsZip(dependsOn: [':docs:asciidoctor',':spring-session:javadoc']) << {
|
||||
project.tasks.docsZip.from(project(':docs').asciidoctor) {
|
||||
into('reference')
|
||||
}
|
||||
project.tasks.docsZip.from(project(':spring-session').javadoc) {
|
||||
into('api')
|
||||
task configDocsZip(dependsOn: [':docs:asciidoctor',':spring-session:javadoc']) {
|
||||
doLast {
|
||||
project.tasks.docsZip.from(project(':docs').asciidoctor) {
|
||||
into('reference')
|
||||
}
|
||||
project.tasks.docsZip.from(project(':spring-session').javadoc) {
|
||||
into('api')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ If you are using Maven, ensure to add the following dependencies:
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-redis</artifactId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
----
|
||||
|
||||
@@ -127,3 +127,6 @@ Alternatively, you can also delete the explicit key. Enter the following into yo
|
||||
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
|
||||
|
||||
Now visit the application at http://localhost:8080/test/index and observe that we are no longer authenticated.
|
||||
|
||||
NOTE: Spring Session will not work with grails flash scope without additional work. +
|
||||
See this answer for an explanation: https://stackoverflow.com/a/43311427
|
||||
|
||||
@@ -95,7 +95,7 @@ and managed by GemFire. As well, we have specified an arbitrary expiration attr
|
||||
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].
|
||||
http://gemfire.docs.pivotal.io/docs-gemfire/latest/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,
|
||||
@@ -159,7 +159,7 @@ 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*").
|
||||
* `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://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
|
||||
with a GemFire http://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/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`.
|
||||
@@ -230,7 +230,10 @@ Go ahead and view the cookies (click for help with https://developer.chrome.com/
|
||||
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].
|
||||
see http://gemfire.docs.pivotal.io/docs-gemfire/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
|
||||
|
||||
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`. For example, on a Linux-based system type the following
|
||||
at the command-line:
|
||||
|
||||
@@ -92,7 +92,7 @@ bean to replace placeholders in the Spring XML configuration meta-data with the
|
||||
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].
|
||||
http://gemfire.docs.pivotal.io/docs-gemfire/latest/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`.
|
||||
@@ -234,7 +234,7 @@ Go ahead and view the cookies (click for help with https://developer.chrome.com/
|
||||
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].
|
||||
see https://gemfire.docs.pivotal.io/gemfire/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
|
||||
|
||||
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:
|
||||
|
||||
@@ -87,12 +87,12 @@ include::{samples-dir}httpsession-gemfire-clientserver/src/main/java/sample/Clie
|
||||
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].
|
||||
using http://gemfire.docs.pivotal.io/docs-gemfire/latest/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://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/PoolFactory.html[PoolFactory API].
|
||||
http://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/PoolFactory.html[PoolFactory API].
|
||||
<56> Finally, we include a Spring `BeanPostProcessor` to block the client until our GemFire Server is up and running,
|
||||
listening for and accepting client connections.
|
||||
|
||||
@@ -100,7 +100,7 @@ The `gemfireCacheServerReadyBeanPostProcessor` is necessary in order to coordina
|
||||
an automated fashion during testing, but unnecessary in situations where the GemFire cluster is already presently
|
||||
running, such as in production.
|
||||
|
||||
The `BeanPostProcessor` uses a GemFire http://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/management/membership/ClientMembershipListener.html[ClientMembershipListener]
|
||||
The `BeanPostProcessor` uses a GemFire https://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/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.
|
||||
@@ -118,7 +118,7 @@ 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*").
|
||||
* `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://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
|
||||
with a GemFire https://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/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`.
|
||||
@@ -233,7 +233,7 @@ Go ahead and view the cookies (click for help with https://developer.chrome.com/
|
||||
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].
|
||||
see https://gemfire.docs.pivotal.io/gemfire/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
|
||||
|
||||
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:
|
||||
|
||||
@@ -176,7 +176,7 @@ Go ahead and view the cookies (click for help with https://developer.chrome.com/
|
||||
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].
|
||||
see http://gemfire.docs.pivotal.io/gemfire/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
|
||||
|
||||
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:
|
||||
|
||||
@@ -104,7 +104,7 @@ 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://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/RegionShortcut.html[RegionShortcut]
|
||||
with a GemFire https://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/RegionShortcut.html[RegionShortcut]
|
||||
(default is `PARTITION`).
|
||||
|
||||
NOTE: `clientRegionShort` is ignored in a peer cache configuration and only applies when a client-server topology,
|
||||
@@ -175,7 +175,7 @@ Go ahead and view the cookies (click for help with https://developer.chrome.com/
|
||||
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].
|
||||
see https://gemfire.docs.pivotal.io/gemfire/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
|
||||
|
||||
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:
|
||||
|
||||
@@ -23,16 +23,21 @@ Additional features include:
|
||||
|
||||
* <<websocket,WebSocket>> - provides the ability to keep the `HttpSession` alive when receiving WebSocket messages
|
||||
|
||||
== What's New in 1.2
|
||||
== What's New in 1.3
|
||||
|
||||
Below are the highlights of what is new in Spring Session 1.2. You can find a complete list of what's new in https://github.com/spring-projects/spring-session/issues?utf8=%E2%9C%93&q=milestone%3A%221.2.0+RC1%22[1.2.0 RC1] by referring to the changelog.
|
||||
Below are the highlights of what is new in Spring Session 1.3. You can find a complete list of what's new by referring to the changelogs of
|
||||
https://github.com/spring-projects/spring-session/milestone/6?closed=1[1.3.0.M1],
|
||||
https://github.com/spring-projects/spring-session/milestone/18?closed=1[1.3.0.M2],
|
||||
https://github.com/spring-projects/spring-session/milestone/16?closed=1[1.3.0.RC1], and
|
||||
https://github.com/spring-projects/spring-session/milestone/19?closed=1[1.3.0.RELEASE].
|
||||
|
||||
* First class support for http://docs.spring.io/spring-session/docs/1.3.0.RELEASE/reference/html5/#httpsession-hazelcast[Hazelcast]
|
||||
* First class support for http://docs.spring.io/spring-session/docs/1.3.0.RELEASE/reference/html5/#spring-security-concurrent-sessions-how[Spring Security's concurrent session management]
|
||||
* Added https://github.com/maseev/spring-session-orientdb[OrientDB Community Extension]
|
||||
* Added <<httpsession-jdbc,JdbcOperationsSessionRepository>> (See https://github.com/spring-projects/spring-session/issues/364[#364]).
|
||||
* Added <<httpsession-mongo,MongoOperationsSessionRepository>> (See https://github.com/spring-projects/spring-session/pull/371[#371]).
|
||||
* SessionRepositoryFilter caches null session lookup (See https://github.com/spring-projects/spring-session/issues/423[#423])
|
||||
* link:guides/grails3.html[Grails 3 Sample & Guide]
|
||||
* Improved Workspace Setup (See https://github.com/spring-projects/spring-session/pull/417[#417])
|
||||
* https://github.com/spring-projects/spring-session/tree/1.3.0.RELEASE/samples/httpsession-redis-json[GenericJackson2JsonRedisSerializer sample] with Spring Security's new Jackson Support
|
||||
* Guides now https://github.com/spring-projects/spring-session/pull/652[use Lettuce]
|
||||
* `spring.session.cleanup.cron.expression` can be used to override the cleanup task’s cron expression
|
||||
* Lots of performance improvements and bug fixes
|
||||
|
||||
[[samples]]
|
||||
== Samples and Guides (Start Here)
|
||||
@@ -187,7 +192,7 @@ The two most common topologies to manage Spring Sessions using GemFire include:
|
||||
* <<httpsession-gemfire-clientserver,Client-Server>>
|
||||
* <<httpsession-gemfire-p2p,Peer-To-Peer (P2P)>>
|
||||
|
||||
Additionally, 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].
|
||||
Additionally, GemFire supports site-to-site replication using http://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/multi_site_configuration/chapter_overview.html[WAN functionality].
|
||||
The ability to configure and use GemFire's WAN support is independent of Spring Session, and is beyond the scope
|
||||
of this document. More details on GemFire WAN functionality can be found http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/#bootstrap:gateway[here].
|
||||
|
||||
@@ -824,12 +829,12 @@ EXPIRE spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe 1800
|
||||
|
||||
When a session expires key is deleted or expires, the keyspace notification triggers a lookup of the actual session and a SessionDestroyedEvent is fired.
|
||||
|
||||
One problem with relying on Redis expiration exclusively is that Redis makes no guarantee of when the expired event will be fired if they key has not been accessed.
|
||||
One problem with relying on Redis expiration exclusively is that Redis makes no guarantee of when the expired event will be fired if the key has not been accessed.
|
||||
Specifically the background task that Redis uses to clean up expired keys is a low priority task and may not trigger the key expiration.
|
||||
For additional details see http://redis.io/topics/notifications[Timing of expired events] section in the Redis documentation.
|
||||
|
||||
To circumvent the fact that expired events are not guaranteed to happen we can ensure that each key is accessed when it is expected to expire.
|
||||
This means that if the TTL is expired on the key, Redis will remove the key and fire the expired event when we try to access they key.
|
||||
This means that if the TTL is expired on the key, Redis will remove the key and fire the expired event when we try to access the key.
|
||||
|
||||
For this reason, each session expiration is also tracked to the nearest minute.
|
||||
This allows a background task to access the potentially expired sessions to ensure that Redis expired events are fired in a more deterministic fashion.
|
||||
@@ -841,7 +846,7 @@ EXPIRE spring:session:expirations1439245080000 2100
|
||||
----
|
||||
|
||||
The background task will then use these mappings to explicitly request each key.
|
||||
By accessing they key, rather than deleting it, we ensure that Redis deletes the key for us only if the TTL is expired.
|
||||
By accessing the key, rather than deleting it, we ensure that Redis deletes the key for us only if the TTL is expired.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
@@ -1194,7 +1199,17 @@ Spring Session is Open Source software released under the http://www.apache.org/
|
||||
|
||||
[[community-extensions]]
|
||||
=== Community Extensions
|
||||
https://github.com/maseev/spring-session-orientdb[Spring Session OrientDB]
|
||||
|
||||
|===
|
||||
| Name | Location
|
||||
|
||||
| Spring Session OrientDB
|
||||
| https://github.com/maseev/spring-session-orientdb
|
||||
|
||||
| Spring Session Infinispan
|
||||
| http://infinispan.org/docs/dev/user_guide/user_guide.html#externalizing_session_using_spring_session
|
||||
|
||||
|===
|
||||
|
||||
[[minimum-requirements]]
|
||||
== Minimum Requirements
|
||||
|
||||
@@ -4,25 +4,26 @@ jacksonVersion=2.6.5
|
||||
jspApiVersion=2.0
|
||||
servletApiVersion=3.0.1
|
||||
jstlelVersion=1.2.5
|
||||
version=1.3.0.RC1
|
||||
springDataRedisVersion=1.7.1.RELEASE
|
||||
version=1.3.2.RELEASE
|
||||
springDataRedisVersion=1.7.10.RELEASE
|
||||
html5ShivVersion=3.7.3
|
||||
commonsLoggingVersion=1.2
|
||||
junitVersion=4.12
|
||||
springDataRedisSpring3Version=1.7.1.RELEASE
|
||||
lettuceVersion=3.5.0.Final
|
||||
gebVersion=0.13.1
|
||||
mockitoVersion=1.10.19
|
||||
hazelcastVersion=3.6.5
|
||||
seleniumVersion=2.52.0
|
||||
springDataGeodeVersion=1.0.0.APACHE-GEODE-INCUBATING-M2
|
||||
springDataGeodeVersion=1.0.0.INCUBATING-RELEASE
|
||||
springSecurityVersion=4.2.0.RELEASE
|
||||
springVersion=4.3.4.RELEASE
|
||||
httpClientVersion=4.5.1
|
||||
jedisVersion=2.8.1
|
||||
h2Version=1.4.192
|
||||
jedisVersion=2.8.1
|
||||
springDataMongoVersion=1.9.4.RELEASE
|
||||
springShellVersion=1.1.0.RELEASE
|
||||
springDataGemFireVersion=1.8.5.RELEASE
|
||||
springDataGemFireVersion=1.8.10.RELEASE
|
||||
assertjVersion=2.5.0
|
||||
spockVersion=1.0-groovy-2.4
|
||||
webjarsTaglibVersion=0.3
|
||||
|
||||
@@ -9,6 +9,9 @@ configurations.spring3TestRuntime {
|
||||
&& details.requested.name != 'spring-messaging') {
|
||||
details.useVersion '3.2.14.RELEASE'
|
||||
}
|
||||
if (details.requested.name == 'spring-data-redis') {
|
||||
details.useVersion springDataRedisSpring3Version
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
#Fri Nov 11 19:46:57 CET 2016
|
||||
#Mon Jan 29 18:35:20 CET 2018
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5.1-bin.zip
|
||||
|
||||
19
gradlew
vendored
19
gradlew
vendored
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
@@ -154,16 +154,19 @@ if $cygwin ; then
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
# Escape application args
|
||||
save ( ) {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
exec "$JAVACMD" "$@"
|
||||
|
||||
@@ -16,7 +16,7 @@ group = 'samples'
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-session'),
|
||||
"org.springframework.boot:spring-boot-starter-redis",
|
||||
"org.springframework.boot:spring-boot-starter-data-redis",
|
||||
"org.springframework.boot:spring-boot-starter-web",
|
||||
"org.springframework.boot:spring-boot-starter-thymeleaf",
|
||||
"org.springframework.boot:spring-boot-starter-security",
|
||||
|
||||
@@ -16,7 +16,7 @@ group = 'samples'
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-session'),
|
||||
"org.springframework.boot:spring-boot-starter-redis",
|
||||
"org.springframework.boot:spring-boot-starter-data-redis",
|
||||
"org.springframework.boot:spring-boot-starter-web",
|
||||
"org.springframework.boot:spring-boot-starter-security",
|
||||
"org.springframework.boot:spring-boot-starter-thymeleaf",
|
||||
|
||||
@@ -10,12 +10,7 @@ buildscript {
|
||||
apply from: JAVA_GRADLE
|
||||
apply plugin: "application"
|
||||
apply plugin: 'org.springframework.boot'
|
||||
|
||||
tasks.findByPath("artifactoryPublish")?.enabled = false
|
||||
|
||||
sonarqube {
|
||||
skipProject = true
|
||||
}
|
||||
apply from: SAMPLE_GRADLE
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-session-data-gemfire'),
|
||||
@@ -44,24 +39,26 @@ springBoot {
|
||||
mainClass = 'sample.client.Application'
|
||||
}
|
||||
|
||||
task runGemFireServer() << {
|
||||
println 'STARTING GEMFIRE SERVER...'
|
||||
task runGemFireServer() {
|
||||
doLast {
|
||||
println 'STARTING GEMFIRE SERVER...'
|
||||
|
||||
ext.port = reservePort()
|
||||
ext.port = reservePort()
|
||||
|
||||
String classpath = sourceSets.main.runtimeClasspath.collect { it }.join(File.pathSeparator)
|
||||
String classpath = sourceSets.main.runtimeClasspath.collect { it }.join(File.pathSeparator)
|
||||
|
||||
String[] commandLine = ['java', '-server', '-ea', '-classpath', classpath,
|
||||
"-Dgemfire.cache.server.port=$port",
|
||||
"-Dgemfire.log-level=" + System.getProperty('gemfire.log.level', 'warning'),
|
||||
'sample.server.GemFireServer']
|
||||
String[] commandLine = ['java', '-server', '-ea', '-classpath', classpath,
|
||||
"-Dgemfire.cache.server.port=$port",
|
||||
"-Dgemfire.log-level=" + System.getProperty('gemfire.log.level', 'warning'),
|
||||
'sample.server.GemFireServer']
|
||||
|
||||
//println commandLine
|
||||
//println commandLine
|
||||
|
||||
ext.process = commandLine.execute()
|
||||
process.in.close()
|
||||
process.out.close()
|
||||
process.err.close()
|
||||
ext.process = commandLine.execute()
|
||||
process.in.close()
|
||||
process.out.close()
|
||||
process.err.close()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
@Controller
|
||||
public class Application {
|
||||
|
||||
static final long DEFAULT_WAIT_DURATION = TimeUnit.SECONDS.toMillis(20);
|
||||
static final long DEFAULT_WAIT_DURATION = TimeUnit.SECONDS.toMillis(60);
|
||||
|
||||
static final CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
@@ -127,7 +127,7 @@ public class Application {
|
||||
|
||||
gemfirePool.setKeepAlive(false);
|
||||
gemfirePool.setPingInterval(TimeUnit.SECONDS.toMillis(5));
|
||||
gemfirePool.setReadTimeout(Long.valueOf(TimeUnit.SECONDS.toMillis(2)).intValue());
|
||||
gemfirePool.setReadTimeout(Long.valueOf(TimeUnit.SECONDS.toMillis(15)).intValue());
|
||||
gemfirePool.setRetryAttempts(1);
|
||||
gemfirePool.setSubscriptionEnabled(true);
|
||||
gemfirePool.setThreadLocalConnections(false);
|
||||
|
||||
@@ -66,15 +66,14 @@ public class GemFireServer {
|
||||
gemfireProperties.setProperty("name", applicationName());
|
||||
gemfireProperties.setProperty("mcast-port", "0");
|
||||
gemfireProperties.setProperty("log-level", logLevel());
|
||||
gemfireProperties.setProperty("jmx-manager", "true");
|
||||
gemfireProperties.setProperty("jmx-manager-start", "true");
|
||||
//gemfireProperties.setProperty("jmx-manager", "true");
|
||||
//gemfireProperties.setProperty("jmx-manager-start", "true");
|
||||
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
String applicationName() {
|
||||
return "samples:httpsession-gemfire-boot:"
|
||||
.concat(getClass().getSimpleName());
|
||||
return "samples:httpsession-gemfire-boot:".concat(getClass().getSimpleName());
|
||||
}
|
||||
|
||||
String logLevel() {
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
apply from: JAVA_GRADLE
|
||||
apply from: TOMCAT_7_GRADLE
|
||||
apply plugin: "application"
|
||||
|
||||
tasks.findByPath("artifactoryPublish")?.enabled = false
|
||||
|
||||
sonarqube {
|
||||
skipProject = true
|
||||
}
|
||||
apply from: SAMPLE_GRADLE
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-session-data-gemfire'),
|
||||
@@ -31,29 +26,33 @@ mainClassName = 'sample.Application'
|
||||
def port
|
||||
def process
|
||||
|
||||
task availablePort() << {
|
||||
def serverSocket = new ServerSocket(0)
|
||||
port = serverSocket.localPort
|
||||
serverSocket.close()
|
||||
task availablePort() {
|
||||
doLast {
|
||||
def serverSocket = new ServerSocket(0)
|
||||
port = serverSocket.localPort
|
||||
serverSocket.close()
|
||||
}
|
||||
}
|
||||
|
||||
task runGemFireServer(dependsOn: availablePort) << {
|
||||
println 'STARTING GEMFIRE SERVER...'
|
||||
task runGemFireServer(dependsOn: availablePort) {
|
||||
doLast {
|
||||
println 'STARTING GEMFIRE SERVER...'
|
||||
|
||||
String classpath = sourceSets.main.runtimeClasspath.collect { it }.join(File.pathSeparator)
|
||||
String classpath = sourceSets.main.runtimeClasspath.collect { it }.join(File.pathSeparator)
|
||||
|
||||
String[] commandLine = ['java', '-server', '-ea',
|
||||
"-Dspring.session.data.gemfire.port=$port",
|
||||
"-Dsample.httpsession.gemfire.log-level="
|
||||
+ System.getProperty('sample.httpsession.gemfire.log-level', 'warning'),
|
||||
'-classpath', classpath, 'sample.Application' ]
|
||||
String[] commandLine = ['java', '-server', '-ea',
|
||||
"-Dspring.session.data.gemfire.port=$port",
|
||||
"-Dsample.httpsession.gemfire.log-level="
|
||||
+ System.getProperty('sample.httpsession.gemfire.log-level', 'warning'),
|
||||
'-classpath', classpath, 'sample.Application']
|
||||
|
||||
//println commandLine
|
||||
//println commandLine
|
||||
|
||||
process = commandLine.execute()
|
||||
process.in.close()
|
||||
process.out.close()
|
||||
process.err.close()
|
||||
process = commandLine.execute()
|
||||
process.in.close()
|
||||
process.out.close()
|
||||
process.err.close()
|
||||
}
|
||||
}
|
||||
|
||||
integrationTest.doLast {
|
||||
|
||||
@@ -27,29 +27,33 @@ def process
|
||||
|
||||
mainClassName = "sample.ServerConfig"
|
||||
|
||||
task availablePort() << {
|
||||
def serverSocket = new ServerSocket(0)
|
||||
port = serverSocket.localPort
|
||||
serverSocket.close()
|
||||
task availablePort() {
|
||||
doLast {
|
||||
def serverSocket = new ServerSocket(0)
|
||||
port = serverSocket.localPort
|
||||
serverSocket.close()
|
||||
}
|
||||
}
|
||||
|
||||
task runGemFireServer(dependsOn: availablePort) << {
|
||||
println 'STARTING GEMFIRE SERVER...'
|
||||
task runGemFireServer(dependsOn: availablePort) {
|
||||
doLast {
|
||||
println 'STARTING GEMFIRE SERVER...'
|
||||
|
||||
String classpath = sourceSets.main.runtimeClasspath.collect { it }.join(File.pathSeparator)
|
||||
String classpath = sourceSets.main.runtimeClasspath.collect { it }.join(File.pathSeparator)
|
||||
|
||||
String[] commandLine = ['java', '-server', '-ea',
|
||||
"-Dspring.session.data.gemfire.port=$port",
|
||||
"-Dsample.httpsession.gemfire.log-level="
|
||||
+ System.getProperty('sample.httpsession.gemfire.log-level', 'warning'),
|
||||
'-classpath', classpath, 'sample.ServerConfig']
|
||||
String[] commandLine = ['java', '-server', '-ea',
|
||||
"-Dspring.session.data.gemfire.port=$port",
|
||||
"-Dsample.httpsession.gemfire.log-level="
|
||||
+ System.getProperty('sample.httpsession.gemfire.log-level', 'warning'),
|
||||
'-classpath', classpath, 'sample.ServerConfig']
|
||||
|
||||
//println commandLine
|
||||
//println commandLine
|
||||
|
||||
process = commandLine.execute()
|
||||
process.in.close()
|
||||
process.out.close()
|
||||
process.err.close()
|
||||
process = commandLine.execute()
|
||||
process.in.close()
|
||||
process.out.close()
|
||||
process.err.close()
|
||||
}
|
||||
}
|
||||
|
||||
integrationTest.doLast {
|
||||
|
||||
@@ -10,8 +10,7 @@ buildscript {
|
||||
apply plugin: 'org.springframework.boot'
|
||||
|
||||
apply from: JAVA_GRADLE
|
||||
|
||||
//tasks.findByPath("artifactoryPublish")?.enabled = false
|
||||
apply from: SAMPLE_GRADLE
|
||||
|
||||
group = 'samples'
|
||||
ext {
|
||||
@@ -23,7 +22,7 @@ ext['spring-security.version'] = springSecurityVersion
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-session'),
|
||||
"org.springframework.boot:spring-boot-starter-redis",
|
||||
"org.springframework.boot:spring-boot-starter-data-redis",
|
||||
"org.springframework.boot:spring-boot-starter-web",
|
||||
"org.springframework.boot:spring-boot-starter-thymeleaf",
|
||||
"org.springframework.boot:spring-boot-starter-security",
|
||||
@@ -66,4 +65,4 @@ def reservePort() {
|
||||
def result = socket.localPort
|
||||
socket.close()
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.gemstone.gemfire.cache.client.ClientCache;
|
||||
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
|
||||
import com.gemstone.gemfire.cache.query.Index;
|
||||
import com.gemstone.gemfire.cache.server.CacheServer;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -47,8 +48,8 @@ import org.springframework.session.events.AbstractSessionEvent;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* AbstractGemFireIntegrationTests is an abstract base class encapsulating common
|
||||
* operations for writing Spring Session GemFire integration tests.
|
||||
* {@link AbstractGemFireIntegrationTests} is an abstract base class encapsulating common
|
||||
* operations for writing Spring Session Data GemFire integration tests.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
@@ -74,8 +75,7 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
protected static final long DEFAULT_WAIT_DURATION = TimeUnit.SECONDS.toMillis(20);
|
||||
protected static final long DEFAULT_WAIT_INTERVAL = 500L;
|
||||
|
||||
protected static final File WORKING_DIRECTORY =
|
||||
new File(System.getProperty("user.dir"));
|
||||
protected static final File WORKING_DIRECTORY = new File(System.getProperty("user.dir"));
|
||||
|
||||
protected static final String DEFAULT_PROCESS_CONTROL_FILENAME = "process.ctl";
|
||||
|
||||
@@ -83,7 +83,7 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
System.getProperty("spring.session.data.gemfire.log-file", "server.log");
|
||||
|
||||
protected static final String GEMFIRE_LOG_LEVEL =
|
||||
System.getProperty("spring.session.data.gemfire.log-level", "warning");
|
||||
System.getProperty("spring.session.data.gemfire.log-level", "error");
|
||||
|
||||
@Autowired
|
||||
protected Cache gemfireCache;
|
||||
@@ -258,7 +258,7 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected static int waitForProcessToStop(Process process, File directory, long duration) {
|
||||
final long timeout = (System.currentTimeMillis() + duration);
|
||||
long timeout = (System.currentTimeMillis() + duration);
|
||||
|
||||
try {
|
||||
while (process.isAlive() && System.currentTimeMillis() < timeout) {
|
||||
@@ -282,7 +282,7 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("all")
|
||||
protected static boolean waitOnCondition(Condition condition, long duration) {
|
||||
final long timeout = (System.currentTimeMillis() + duration);
|
||||
long timeout = (System.currentTimeMillis() + duration);
|
||||
|
||||
try {
|
||||
while (!condition.evaluate() && System.currentTimeMillis() < timeout) {
|
||||
@@ -311,6 +311,13 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
return processControl;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void assertValidSession(ExpiringSession session) {
|
||||
assertThat(session).isNotNull();
|
||||
assertThat(session.getId()).isNotEmpty();
|
||||
assertThat(session.isExpired()).isFalse();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void assertRegion(Region<?, ?> actualRegion, String expectedName, DataPolicy expectedDataPolicy) {
|
||||
assertThat(actualRegion).isNotNull();
|
||||
@@ -335,6 +342,7 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
/* (non-Javadoc) */
|
||||
protected void assertEntryIdleTimeout(ExpirationAttributes actualExpirationAttributes,
|
||||
ExpirationAction expectedAction, int expectedTimeout) {
|
||||
|
||||
assertThat(actualExpirationAttributes).isNotNull();
|
||||
assertThat(actualExpirationAttributes.getAction()).isEqualTo(expectedAction);
|
||||
assertThat(actualExpirationAttributes.getTimeout()).isEqualTo(expectedTimeout);
|
||||
@@ -379,6 +387,12 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
return (T) session;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected <T extends ExpiringSession> T delete(T session) {
|
||||
this.gemfireSessionRepository.delete(session);
|
||||
return session;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected <T extends ExpiringSession> T expire(T session) {
|
||||
session.setLastAccessedTime(0L);
|
||||
@@ -446,5 +460,4 @@ public abstract class AbstractGemFireIntegrationTests {
|
||||
protected interface Condition {
|
||||
boolean evaluate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ import com.gemstone.gemfire.cache.DataPolicy;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.RegionAttributes;
|
||||
import com.gemstone.gemfire.cache.client.ClientCache;
|
||||
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
@@ -58,7 +60,7 @@ import org.springframework.session.events.SessionDeletedEvent;
|
||||
import org.springframework.session.events.SessionExpiredEvent;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
import org.springframework.util.SocketUtils;
|
||||
@@ -66,28 +68,29 @@ import org.springframework.util.SocketUtils;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* The ClientServerGemFireOperationsSessionRepositoryIntegrationTests class is a test
|
||||
* suite of test cases testing the functionality of GemFire-backed Spring Sessions using a
|
||||
* GemFire client-server topology.
|
||||
* Integration tests to test the functionality of GemFire-backed Spring Sessions using
|
||||
* the GemFire client-server topology.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.springframework.context.ConfigurableApplicationContext
|
||||
* @see org.springframework.session.ExpiringSession
|
||||
* @see org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
|
||||
* @see org.springframework.test.annotation.DirtiesContext
|
||||
* @see org.springframework.test.context.ContextConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @see org.springframework.test.context.web.WebAppConfiguration
|
||||
* @see com.gemstone.gemfire.cache.Cache
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
* @see com.gemstone.gemfire.cache.client.ClientCache
|
||||
* @see com.gemstone.gemfire.cache.client.Pool
|
||||
* @see com.gemstone.gemfire.cache.server.CacheServer
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = ClientServerGemFireOperationsSessionRepositoryIntegrationTests.SpringSessionGemFireClientConfiguration.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes =
|
||||
ClientServerGemFireOperationsSessionRepositoryIntegrationTests.SpringSessionDataGemFireClientConfiguration.class)
|
||||
@DirtiesContext
|
||||
@WebAppConfiguration
|
||||
public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
|
||||
@@ -108,32 +111,33 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
|
||||
|
||||
@BeforeClass
|
||||
public static void startGemFireServer() throws IOException {
|
||||
final long t0 = System.currentTimeMillis();
|
||||
long t0 = System.currentTimeMillis();
|
||||
|
||||
final int port = SocketUtils.findAvailableTcpPort();
|
||||
int port = SocketUtils.findAvailableTcpPort();
|
||||
|
||||
System.err.printf("Starting a GemFire Server on [%1$s] listening on port [%2$d]%n",
|
||||
SpringSessionGemFireServerConfiguration.SERVER_HOSTNAME, port);
|
||||
System.err.printf("Starting a GemFire Server running on host [%1$s] listening on port [%2$d]%n",
|
||||
SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port);
|
||||
|
||||
System.setProperty("spring.session.data.gemfire.port", String.valueOf(port));
|
||||
|
||||
String processWorkingDirectoryPathname = String.format("gemfire-client-server-tests-%1$s",
|
||||
TIMESTAMP.format(new Date()));
|
||||
String processWorkingDirectoryPathname =
|
||||
String.format("gemfire-client-server-tests-%1$s", TIMESTAMP.format(new Date()));
|
||||
|
||||
processWorkingDirectory = createDirectory(processWorkingDirectoryPathname);
|
||||
|
||||
gemfireServer = run(SpringSessionGemFireServerConfiguration.class, processWorkingDirectory,
|
||||
gemfireServer = run(SpringSessionDataGemFireServerConfiguration.class, processWorkingDirectory,
|
||||
String.format("-Dspring.session.data.gemfire.port=%1$d", port));
|
||||
|
||||
assertThat(waitForCacheServerToStart(SpringSessionGemFireServerConfiguration.SERVER_HOSTNAME, port)).isTrue();
|
||||
assertThat(waitForCacheServerToStart(SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port))
|
||||
.isTrue();
|
||||
|
||||
System.err.printf("GemFire Server [startup time = %1$d ms]%n", System.currentTimeMillis() - t0);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopGemFireServerAndDeleteArtifacts() {
|
||||
public static void stopGemFireServer() {
|
||||
if (gemfireServer != null) {
|
||||
gemfireServer.destroyForcibly();
|
||||
gemfireServer.destroy();
|
||||
System.err.printf("GemFire Server [exit code = %1$d]%n",
|
||||
waitForProcessToStop(gemfireServer, processWorkingDirectory));
|
||||
}
|
||||
@@ -158,7 +162,7 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
|
||||
springSessionGemFireRegion.getAttributes();
|
||||
|
||||
assertThat(springSessionGemFireRegionAttributes).isNotNull();
|
||||
assertThat(springSessionGemFireRegionAttributes.getDataPolicy()).isEqualTo(DataPolicy.EMPTY);
|
||||
assertThat(springSessionGemFireRegionAttributes.getDataPolicy()).isEqualTo(DataPolicy.NORMAL);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -168,7 +172,7 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
|
||||
|
||||
@Test
|
||||
public void createSessionFiresSessionCreatedEvent() {
|
||||
final long beforeOrAtCreationTime = System.currentTimeMillis();
|
||||
long beforeOrAtCreationTime = System.currentTimeMillis();
|
||||
|
||||
ExpiringSession expectedSession = save(createSession());
|
||||
|
||||
@@ -178,12 +182,19 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
|
||||
|
||||
ExpiringSession createdSession = sessionEvent.getSession();
|
||||
|
||||
assertThat(createdSession).isEqualTo(expectedSession);
|
||||
assertThat(createdSession.getId()).isNotNull();
|
||||
assertThat(createdSession.getId()).isEqualTo(expectedSession.getId());
|
||||
assertThat(createdSession.getCreationTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime);
|
||||
assertThat(createdSession.getLastAccessedTime()).isEqualTo(createdSession.getCreationTime());
|
||||
assertThat(createdSession.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
|
||||
createdSession.setAttribute("attrOne", 1);
|
||||
|
||||
assertThat(save(touch(createdSession)).getAttribute("attrOne")).isEqualTo(1);
|
||||
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
|
||||
|
||||
assertThat(sessionEvent).isNull();
|
||||
|
||||
this.gemfireSessionRepository.delete(expectedSession.getId());
|
||||
}
|
||||
|
||||
@@ -194,19 +205,13 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
|
||||
AbstractSessionEvent sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
|
||||
|
||||
assertThat(sessionEvent).isInstanceOf(SessionCreatedEvent.class);
|
||||
assertThat(sessionEvent.<ExpiringSession>getSession()).isEqualTo(expectedSession);
|
||||
assertThat(sessionEvent.getSession()).isEqualTo(expectedSession);
|
||||
assertThat(this.sessionEventListener.getSessionEvent()).isNull();
|
||||
|
||||
ExpiringSession savedSession = this.gemfireSessionRepository.getSession(expectedSession.getId());
|
||||
|
||||
assertThat(savedSession).isEqualTo(expectedSession);
|
||||
|
||||
// NOTE for some reason or another, performing a GemFire (Client)Cache
|
||||
// Region.get(key)
|
||||
// causes a Region CREATE event... o.O
|
||||
// calling sessionEventListener.getSessionEvent() here to clear the event
|
||||
this.sessionEventListener.getSessionEvent();
|
||||
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(
|
||||
TimeUnit.SECONDS.toMillis(MAX_INACTIVE_INTERVAL_IN_SECONDS + 1));
|
||||
|
||||
@@ -240,15 +245,15 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME,
|
||||
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
static class SpringSessionGemFireClientConfiguration {
|
||||
clientRegionShortcut = ClientRegionShortcut.CACHING_PROXY,
|
||||
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
static class SpringSessionDataGemFireClientConfiguration {
|
||||
|
||||
@Bean
|
||||
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
Properties gemfireProperties() {
|
||||
Properties gemfireProperties = new Properties();
|
||||
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
|
||||
@@ -271,17 +276,14 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
|
||||
|
||||
PoolFactoryBean poolFactory = new PoolFactoryBean();
|
||||
|
||||
poolFactory.setFreeConnectionTimeout(5000); // 5 seconds
|
||||
poolFactory.setKeepAlive(false);
|
||||
poolFactory.setMaxConnections(SpringSessionGemFireServerConfiguration.MAX_CONNECTIONS);
|
||||
poolFactory.setPingInterval(TimeUnit.SECONDS.toMillis(5));
|
||||
poolFactory.setReadTimeout(2000); // 2 seconds
|
||||
poolFactory.setRetryAttempts(1);
|
||||
poolFactory.setSubscriptionEnabled(true);
|
||||
poolFactory.setThreadLocalConnections(false);
|
||||
|
||||
poolFactory.setServers(Collections.singletonList(new ConnectionEndpoint(
|
||||
SpringSessionGemFireServerConfiguration.SERVER_HOSTNAME, port)));
|
||||
SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port)));
|
||||
|
||||
return poolFactory;
|
||||
}
|
||||
@@ -293,9 +295,9 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
|
||||
|
||||
// used for debugging purposes
|
||||
@SuppressWarnings("resource")
|
||||
public static void main(final String[] args) {
|
||||
public static void main(String[] args) {
|
||||
ConfigurableApplicationContext applicationContext = new AnnotationConfigApplicationContext(
|
||||
SpringSessionGemFireClientConfiguration.class);
|
||||
SpringSessionDataGemFireClientConfiguration.class);
|
||||
|
||||
applicationContext.registerShutdownHook();
|
||||
|
||||
@@ -308,31 +310,29 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
|
||||
}
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME, maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
static class SpringSessionGemFireServerConfiguration {
|
||||
@EnableGemFireHttpSession(regionName = SPRING_SESSION_GEMFIRE_REGION_NAME,
|
||||
maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
static class SpringSessionDataGemFireServerConfiguration {
|
||||
|
||||
static final int MAX_CONNECTIONS = 50;
|
||||
static final String SERVER_HOSTNAME = "localhost";
|
||||
|
||||
@Bean
|
||||
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
Properties gemfireProperties() {
|
||||
Properties gemfireProperties = new Properties();
|
||||
|
||||
gemfireProperties.setProperty("name", name());
|
||||
gemfireProperties.setProperty("mcast-port", "0");
|
||||
gemfireProperties.setProperty("log-file", "server.log");
|
||||
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
|
||||
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
String name() {
|
||||
return SpringSessionGemFireServerConfiguration.class.getName();
|
||||
return ClientServerGemFireOperationsSessionRepositoryIntegrationTests.class.getName();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -351,22 +351,22 @@ public class ClientServerGemFireOperationsSessionRepositoryIntegrationTests
|
||||
|
||||
CacheServerFactoryBean cacheServerFactory = new CacheServerFactoryBean();
|
||||
|
||||
cacheServerFactory.setCache(gemfireCache);
|
||||
cacheServerFactory.setAutoStartup(true);
|
||||
cacheServerFactory.setBindAddress(SERVER_HOSTNAME);
|
||||
cacheServerFactory.setCache(gemfireCache);
|
||||
cacheServerFactory.setMaxConnections(MAX_CONNECTIONS);
|
||||
cacheServerFactory.setPort(port);
|
||||
|
||||
return cacheServerFactory;
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public static void main(final String[] args) throws IOException {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
SpringSessionGemFireServerConfiguration.class);
|
||||
public static void main(String[] args) throws IOException {
|
||||
AnnotationConfigApplicationContext context =
|
||||
new AnnotationConfigApplicationContext(SpringSessionDataGemFireServerConfiguration.class);
|
||||
|
||||
context.registerShutdownHook();
|
||||
|
||||
writeProcessControlFile(WORKING_DIRECTORY);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.session.data.gemfire;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.gemstone.gemfire.cache.Cache;
|
||||
import com.gemstone.gemfire.cache.client.ClientCache;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
|
||||
import org.springframework.data.gemfire.client.PoolFactoryBean;
|
||||
import org.springframework.data.gemfire.server.CacheServerFactoryBean;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpoint;
|
||||
import org.springframework.session.ExpiringSession;
|
||||
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests testing the addition/removal of HTTP Session Attributes
|
||||
* and the proper persistence of the HTTP Session state in a GemFire cache
|
||||
* across a client/server topology.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.springframework.context.ConfigurableApplicationContext
|
||||
* @see org.springframework.session.ExpiringSession
|
||||
* @see org.springframework.session.data.gemfire.AbstractGemFireIntegrationTests
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession
|
||||
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
|
||||
* @see org.springframework.test.context.ContextConfiguration
|
||||
* @see org.springframework.test.context.junit4.SpringRunner
|
||||
* @see com.gemstone.gemfire.cache.Cache
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
* @see com.gemstone.gemfire.cache.client.ClientCache
|
||||
* @since 1.3.1
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes =
|
||||
ClientServerHttpSessionAttributesDeltaIntegrationTests.SpringSessionDataGemFireClientConfiguration.class)
|
||||
public class ClientServerHttpSessionAttributesDeltaIntegrationTests extends AbstractGemFireIntegrationTests {
|
||||
|
||||
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 1;
|
||||
|
||||
private static final DateFormat TIMESTAMP = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
|
||||
|
||||
private static File processWorkingDirectory;
|
||||
|
||||
private static Process gemfireServer;
|
||||
|
||||
@BeforeClass
|
||||
public static void startGemFireServer() throws IOException {
|
||||
long t0 = System.currentTimeMillis();
|
||||
|
||||
int port = SocketUtils.findAvailableTcpPort();
|
||||
|
||||
System.err.printf("Starting a GemFire Server running on host [%1$s] listening on port [%2$d]%n",
|
||||
SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port);
|
||||
|
||||
System.setProperty("spring.session.data.gemfire.port", String.valueOf(port));
|
||||
|
||||
String processWorkingDirectoryPathname =
|
||||
String.format("gemfire-client-server-tests-%1$s", TIMESTAMP.format(new Date()));
|
||||
|
||||
processWorkingDirectory = createDirectory(processWorkingDirectoryPathname);
|
||||
|
||||
gemfireServer = run(SpringSessionDataGemFireServerConfiguration.class, processWorkingDirectory,
|
||||
String.format("-Dspring.session.data.gemfire.port=%1$d", port));
|
||||
|
||||
assertThat(waitForCacheServerToStart(SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port))
|
||||
.isTrue();
|
||||
|
||||
System.err.printf("GemFire Server [startup time = %1$d ms]%n", System.currentTimeMillis() - t0);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopGemFireServer() {
|
||||
if (gemfireServer != null) {
|
||||
gemfireServer.destroy();
|
||||
System.err.printf("GemFire Server [exit code = %1$d]%n",
|
||||
waitForProcessToStop(gemfireServer, processWorkingDirectory));
|
||||
}
|
||||
|
||||
if (Boolean.valueOf(System.getProperty("spring.session.data.gemfire.fork.clean", Boolean.TRUE.toString()))) {
|
||||
FileSystemUtils.deleteRecursively(processWorkingDirectory);
|
||||
}
|
||||
|
||||
assertThat(waitForClientCacheToClose(DEFAULT_WAIT_DURATION)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionCreationAndAccessIsSuccessful() {
|
||||
ExpiringSession session = save(touch(createSession()));
|
||||
|
||||
assertThat(session).isNotNull();
|
||||
assertThat(session.isExpired()).isFalse();
|
||||
|
||||
session.setAttribute("attrOne", 1);
|
||||
session.setAttribute("attrTwo", 2);
|
||||
|
||||
save(touch(session));
|
||||
|
||||
ExpiringSession loadedSession = get(session.getId());
|
||||
|
||||
assertThat(loadedSession).isNotNull();
|
||||
assertThat(loadedSession.isExpired()).isFalse();
|
||||
assertThat(loadedSession).isNotSameAs(session);
|
||||
assertThat(loadedSession.getId()).isEqualTo(session.getId());
|
||||
assertThat(loadedSession.<Integer>getAttribute("attrOne")).isEqualTo(1);
|
||||
assertThat(loadedSession.<Integer>getAttribute("attrTwo")).isEqualTo(2);
|
||||
|
||||
loadedSession.removeAttribute("attrTwo");
|
||||
|
||||
assertThat(loadedSession.getAttributeNames()).doesNotContain("attrTwo");
|
||||
assertThat(loadedSession.getAttributeNames()).hasSize(1);
|
||||
|
||||
save(touch(loadedSession));
|
||||
|
||||
ExpiringSession reloadedSession = get(loadedSession.getId());
|
||||
|
||||
assertThat(reloadedSession).isNotNull();
|
||||
assertThat(reloadedSession.isExpired()).isFalse();
|
||||
assertThat(reloadedSession).isNotSameAs(loadedSession);
|
||||
assertThat(reloadedSession.getId()).isEqualTo(loadedSession.getId());
|
||||
assertThat(reloadedSession.getAttributeNames()).hasSize(1);
|
||||
assertThat(reloadedSession.getAttributeNames()).doesNotContain("attrTwo");
|
||||
assertThat(reloadedSession.<Integer>getAttribute("attrOne")).isEqualTo(1);
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession
|
||||
static class SpringSessionDataGemFireClientConfiguration {
|
||||
|
||||
@Bean
|
||||
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
Properties gemfireProperties() {
|
||||
Properties gemfireProperties = new Properties();
|
||||
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
ClientCacheFactoryBean gemfireCache() {
|
||||
ClientCacheFactoryBean clientCacheFactory = new ClientCacheFactoryBean();
|
||||
|
||||
clientCacheFactory.setClose(true);
|
||||
clientCacheFactory.setProperties(gemfireProperties());
|
||||
|
||||
return clientCacheFactory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
PoolFactoryBean gemfirePool(@Value("${spring.session.data.gemfire.port:"
|
||||
+ DEFAULT_GEMFIRE_SERVER_PORT + "}") int port) {
|
||||
|
||||
PoolFactoryBean poolFactory = new PoolFactoryBean();
|
||||
|
||||
poolFactory.setKeepAlive(false);
|
||||
poolFactory.setPingInterval(TimeUnit.SECONDS.toMillis(5));
|
||||
poolFactory.setReadTimeout(2000); // 2 seconds
|
||||
poolFactory.setRetryAttempts(1);
|
||||
poolFactory.setSubscriptionEnabled(true);
|
||||
|
||||
poolFactory.setServers(Collections.singletonList(new ConnectionEndpoint(
|
||||
SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port)));
|
||||
|
||||
return poolFactory;
|
||||
}
|
||||
|
||||
// used for debugging purposes
|
||||
@SuppressWarnings("resource")
|
||||
public static void main(String[] args) {
|
||||
ConfigurableApplicationContext applicationContext =
|
||||
new AnnotationConfigApplicationContext(SpringSessionDataGemFireClientConfiguration.class);
|
||||
|
||||
applicationContext.registerShutdownHook();
|
||||
|
||||
ClientCache clientCache = applicationContext.getBean(ClientCache.class);
|
||||
|
||||
for (InetSocketAddress server : clientCache.getCurrentServers()) {
|
||||
System.err.printf("GemFire Server [host: %1$s, port: %2$d]%n",
|
||||
server.getHostName(), server.getPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
static class SpringSessionDataGemFireServerConfiguration {
|
||||
|
||||
static final String SERVER_HOSTNAME = "localhost";
|
||||
|
||||
@Bean
|
||||
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
Properties gemfireProperties() {
|
||||
Properties gemfireProperties = new Properties();
|
||||
|
||||
gemfireProperties.setProperty("name", name());
|
||||
gemfireProperties.setProperty("mcast-port", "0");
|
||||
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
|
||||
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
String name() {
|
||||
return ClientServerHttpSessionAttributesDeltaIntegrationTests.class.getName();
|
||||
}
|
||||
|
||||
@Bean
|
||||
CacheFactoryBean gemfireCache() {
|
||||
CacheFactoryBean gemfireCache = new CacheFactoryBean();
|
||||
|
||||
gemfireCache.setClose(true);
|
||||
gemfireCache.setProperties(gemfireProperties());
|
||||
|
||||
return gemfireCache;
|
||||
}
|
||||
|
||||
@Bean
|
||||
CacheServerFactoryBean gemfireCacheServer(Cache gemfireCache,
|
||||
@Value("${spring.session.data.gemfire.port:" + DEFAULT_GEMFIRE_SERVER_PORT + "}") int port) {
|
||||
|
||||
CacheServerFactoryBean cacheServerFactory = new CacheServerFactoryBean();
|
||||
|
||||
cacheServerFactory.setCache(gemfireCache);
|
||||
cacheServerFactory.setAutoStartup(true);
|
||||
cacheServerFactory.setBindAddress(SERVER_HOSTNAME);
|
||||
cacheServerFactory.setPort(port);
|
||||
|
||||
return cacheServerFactory;
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public static void main(String[] args) throws IOException {
|
||||
AnnotationConfigApplicationContext context =
|
||||
new AnnotationConfigApplicationContext(SpringSessionDataGemFireServerConfiguration.class);
|
||||
|
||||
context.registerShutdownHook();
|
||||
|
||||
writeProcessControlFile(WORKING_DIRECTORY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.session.data.gemfire;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.gemstone.gemfire.cache.Cache;
|
||||
import com.gemstone.gemfire.cache.client.ClientCache;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
|
||||
import org.springframework.data.gemfire.client.PoolFactoryBean;
|
||||
import org.springframework.data.gemfire.server.CacheServerFactoryBean;
|
||||
import org.springframework.data.gemfire.support.ConnectionEndpoint;
|
||||
import org.springframework.session.ExpiringSession;
|
||||
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
|
||||
import org.springframework.session.events.AbstractSessionEvent;
|
||||
import org.springframework.session.events.SessionCreatedEvent;
|
||||
import org.springframework.session.events.SessionDeletedEvent;
|
||||
import org.springframework.session.events.SessionExpiredEvent;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* The ClientServerProxyRegionSessionOperationsIntegrationTests class...
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes =
|
||||
ClientServerProxyRegionSessionOperationsIntegrationTests.SpringSessionDataGemFireClientConfiguration.class)
|
||||
public class ClientServerProxyRegionSessionOperationsIntegrationTests extends AbstractGemFireIntegrationTests {
|
||||
|
||||
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 1;
|
||||
|
||||
private static final DateFormat TIMESTAMP = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
|
||||
|
||||
private static File processWorkingDirectory;
|
||||
|
||||
private static Process gemfireServer;
|
||||
|
||||
@Autowired
|
||||
private SessionEventListener sessionEventListener;
|
||||
|
||||
@BeforeClass
|
||||
public static void startGemFireServer() throws IOException {
|
||||
long t0 = System.currentTimeMillis();
|
||||
|
||||
int port = SocketUtils.findAvailableTcpPort();
|
||||
|
||||
System.err.printf("Starting a GemFire Server running on host [%1$s] listening on port [%2$d]%n",
|
||||
SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port);
|
||||
|
||||
System.setProperty("spring.session.data.gemfire.port", String.valueOf(port));
|
||||
|
||||
String processWorkingDirectoryPathname =
|
||||
String.format("gemfire-client-server-tests-%1$s", TIMESTAMP.format(new Date()));
|
||||
|
||||
processWorkingDirectory = createDirectory(processWorkingDirectoryPathname);
|
||||
|
||||
gemfireServer = run(SpringSessionDataGemFireServerConfiguration.class, processWorkingDirectory,
|
||||
String.format("-Dspring.session.data.gemfire.port=%1$d", port));
|
||||
|
||||
assertThat(waitForCacheServerToStart(SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port))
|
||||
.isTrue();
|
||||
|
||||
System.err.printf("GemFire Server [startup time = %1$d ms]%n", System.currentTimeMillis() - t0);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopGemFireServer() {
|
||||
if (gemfireServer != null) {
|
||||
gemfireServer.destroy();
|
||||
System.err.printf("GemFire Server [exit code = %1$d]%n",
|
||||
waitForProcessToStop(gemfireServer, processWorkingDirectory));
|
||||
}
|
||||
|
||||
if (Boolean.valueOf(System.getProperty("spring.session.data.gemfire.fork.clean", Boolean.TRUE.toString()))) {
|
||||
FileSystemUtils.deleteRecursively(processWorkingDirectory);
|
||||
}
|
||||
|
||||
assertThat(waitForClientCacheToClose(DEFAULT_WAIT_DURATION)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createReadUpdateExpireRecreateDeleteRecreateSessionResultsCorrectSessionCreatedEvents() {
|
||||
ExpiringSession session = save(touch(createSession()));
|
||||
|
||||
assertValidSession(session);
|
||||
|
||||
AbstractSessionEvent sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
|
||||
|
||||
assertThat(sessionEvent).isInstanceOf(SessionCreatedEvent.class);
|
||||
assertThat(sessionEvent.getSessionId()).isEqualTo(session.getId());
|
||||
|
||||
// GET
|
||||
ExpiringSession loadedSession = get(session.getId());
|
||||
|
||||
assertThat(loadedSession).isNotNull();
|
||||
assertThat(loadedSession.getId()).isEqualTo(session.getId());
|
||||
assertThat(loadedSession.getCreationTime()).isEqualTo(session.getCreationTime());
|
||||
assertThat(loadedSession.getLastAccessedTime()).isGreaterThanOrEqualTo((session.getLastAccessedTime()));
|
||||
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
|
||||
|
||||
assertThat(sessionEvent).isNull();
|
||||
|
||||
loadedSession.setAttribute("attrOne", 1);
|
||||
loadedSession.setAttribute("attrTwo", 2);
|
||||
|
||||
// UPDATE
|
||||
save(touch(loadedSession));
|
||||
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
|
||||
|
||||
assertThat(sessionEvent).isNull();
|
||||
|
||||
// EXPIRE
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(
|
||||
TimeUnit.SECONDS.toMillis(MAX_INACTIVE_INTERVAL_IN_SECONDS + 1));
|
||||
|
||||
assertThat(sessionEvent).isInstanceOf(SessionExpiredEvent.class);
|
||||
assertThat(sessionEvent.getSessionId()).isEqualTo(session.getId());
|
||||
|
||||
// RECREATE
|
||||
save(touch(session));
|
||||
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
|
||||
|
||||
assertThat(sessionEvent).isInstanceOf(SessionCreatedEvent.class);
|
||||
assertThat(sessionEvent.getSessionId()).isEqualTo(session.getId());
|
||||
|
||||
// DELETE
|
||||
delete(session);
|
||||
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
|
||||
|
||||
assertThat(sessionEvent).isInstanceOf(SessionDeletedEvent.class);
|
||||
assertThat(sessionEvent.getSessionId()).isEqualTo(session.getId());
|
||||
|
||||
// RECREATE
|
||||
save(touch(session));
|
||||
|
||||
sessionEvent = this.sessionEventListener.waitForSessionEvent(500);
|
||||
|
||||
assertThat(sessionEvent).isInstanceOf(SessionCreatedEvent.class);
|
||||
assertThat(sessionEvent.getSessionId()).isEqualTo(session.getId());
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession
|
||||
static class SpringSessionDataGemFireClientConfiguration {
|
||||
|
||||
@Bean
|
||||
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
Properties gemfireProperties() {
|
||||
Properties gemfireProperties = new Properties();
|
||||
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
ClientCacheFactoryBean gemfireCache() {
|
||||
ClientCacheFactoryBean clientCacheFactory = new ClientCacheFactoryBean();
|
||||
|
||||
clientCacheFactory.setClose(true);
|
||||
clientCacheFactory.setProperties(gemfireProperties());
|
||||
|
||||
return clientCacheFactory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
PoolFactoryBean gemfirePool(@Value("${spring.session.data.gemfire.port:"
|
||||
+ DEFAULT_GEMFIRE_SERVER_PORT + "}") int port) {
|
||||
|
||||
PoolFactoryBean poolFactory = new PoolFactoryBean();
|
||||
|
||||
poolFactory.setKeepAlive(false);
|
||||
poolFactory.setPingInterval(TimeUnit.SECONDS.toMillis(5));
|
||||
poolFactory.setReadTimeout(2000); // 2 seconds
|
||||
poolFactory.setRetryAttempts(1);
|
||||
poolFactory.setSubscriptionEnabled(true);
|
||||
|
||||
poolFactory.setServers(Collections.singletonList(new ConnectionEndpoint(
|
||||
SpringSessionDataGemFireServerConfiguration.SERVER_HOSTNAME, port)));
|
||||
|
||||
return poolFactory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SessionEventListener sessionEventListener() {
|
||||
return new SessionEventListener();
|
||||
}
|
||||
|
||||
// used for debugging purposes
|
||||
@SuppressWarnings("resource")
|
||||
public static void main(String[] args) {
|
||||
ConfigurableApplicationContext applicationContext =
|
||||
new AnnotationConfigApplicationContext(SpringSessionDataGemFireClientConfiguration.class);
|
||||
|
||||
applicationContext.registerShutdownHook();
|
||||
|
||||
ClientCache clientCache = applicationContext.getBean(ClientCache.class);
|
||||
|
||||
for (InetSocketAddress server : clientCache.getCurrentServers()) {
|
||||
System.err.printf("GemFire Server [host: %1$s, port: %2$d]%n",
|
||||
server.getHostName(), server.getPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
static class SpringSessionDataGemFireServerConfiguration {
|
||||
|
||||
static final String SERVER_HOSTNAME = "localhost";
|
||||
|
||||
@Bean
|
||||
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
Properties gemfireProperties() {
|
||||
Properties gemfireProperties = new Properties();
|
||||
|
||||
gemfireProperties.setProperty("name", name());
|
||||
gemfireProperties.setProperty("mcast-port", "0");
|
||||
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
|
||||
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
String name() {
|
||||
return ClientServerProxyRegionSessionOperationsIntegrationTests.class.getName();
|
||||
}
|
||||
|
||||
@Bean
|
||||
CacheFactoryBean gemfireCache() {
|
||||
CacheFactoryBean gemfireCache = new CacheFactoryBean();
|
||||
|
||||
gemfireCache.setClose(true);
|
||||
gemfireCache.setProperties(gemfireProperties());
|
||||
|
||||
return gemfireCache;
|
||||
}
|
||||
|
||||
@Bean
|
||||
CacheServerFactoryBean gemfireCacheServer(Cache gemfireCache,
|
||||
@Value("${spring.session.data.gemfire.port:" + DEFAULT_GEMFIRE_SERVER_PORT + "}") int port) {
|
||||
|
||||
CacheServerFactoryBean cacheServerFactory = new CacheServerFactoryBean();
|
||||
|
||||
cacheServerFactory.setCache(gemfireCache);
|
||||
cacheServerFactory.setAutoStartup(true);
|
||||
cacheServerFactory.setBindAddress(SERVER_HOSTNAME);
|
||||
cacheServerFactory.setPort(port);
|
||||
|
||||
return cacheServerFactory;
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public static void main(String[] args) throws IOException {
|
||||
AnnotationConfigApplicationContext context =
|
||||
new AnnotationConfigApplicationContext(SpringSessionDataGemFireServerConfiguration.class);
|
||||
|
||||
context.registerShutdownHook();
|
||||
|
||||
writeProcessControlFile(WORKING_DIRECTORY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,7 +52,7 @@ public interface FindByIndexNameSessionRepository<S extends Session>
|
||||
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME} and the value of
|
||||
* the specified principal name.
|
||||
*
|
||||
* @param indexName the name if the index (i.e.
|
||||
* @param indexName the name of the index (i.e.
|
||||
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME})
|
||||
* @param indexValue the value of the index to search for.
|
||||
* @return a Map (never null) of the session id to the {@link Session} of all sessions
|
||||
|
||||
@@ -39,8 +39,11 @@ import com.gemstone.gemfire.Delta;
|
||||
import com.gemstone.gemfire.Instantiator;
|
||||
import com.gemstone.gemfire.InvalidDeltaException;
|
||||
import com.gemstone.gemfire.cache.EntryEvent;
|
||||
import com.gemstone.gemfire.cache.Operation;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
|
||||
import com.gemstone.gemfire.internal.concurrent.ConcurrentHashSet;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -57,11 +60,13 @@ import org.springframework.session.FindByIndexNameSessionRepository;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
|
||||
import org.springframework.session.data.gemfire.support.GemFireUtils;
|
||||
import org.springframework.session.events.SessionCreatedEvent;
|
||||
import org.springframework.session.events.SessionDeletedEvent;
|
||||
import org.springframework.session.events.SessionDestroyedEvent;
|
||||
import org.springframework.session.events.SessionExpiredEvent;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -90,6 +95,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
}
|
||||
};
|
||||
|
||||
private final Set<Integer> cachedSessionIds = new ConcurrentHashSet<Integer>();
|
||||
|
||||
private final GemfireOperations template;
|
||||
|
||||
protected final Log logger = newLogger();
|
||||
@@ -216,8 +223,49 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
boolean isExpiringSessionOrNull(Object obj) {
|
||||
return (obj == null || obj instanceof ExpiringSession);
|
||||
boolean isCreate(EntryEvent<?, ?> event) {
|
||||
return (isCreate(event.getOperation()) && isNotUpdate(event) && isExpiringSessionOrNull(event.getNewValue()));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private boolean isCreate(Operation operation) {
|
||||
return (operation.isCreate() && !Operation.LOCAL_LOAD_CREATE.equals(operation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine whether the developer is storing (HTTP) Sessions with other, arbitrary application
|
||||
* domain objects in the same GemFire cache {@link Region}; crazier things have happened!
|
||||
*
|
||||
* @param obj {@link Object} to evaluate.
|
||||
* @return a boolean value indicating whether the {@link Object} from the entry event is indeed
|
||||
* a {@link ExpiringSession}.
|
||||
* @see org.springframework.session.ExpiringSession
|
||||
*/
|
||||
private boolean isExpiringSessionOrNull(Object obj) {
|
||||
return (obj instanceof ExpiringSession || obj == null);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private boolean isNotUpdate(EntryEvent event) {
|
||||
return (isNotProxyRegion() || !this.cachedSessionIds.contains(ObjectUtils.nullSafeHashCode(event.getKey())));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private boolean isNotProxyRegion() {
|
||||
return !isProxyRegion();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private boolean isProxyRegion() {
|
||||
return GemFireUtils.isProxy(((GemfireAccessor) getTemplate()).getRegion());
|
||||
}
|
||||
|
||||
boolean forget(Object sessionId) {
|
||||
return this.cachedSessionIds.remove(ObjectUtils.nullSafeHashCode(sessionId));
|
||||
}
|
||||
|
||||
boolean remember(Object sessionId) {
|
||||
return (isProxyRegion() && this.cachedSessionIds.add(ObjectUtils.nullSafeHashCode(sessionId)));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@@ -226,16 +274,15 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method triggered when an entry is created in the GemFire cache
|
||||
* {@link Region}.
|
||||
* Callback method triggered when an entry is created in the GemFire cache {@link Region}.
|
||||
*
|
||||
* @param event an EntryEvent containing the details of the cache operation.
|
||||
* @param event {@link EntryEvent} containing the details of the cache {@link Region} operation.
|
||||
* @see com.gemstone.gemfire.cache.EntryEvent
|
||||
* @see #handleCreated(String, ExpiringSession)
|
||||
*/
|
||||
@Override
|
||||
public void afterCreate(EntryEvent<Object, ExpiringSession> event) {
|
||||
if (isExpiringSessionOrNull(event.getNewValue())) {
|
||||
if (isCreate(event)) {
|
||||
handleCreated(event.getKey().toString(), toExpiringSession(event.getNewValue()));
|
||||
}
|
||||
}
|
||||
@@ -266,6 +313,19 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
handleExpired(event.getKey().toString(), toExpiringSession(event.getOldValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given {@link Session} from GemFire.
|
||||
*
|
||||
* @param session {@link Session} to delete.
|
||||
* @return {@literal null}.
|
||||
* @see org.springframework.session.Session
|
||||
* @see #delete(String)
|
||||
*/
|
||||
protected ExpiringSession delete(Session session) {
|
||||
delete(session.getId());
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes Session created events to be published to the Spring application context.
|
||||
*
|
||||
@@ -276,6 +336,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
* @see #publishEvent(ApplicationEvent)
|
||||
*/
|
||||
protected void handleCreated(String sessionId, ExpiringSession session) {
|
||||
remember(sessionId);
|
||||
|
||||
publishEvent(session != null ? new SessionCreatedEvent(this, session)
|
||||
: new SessionCreatedEvent(this, sessionId));
|
||||
}
|
||||
@@ -290,6 +352,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
* @see #publishEvent(ApplicationEvent)
|
||||
*/
|
||||
protected void handleDeleted(String sessionId, ExpiringSession session) {
|
||||
forget(sessionId);
|
||||
|
||||
publishEvent(session != null ? new SessionDeletedEvent(this, session)
|
||||
: new SessionDeletedEvent(this, sessionId));
|
||||
}
|
||||
@@ -304,6 +368,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
* @see #publishEvent(ApplicationEvent)
|
||||
*/
|
||||
protected void handleDestroyed(String sessionId, ExpiringSession session) {
|
||||
forget(sessionId);
|
||||
|
||||
publishEvent(session != null ? new SessionDestroyedEvent(this, session)
|
||||
: new SessionDestroyedEvent(this, sessionId));
|
||||
}
|
||||
@@ -318,6 +384,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
* @see #publishEvent(ApplicationEvent)
|
||||
*/
|
||||
protected void handleExpired(String sessionId, ExpiringSession session) {
|
||||
forget(sessionId);
|
||||
|
||||
publishEvent(session != null ? new SessionExpiredEvent(this, session)
|
||||
: new SessionExpiredEvent(this, sessionId));
|
||||
}
|
||||
@@ -334,10 +402,23 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
getApplicationEventPublisher().publishEvent(event);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
this.logger.error(String.format("error occurred publishing event (%1$s)", event), t);
|
||||
this.logger.error(String.format("Error occurred publishing event [%s]", event), t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the {@link ExpiringSession#setLastAccessedTime(long)} property of the {@link ExpiringSession}.
|
||||
*
|
||||
* @param <T> {@link Class} sub-type of the {@link ExpiringSession}.
|
||||
* @param expiringSession {@link ExpiringSession} to touch.
|
||||
* @return the {@link ExpiringSession}.
|
||||
* @see org.springframework.session.ExpiringSession#setLastAccessedTime(long)
|
||||
*/
|
||||
protected <T extends ExpiringSession> T touch(T expiringSession) {
|
||||
expiringSession.setLastAccessedTime(System.currentTimeMillis());
|
||||
return expiringSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* GemFireSession is a GemFire representation model of a Spring {@link ExpiringSession}
|
||||
* that stores and manages Session state information in GemFire. This class implements
|
||||
@@ -362,8 +443,8 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
private long creationTime;
|
||||
private long lastAccessedTime;
|
||||
|
||||
private transient final GemFireSessionAttributes sessionAttributes = new GemFireSessionAttributes(
|
||||
this);
|
||||
private transient final GemFireSessionAttributes sessionAttributes =
|
||||
new GemFireSessionAttributes(this);
|
||||
|
||||
private transient final SpelExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
@@ -399,11 +480,13 @@ public abstract class AbstractGemFireOperationsSessionRepository extends CacheLi
|
||||
return session;
|
||||
}
|
||||
|
||||
public static GemFireSession copy(ExpiringSession session) {
|
||||
return new GemFireSession(session);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static GemFireSession from(ExpiringSession expiringSession) {
|
||||
GemFireSession session = new GemFireSession(expiringSession);
|
||||
session.setLastAccessedTime(System.currentTimeMillis());
|
||||
return session;
|
||||
public static GemFireSession from(ExpiringSession session) {
|
||||
return (session instanceof GemFireSession ? (GemFireSession) session : copy(session));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
|
||||
@@ -119,15 +119,12 @@ public class GemFireOperationsSessionRepository extends AbstractGemFireOperation
|
||||
ExpiringSession storedSession = getTemplate().get(sessionId);
|
||||
|
||||
if (storedSession != null) {
|
||||
if (storedSession.isExpired()) {
|
||||
delete(storedSession.getId());
|
||||
}
|
||||
else {
|
||||
return GemFireSession.from(storedSession);
|
||||
}
|
||||
storedSession = storedSession.isExpired()
|
||||
? delete(storedSession)
|
||||
: touch(GemFireSession.from(storedSession));
|
||||
}
|
||||
|
||||
return null;
|
||||
return storedSession;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,7 +135,7 @@ public class GemFireOperationsSessionRepository extends AbstractGemFireOperation
|
||||
* @see org.springframework.session.ExpiringSession
|
||||
*/
|
||||
public void save(ExpiringSession session) {
|
||||
getTemplate().put(session.getId(), new GemFireSession(session));
|
||||
getTemplate().put(session.getId(), GemFireSession.from(session));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,5 +149,4 @@ public class GemFireOperationsSessionRepository extends AbstractGemFireOperation
|
||||
public void delete(String sessionId) {
|
||||
handleDeleted(sessionId, getTemplate().<Object, ExpiringSession>remove(sessionId));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.gemstone.gemfire.cache.Cache;
|
||||
import com.gemstone.gemfire.cache.DataPolicy;
|
||||
import com.gemstone.gemfire.cache.GemFireCache;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.RegionShortcut;
|
||||
@@ -122,6 +123,19 @@ public abstract class GemFireUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given {@link Region} is a PROXY, which would be indicated by the {@link Region}
|
||||
* having a {@link DataPolicy} of {@link DataPolicy#EMPTY}.
|
||||
*
|
||||
* @param region {@link Region} to evaluate.
|
||||
* @return a boolean value indicating whether the {@link Region} is a PROXY.
|
||||
* @see com.gemstone.gemfire.cache.DataPolicy
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
*/
|
||||
public static boolean isProxy(Region<?, ?> region) {
|
||||
return DataPolicy.EMPTY.equals(region.getAttributes().getDataPolicy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the peer {@link RegionShortcut} is a proxy-based shortcut. NOTE:
|
||||
* "proxy"-based Regions keep no local state.
|
||||
@@ -153,5 +167,4 @@ public abstract class GemFireUtils {
|
||||
public static String toRegionPath(String regionName) {
|
||||
return String.format("%1$s%2$s", Region.SEPARATOR, regionName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ public class MongoExpiringSession implements ExpiringSession {
|
||||
}
|
||||
|
||||
public boolean isExpired() {
|
||||
return new Date().after(this.expireAt);
|
||||
return this.interval >= 0 && new Date().after(this.expireAt);
|
||||
}
|
||||
|
||||
public Date getExpireAt() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -66,7 +66,11 @@ public class MongoOperationsSessionRepository
|
||||
}
|
||||
|
||||
public MongoExpiringSession createSession() {
|
||||
return new MongoExpiringSession(this.maxInactiveIntervalInSeconds);
|
||||
MongoExpiringSession session = new MongoExpiringSession();
|
||||
if (this.maxInactiveIntervalInSeconds != null) {
|
||||
session.setMaxInactiveIntervalInSeconds(this.maxInactiveIntervalInSeconds);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
public void save(MongoExpiringSession session) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -277,7 +277,7 @@ public class RedisOperationsSessionRepository implements
|
||||
static final String LAST_ACCESSED_ATTR = "lastAccessedTime";
|
||||
|
||||
/**
|
||||
* The prefix of the key for used for session attributes. The suffix is the name of
|
||||
* The prefix of the key used for session attributes. The suffix is the name of
|
||||
* the session attribute. For example, if the session contained an attribute named
|
||||
* attributeName, then there would be an entry in the hash named
|
||||
* sessionAttr:attributeName that mapped to its value.
|
||||
@@ -518,6 +518,11 @@ public class RedisOperationsSessionRepository implements
|
||||
|
||||
RedisSession session = getSession(sessionId, true);
|
||||
|
||||
if (session == null) {
|
||||
logger.warn("Unable to publish SessionDestroyedEvent for session "
|
||||
+ sessionId);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Publishing SessionDestroyedEvent for session " + sessionId);
|
||||
}
|
||||
@@ -525,10 +530,10 @@ public class RedisOperationsSessionRepository implements
|
||||
cleanupPrincipalIndex(session);
|
||||
|
||||
if (isDeleted) {
|
||||
handleDeleted(sessionId, session);
|
||||
handleDeleted(session);
|
||||
}
|
||||
else {
|
||||
handleExpired(sessionId, session);
|
||||
handleExpired(session);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -536,9 +541,6 @@ public class RedisOperationsSessionRepository implements
|
||||
}
|
||||
|
||||
private void cleanupPrincipalIndex(RedisSession session) {
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
String sessionId = session.getId();
|
||||
String principal = PRINCIPAL_NAME_RESOLVER.resolvePrincipal(session);
|
||||
if (principal != null) {
|
||||
@@ -553,22 +555,12 @@ public class RedisOperationsSessionRepository implements
|
||||
publishEvent(new SessionCreatedEvent(this, session));
|
||||
}
|
||||
|
||||
private void handleDeleted(String sessionId, RedisSession session) {
|
||||
if (session == null) {
|
||||
publishEvent(new SessionDeletedEvent(this, sessionId));
|
||||
}
|
||||
else {
|
||||
publishEvent(new SessionDeletedEvent(this, session));
|
||||
}
|
||||
private void handleDeleted(RedisSession session) {
|
||||
publishEvent(new SessionDeletedEvent(this, session));
|
||||
}
|
||||
|
||||
private void handleExpired(String sessionId, RedisSession session) {
|
||||
if (session == null) {
|
||||
publishEvent(new SessionExpiredEvent(this, sessionId));
|
||||
}
|
||||
else {
|
||||
publishEvent(new SessionExpiredEvent(this, session));
|
||||
}
|
||||
private void handleExpired(RedisSession session) {
|
||||
publishEvent(new SessionExpiredEvent(this, session));
|
||||
}
|
||||
|
||||
private void publishEvent(ApplicationEvent event) {
|
||||
@@ -694,7 +686,7 @@ public class RedisOperationsSessionRepository implements
|
||||
* was retrieved. Cannot be null.
|
||||
*/
|
||||
RedisSession(MapSession cached) {
|
||||
Assert.notNull("MapSession cannot be null");
|
||||
Assert.notNull(cached, "MapSession cannot be null");
|
||||
this.cached = cached;
|
||||
this.originalPrincipalName = PRINCIPAL_NAME_RESOLVER.resolvePrincipal(this);
|
||||
}
|
||||
|
||||
@@ -80,15 +80,23 @@ final class RedisSessionExpirationPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
long sessionExpireInSeconds = session.getMaxInactiveIntervalInSeconds();
|
||||
String sessionKey = getSessionKey(keyToExpire);
|
||||
|
||||
if (sessionExpireInSeconds < 0) {
|
||||
this.redis.boundValueOps(sessionKey).append("");
|
||||
this.redis.boundValueOps(sessionKey).persist();
|
||||
this.redis.boundHashOps(getSessionKey(session.getId())).persist();
|
||||
return;
|
||||
}
|
||||
|
||||
String expireKey = getExpirationKey(toExpire);
|
||||
BoundSetOperations<Object, Object> expireOperations = this.redis
|
||||
.boundSetOps(expireKey);
|
||||
expireOperations.add(keyToExpire);
|
||||
|
||||
long sessionExpireInSeconds = session.getMaxInactiveIntervalInSeconds();
|
||||
long fiveMinutesAfterExpires = sessionExpireInSeconds
|
||||
+ TimeUnit.MINUTES.toSeconds(5);
|
||||
String sessionKey = getSessionKey(keyToExpire);
|
||||
|
||||
expireOperations.expire(fiveMinutesAfterExpires, TimeUnit.SECONDS);
|
||||
if (sessionExpireInSeconds == 0) {
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.springframework.session.SessionRepository;
|
||||
|
||||
/**
|
||||
* For {@link SessionRepository} implementations that support it, this event is fired when
|
||||
* a {@link Session} is destroyed either explicitly or via expiration.
|
||||
* a {@link Session} is created.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 1.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,8 @@ import javax.annotation.PreDestroy;
|
||||
|
||||
import com.hazelcast.core.EntryEvent;
|
||||
import com.hazelcast.core.IMap;
|
||||
import com.hazelcast.map.AbstractEntryProcessor;
|
||||
import com.hazelcast.map.EntryProcessor;
|
||||
import com.hazelcast.map.listener.EntryAddedListener;
|
||||
import com.hazelcast.map.listener.EntryEvictedListener;
|
||||
import com.hazelcast.map.listener.EntryRemovedListener;
|
||||
@@ -108,8 +110,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class HazelcastSessionRepository implements
|
||||
FindByIndexNameSessionRepository<HazelcastSessionRepository.HazelcastSession>,
|
||||
EntryAddedListener<String, MapSession>,
|
||||
EntryEvictedListener<String, MapSession>,
|
||||
EntryAddedListener<String, MapSession>, EntryEvictedListener<String, MapSession>,
|
||||
EntryRemovedListener<String, MapSession> {
|
||||
|
||||
/**
|
||||
@@ -200,11 +201,16 @@ public class HazelcastSessionRepository implements
|
||||
}
|
||||
|
||||
public void save(HazelcastSession session) {
|
||||
if (session.isChanged()) {
|
||||
this.sessions.put(session.getId(), session.getDelegate(),
|
||||
if (session.isNew) {
|
||||
this.sessions.set(session.getId(), session.getDelegate(),
|
||||
session.getMaxInactiveIntervalInSeconds(), TimeUnit.SECONDS);
|
||||
session.markUnchanged();
|
||||
}
|
||||
else if (session.changed) {
|
||||
this.sessions.executeOnKey(session.getId(),
|
||||
new SessionUpdateEntryProcessor(session.getLastAccessedTime(),
|
||||
session.getMaxInactiveIntervalInSeconds(), session.delta));
|
||||
}
|
||||
session.clearFlags();
|
||||
}
|
||||
|
||||
public HazelcastSession getSession(String id) {
|
||||
@@ -223,13 +229,13 @@ public class HazelcastSessionRepository implements
|
||||
this.sessions.remove(id);
|
||||
}
|
||||
|
||||
public Map<String, HazelcastSession> findByIndexNameAndIndexValue(
|
||||
String indexName, String indexValue) {
|
||||
public Map<String, HazelcastSession> findByIndexNameAndIndexValue(String indexName,
|
||||
String indexValue) {
|
||||
if (!PRINCIPAL_NAME_INDEX_NAME.equals(indexName)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Collection<MapSession> sessions = this.sessions.values(
|
||||
Predicates.equal(PRINCIPAL_NAME_ATTRIBUTE, indexValue));
|
||||
Collection<MapSession> sessions = this.sessions
|
||||
.values(Predicates.equal(PRINCIPAL_NAME_ATTRIBUTE, indexValue));
|
||||
Map<String, HazelcastSession> sessionMap = new HashMap<String, HazelcastSession>(
|
||||
sessions.size());
|
||||
for (MapSession session : sessions) {
|
||||
@@ -270,15 +276,20 @@ public class HazelcastSessionRepository implements
|
||||
final class HazelcastSession implements ExpiringSession {
|
||||
|
||||
private final MapSession delegate;
|
||||
|
||||
private boolean isNew;
|
||||
|
||||
private boolean changed;
|
||||
|
||||
private Map<String, Object> delta = new HashMap<String, Object>();
|
||||
|
||||
/**
|
||||
* Creates a new instance ensuring to mark all of the new attributes to be
|
||||
* persisted in the next save operation.
|
||||
*/
|
||||
HazelcastSession() {
|
||||
this(new MapSession());
|
||||
this.changed = true;
|
||||
this.isNew = true;
|
||||
flushImmediateIfNecessary();
|
||||
}
|
||||
|
||||
@@ -334,28 +345,28 @@ public class HazelcastSessionRepository implements
|
||||
|
||||
public void setAttribute(String attributeName, Object attributeValue) {
|
||||
this.delegate.setAttribute(attributeName, attributeValue);
|
||||
this.delta.put(attributeName, attributeValue);
|
||||
this.changed = true;
|
||||
flushImmediateIfNecessary();
|
||||
}
|
||||
|
||||
public void removeAttribute(String attributeName) {
|
||||
this.delegate.removeAttribute(attributeName);
|
||||
this.delta.put(attributeName, null);
|
||||
this.changed = true;
|
||||
flushImmediateIfNecessary();
|
||||
}
|
||||
|
||||
boolean isChanged() {
|
||||
return this.changed;
|
||||
}
|
||||
|
||||
void markUnchanged() {
|
||||
this.changed = false;
|
||||
}
|
||||
|
||||
MapSession getDelegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
void clearFlags() {
|
||||
this.isNew = false;
|
||||
this.changed = false;
|
||||
this.delta.clear();
|
||||
}
|
||||
|
||||
private void flushImmediateIfNecessary() {
|
||||
if (HazelcastSessionRepository.this.hazelcastFlushMode == HazelcastFlushMode.IMMEDIATE) {
|
||||
HazelcastSessionRepository.this.save(this);
|
||||
@@ -364,4 +375,44 @@ public class HazelcastSessionRepository implements
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Hazelcast {@link EntryProcessor} responsible for handling updates to session.
|
||||
*
|
||||
* @since 1.3.2
|
||||
* @see #save(HazelcastSession)
|
||||
*/
|
||||
private static final class SessionUpdateEntryProcessor
|
||||
extends AbstractEntryProcessor<String, MapSession> {
|
||||
|
||||
private final long lastAccessedTime;
|
||||
|
||||
private final int maxInactiveIntervalInSeconds;
|
||||
|
||||
private final Map<String, Object> delta;
|
||||
|
||||
SessionUpdateEntryProcessor(long lastAccessedTime,
|
||||
int maxInactiveIntervalInSeconds, Map<String, Object> delta) {
|
||||
this.lastAccessedTime = lastAccessedTime;
|
||||
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
|
||||
this.delta = delta;
|
||||
}
|
||||
|
||||
public Object process(Map.Entry<String, MapSession> entry) {
|
||||
MapSession value = entry.getValue();
|
||||
value.setLastAccessedTime(this.lastAccessedTime);
|
||||
value.setMaxInactiveIntervalInSeconds(this.maxInactiveIntervalInSeconds);
|
||||
for (final Map.Entry<String, Object> attribute : this.delta.entrySet()) {
|
||||
if (attribute.getValue() != null) {
|
||||
value.setAttribute(attribute.getKey(), attribute.getValue());
|
||||
}
|
||||
else {
|
||||
value.removeAttribute(attribute.getKey());
|
||||
}
|
||||
}
|
||||
entry.setValue(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -105,6 +105,7 @@ import org.springframework.util.StringUtils;
|
||||
* );
|
||||
*
|
||||
* CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
|
||||
* CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
*
|
||||
* CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
* SESSION_ID CHAR(36),
|
||||
@@ -176,7 +177,7 @@ public class JdbcOperationsSessionRepository implements
|
||||
|
||||
private static final String DELETE_SESSIONS_BY_LAST_ACCESS_TIME_QUERY =
|
||||
"DELETE FROM %TABLE_NAME% " +
|
||||
"WHERE LAST_ACCESS_TIME < ? - MAX_INACTIVE_INTERVAL * 1000";
|
||||
"WHERE MAX_INACTIVE_INTERVAL < (? - LAST_ACCESS_TIME) / 1000";
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(JdbcOperationsSessionRepository.class);
|
||||
@@ -658,7 +659,7 @@ public class JdbcOperationsSessionRepository implements
|
||||
}
|
||||
|
||||
JdbcSession(ExpiringSession delegate) {
|
||||
Assert.notNull("ExpiringSession cannot be null");
|
||||
Assert.notNull(delegate, "ExpiringSession cannot be null");
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.session.jdbc.config.annotation.web.http;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
@@ -36,8 +35,6 @@ import org.springframework.core.serializer.support.SerializingConverter;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
import org.springframework.jdbc.support.MetaDataAccessException;
|
||||
import org.springframework.jdbc.support.lob.LobHandler;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
|
||||
@@ -88,19 +85,14 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration
|
||||
|
||||
@Bean
|
||||
public JdbcOperationsSessionRepository sessionRepository(
|
||||
@Qualifier("springSessionJdbcOperations") JdbcTemplate jdbcTemplate,
|
||||
@Qualifier("springSessionJdbcOperations") JdbcOperations jdbcOperations,
|
||||
PlatformTransactionManager transactionManager) {
|
||||
JdbcOperationsSessionRepository sessionRepository =
|
||||
new JdbcOperationsSessionRepository(jdbcTemplate, transactionManager);
|
||||
new JdbcOperationsSessionRepository(jdbcOperations, transactionManager);
|
||||
String tableName = getTableName();
|
||||
if (StringUtils.hasText(tableName)) {
|
||||
sessionRepository.setTableName(tableName);
|
||||
}
|
||||
String databaseName = getDatabaseName(jdbcTemplate.getDataSource());
|
||||
if (Arrays.asList("Apache Derby", "H2").contains(databaseName)) {
|
||||
sessionRepository.setDeleteSessionsByLastAccessTimeQuery("DELETE FROM " + tableName +
|
||||
" WHERE LAST_ACCESS_TIME < ? - CAST(MAX_INACTIVE_INTERVAL AS BIGINT) * 1000");
|
||||
}
|
||||
sessionRepository
|
||||
.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
|
||||
if (this.lobHandler != null) {
|
||||
@@ -163,17 +155,6 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration
|
||||
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
|
||||
}
|
||||
|
||||
private String getDatabaseName(DataSource dataSource) {
|
||||
try {
|
||||
String databaseProductName = JdbcUtils.extractDatabaseMetaData(dataSource,
|
||||
"getDatabaseProductName").toString();
|
||||
return JdbcUtils.commonDatabaseName(databaseProductName);
|
||||
}
|
||||
catch (MetaDataAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getTableName() {
|
||||
String systemProperty = System.getProperty("spring.session.jdbc.tableName", "");
|
||||
if (StringUtils.hasText(systemProperty)) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -57,6 +58,8 @@ public class SpringSessionRememberMeServices
|
||||
|
||||
private int validitySeconds = THIRTY_DAYS_SECONDS;
|
||||
|
||||
private String sessionAttrToDeleteOnLoginFail = HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY;
|
||||
|
||||
public final Authentication autoLogin(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return null;
|
||||
@@ -132,7 +135,7 @@ public class SpringSessionRememberMeServices
|
||||
logger.debug("Interactive login attempt was unsuccessful.");
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
session.invalidate();
|
||||
session.removeAttribute(this.sessionAttrToDeleteOnLoginFail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -250,18 +250,18 @@ public final class CookieHttpSessionStrategy
|
||||
return sessionIds.values().iterator().next();
|
||||
}
|
||||
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<String, String> entry : sessionIds.entrySet()) {
|
||||
String alias = entry.getKey();
|
||||
String id = entry.getValue();
|
||||
|
||||
buffer.append(alias);
|
||||
buffer.append(this.serializationDelimiter);
|
||||
buffer.append(id);
|
||||
buffer.append(this.serializationDelimiter);
|
||||
sb.append(alias);
|
||||
sb.append(this.serializationDelimiter);
|
||||
sb.append(id);
|
||||
sb.append(this.serializationDelimiter);
|
||||
}
|
||||
buffer.deleteCharAt(buffer.length() - 1);
|
||||
return buffer.toString();
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void onInvalidateSession(HttpServletRequest request,
|
||||
|
||||
@@ -226,9 +226,6 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
|
||||
onResponseCommitted();
|
||||
disableOnResponseCommitted();
|
||||
}
|
||||
else if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Skip invoking on");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -289,9 +289,10 @@ public class SessionRepositoryFilter<S extends ExpiringSession>
|
||||
setCurrentSession(null);
|
||||
|
||||
HttpSessionWrapper newSession = getSession();
|
||||
int originalMaxInactiveInterval = session.getMaxInactiveInterval();
|
||||
original.setSession(newSession.getSession());
|
||||
|
||||
newSession.setMaxInactiveInterval(session.getMaxInactiveInterval());
|
||||
newSession.setMaxInactiveInterval(originalMaxInactiveInterval);
|
||||
for (Map.Entry<String, Object> attr : attrs.entrySet()) {
|
||||
String attrName = attr.getKey();
|
||||
Object attrValue = attr.getValue();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CREATE TABLE SPRING_SESSION (
|
||||
SESSION_ID CHAR(36),
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
CREATION_TIME BIGINT NOT NULL,
|
||||
LAST_ACCESS_TIME BIGINT NOT NULL,
|
||||
MAX_INACTIVE_INTERVAL INT NOT NULL,
|
||||
@@ -8,11 +8,12 @@ CREATE TABLE SPRING_SESSION (
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
|
||||
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
|
||||
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
SESSION_ID CHAR(36),
|
||||
ATTRIBUTE_NAME VARCHAR(200),
|
||||
ATTRIBUTE_BYTES BLOB,
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
|
||||
ATTRIBUTE_BYTES BLOB NOT NULL,
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CREATE TABLE SPRING_SESSION (
|
||||
SESSION_ID CHAR(36),
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
CREATION_TIME BIGINT NOT NULL,
|
||||
LAST_ACCESS_TIME BIGINT NOT NULL,
|
||||
MAX_INACTIVE_INTERVAL INT NOT NULL,
|
||||
@@ -8,11 +8,12 @@ CREATE TABLE SPRING_SESSION (
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
|
||||
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
|
||||
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
SESSION_ID CHAR(36),
|
||||
ATTRIBUTE_NAME VARCHAR(200),
|
||||
ATTRIBUTE_BYTES BLOB,
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
|
||||
ATTRIBUTE_BYTES BLOB NOT NULL,
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CREATE TABLE SPRING_SESSION (
|
||||
SESSION_ID CHAR(36),
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
CREATION_TIME BIGINT NOT NULL,
|
||||
LAST_ACCESS_TIME BIGINT NOT NULL,
|
||||
MAX_INACTIVE_INTERVAL INT NOT NULL,
|
||||
@@ -8,11 +8,12 @@ CREATE TABLE SPRING_SESSION (
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
|
||||
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
|
||||
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
SESSION_ID CHAR(36),
|
||||
ATTRIBUTE_NAME VARCHAR(200),
|
||||
ATTRIBUTE_BYTES LONGVARBINARY,
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
|
||||
ATTRIBUTE_BYTES LONGVARBINARY NOT NULL,
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CREATE TABLE SPRING_SESSION (
|
||||
SESSION_ID CHAR(36),
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
CREATION_TIME BIGINT NOT NULL,
|
||||
LAST_ACCESS_TIME BIGINT NOT NULL,
|
||||
MAX_INACTIVE_INTERVAL INT NOT NULL,
|
||||
@@ -8,11 +8,12 @@ CREATE TABLE SPRING_SESSION (
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
|
||||
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
|
||||
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
SESSION_ID CHAR(36),
|
||||
ATTRIBUTE_NAME VARCHAR(200),
|
||||
ATTRIBUTE_BYTES LONGVARBINARY,
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
|
||||
ATTRIBUTE_BYTES LONGVARBINARY NOT NULL,
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CREATE TABLE SPRING_SESSION (
|
||||
SESSION_ID CHAR(36),
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
CREATION_TIME BIGINT NOT NULL,
|
||||
LAST_ACCESS_TIME BIGINT NOT NULL,
|
||||
MAX_INACTIVE_INTERVAL INT NOT NULL,
|
||||
@@ -8,11 +8,12 @@ CREATE TABLE SPRING_SESSION (
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
|
||||
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
|
||||
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
SESSION_ID CHAR(36),
|
||||
ATTRIBUTE_NAME VARCHAR(200),
|
||||
ATTRIBUTE_BYTES BLOB,
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
|
||||
ATTRIBUTE_BYTES BLOB NOT NULL,
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CREATE TABLE SPRING_SESSION (
|
||||
SESSION_ID CHAR(36),
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
CREATION_TIME NUMBER(19,0) NOT NULL,
|
||||
LAST_ACCESS_TIME NUMBER(19,0) NOT NULL,
|
||||
MAX_INACTIVE_INTERVAL NUMBER(10,0) NOT NULL,
|
||||
@@ -8,11 +8,12 @@ CREATE TABLE SPRING_SESSION (
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
|
||||
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
|
||||
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
SESSION_ID CHAR(36),
|
||||
ATTRIBUTE_NAME VARCHAR2(200 CHAR),
|
||||
ATTRIBUTE_BYTES BLOB,
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
ATTRIBUTE_NAME VARCHAR2(200 CHAR) NOT NULL,
|
||||
ATTRIBUTE_BYTES BLOB NOT NULL,
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CREATE TABLE SPRING_SESSION (
|
||||
SESSION_ID CHAR(36),
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
CREATION_TIME BIGINT NOT NULL,
|
||||
LAST_ACCESS_TIME BIGINT NOT NULL,
|
||||
MAX_INACTIVE_INTERVAL INT NOT NULL,
|
||||
@@ -8,11 +8,12 @@ CREATE TABLE SPRING_SESSION (
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
|
||||
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
|
||||
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
SESSION_ID CHAR(36),
|
||||
ATTRIBUTE_NAME VARCHAR(200),
|
||||
ATTRIBUTE_BYTES BYTEA,
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
|
||||
ATTRIBUTE_BYTES BYTEA NOT NULL,
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CREATE TABLE SPRING_SESSION (
|
||||
SESSION_ID CHARACTER(36),
|
||||
SESSION_ID CHARACTER(36) NOT NULL,
|
||||
CREATION_TIME INTEGER NOT NULL,
|
||||
LAST_ACCESS_TIME INTEGER NOT NULL,
|
||||
MAX_INACTIVE_INTERVAL INTEGER NOT NULL,
|
||||
@@ -8,11 +8,12 @@ CREATE TABLE SPRING_SESSION (
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
|
||||
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
|
||||
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
SESSION_ID CHAR(36),
|
||||
ATTRIBUTE_NAME VARCHAR(200),
|
||||
ATTRIBUTE_BYTES BLOB,
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
|
||||
ATTRIBUTE_BYTES BLOB NOT NULL,
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CREATE TABLE SPRING_SESSION (
|
||||
SESSION_ID CHAR(36),
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
CREATION_TIME BIGINT NOT NULL,
|
||||
LAST_ACCESS_TIME BIGINT NOT NULL,
|
||||
MAX_INACTIVE_INTERVAL INT NOT NULL,
|
||||
@@ -8,11 +8,12 @@ CREATE TABLE SPRING_SESSION (
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
|
||||
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
|
||||
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
SESSION_ID CHAR(36),
|
||||
ATTRIBUTE_NAME VARCHAR(200),
|
||||
ATTRIBUTE_BYTES IMAGE,
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
|
||||
ATTRIBUTE_BYTES IMAGE NOT NULL,
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CREATE TABLE SPRING_SESSION (
|
||||
SESSION_ID CHAR(36),
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
CREATION_TIME BIGINT NOT NULL,
|
||||
LAST_ACCESS_TIME BIGINT NOT NULL,
|
||||
MAX_INACTIVE_INTERVAL INT NOT NULL,
|
||||
@@ -8,11 +8,12 @@ CREATE TABLE SPRING_SESSION (
|
||||
) LOCK DATAROWS;
|
||||
|
||||
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
|
||||
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (PRINCIPAL_NAME);
|
||||
|
||||
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
SESSION_ID CHAR(36),
|
||||
ATTRIBUTE_NAME VARCHAR(200),
|
||||
ATTRIBUTE_BYTES IMAGE,
|
||||
SESSION_ID CHAR(36) NOT NULL,
|
||||
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
|
||||
ATTRIBUTE_BYTES IMAGE NOT NULL,
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
|
||||
) LOCK DATAROWS;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import com.gemstone.gemfire.cache.AttributesMutator;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.query.SelectResults;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -89,32 +90,23 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
given(this.mockRegion.getAttributesMutator())
|
||||
.willReturn(this.mockAttributesMutator);
|
||||
given(this.mockRegion.getAttributesMutator()).willReturn(this.mockAttributesMutator);
|
||||
given(this.mockRegion.getFullPath()).willReturn("/Example");
|
||||
given(this.mockTemplate.<Object, ExpiringSession>getRegion())
|
||||
.willReturn(this.mockRegion);
|
||||
given(this.mockTemplate.<Object, ExpiringSession>getRegion()).willReturn(this.mockRegion);
|
||||
|
||||
this.sessionRepository = new GemFireOperationsSessionRepository(
|
||||
this.mockTemplate);
|
||||
this.sessionRepository
|
||||
.setApplicationEventPublisher(this.mockApplicationEventPublisher);
|
||||
this.sessionRepository
|
||||
.setMaxInactiveIntervalInSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
this.sessionRepository = new GemFireOperationsSessionRepository(this.mockTemplate);
|
||||
this.sessionRepository.setApplicationEventPublisher(this.mockApplicationEventPublisher);
|
||||
this.sessionRepository.setMaxInactiveIntervalInSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
this.sessionRepository.afterPropertiesSet();
|
||||
|
||||
assertThat(this.sessionRepository.getApplicationEventPublisher())
|
||||
.isSameAs(this.mockApplicationEventPublisher);
|
||||
assertThat(this.sessionRepository.getFullyQualifiedRegionName())
|
||||
.isEqualTo("/Example");
|
||||
assertThat(this.sessionRepository.getMaxInactiveIntervalInSeconds())
|
||||
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
assertThat(this.sessionRepository.getApplicationEventPublisher()).isSameAs(this.mockApplicationEventPublisher);
|
||||
assertThat(this.sessionRepository.getFullyQualifiedRegionName()).isEqualTo("/Example");
|
||||
assertThat(this.sessionRepository.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
verify(this.mockAttributesMutator, times(1))
|
||||
.addCacheListener(same(this.sessionRepository));
|
||||
verify(this.mockAttributesMutator, times(1)).addCacheListener(same(this.sessionRepository));
|
||||
verify(this.mockRegion, times(1)).getFullPath();
|
||||
verify(this.mockTemplate, times(1)).getRegion();
|
||||
}
|
||||
@@ -128,21 +120,18 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
|
||||
SelectResults<Object> mockSelectResults = mock(SelectResults.class);
|
||||
|
||||
given(mockSelectResults.asList())
|
||||
.willReturn(Collections.<Object>singletonList(mockSession));
|
||||
given(mockSelectResults.asList()).willReturn(Collections.<Object>singletonList(mockSession));
|
||||
|
||||
String indexName = "vip";
|
||||
String indexValue = "rwinch";
|
||||
|
||||
String expectedQql = String.format(
|
||||
GemFireOperationsSessionRepository.FIND_SESSIONS_BY_INDEX_NAME_VALUE_QUERY,
|
||||
this.sessionRepository.getFullyQualifiedRegionName(), indexName);
|
||||
String expectedQql = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_INDEX_NAME_VALUE_QUERY,
|
||||
this.sessionRepository.getFullyQualifiedRegionName(), indexName);
|
||||
|
||||
given(this.mockTemplate.find(eq(expectedQql), eq(indexValue)))
|
||||
.willReturn(mockSelectResults);
|
||||
given(this.mockTemplate.find(eq(expectedQql), eq(indexValue))).willReturn(mockSelectResults);
|
||||
|
||||
Map<String, ExpiringSession> sessions = this.sessionRepository
|
||||
.findByIndexNameAndIndexValue(indexName, indexValue);
|
||||
Map<String, ExpiringSession> sessions =
|
||||
this.sessionRepository.findByIndexNameAndIndexValue(indexName, indexValue);
|
||||
|
||||
assertThat(sessions).isNotNull();
|
||||
assertThat(sessions.size()).isEqualTo(1);
|
||||
@@ -158,8 +147,7 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
public void findByPrincipalNameFindsMatchingSessions() throws Exception {
|
||||
ExpiringSession mockSessionOne = mock(ExpiringSession.class, "MockSessionOne");
|
||||
ExpiringSession mockSessionTwo = mock(ExpiringSession.class, "MockSessionTwo");
|
||||
ExpiringSession mockSessionThree = mock(ExpiringSession.class,
|
||||
"MockSessionThree");
|
||||
ExpiringSession mockSessionThree = mock(ExpiringSession.class, "MockSessionThree");
|
||||
|
||||
given(mockSessionOne.getId()).willReturn("1");
|
||||
given(mockSessionTwo.getId()).willReturn("2");
|
||||
@@ -167,22 +155,18 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
|
||||
SelectResults<Object> mockSelectResults = mock(SelectResults.class);
|
||||
|
||||
given(mockSelectResults.asList()).willReturn(
|
||||
Arrays.<Object>asList(mockSessionOne, mockSessionTwo, mockSessionThree));
|
||||
given(mockSelectResults.asList())
|
||||
.willReturn(Arrays.<Object>asList(mockSessionOne, mockSessionTwo, mockSessionThree));
|
||||
|
||||
String principalName = "jblum";
|
||||
|
||||
String expectedOql = String.format(
|
||||
GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
|
||||
this.sessionRepository.getFullyQualifiedRegionName());
|
||||
String expectedOql = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
|
||||
this.sessionRepository.getFullyQualifiedRegionName());
|
||||
|
||||
given(this.mockTemplate.find(eq(expectedOql), eq(principalName)))
|
||||
.willReturn(mockSelectResults);
|
||||
given(this.mockTemplate.find(eq(expectedOql), eq(principalName))).willReturn(mockSelectResults);
|
||||
|
||||
Map<String, ExpiringSession> sessions = this.sessionRepository
|
||||
.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, ExpiringSession> sessions = this.sessionRepository.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
|
||||
|
||||
assertThat(sessions).isNotNull();
|
||||
assertThat(sessions.size()).isEqualTo(3);
|
||||
@@ -206,17 +190,13 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
|
||||
String principalName = "jblum";
|
||||
|
||||
String expectedOql = String.format(
|
||||
GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
|
||||
this.sessionRepository.getFullyQualifiedRegionName());
|
||||
String expectedOql = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
|
||||
this.sessionRepository.getFullyQualifiedRegionName());
|
||||
|
||||
given(this.mockTemplate.find(eq(expectedOql), eq(principalName)))
|
||||
.willReturn(mockSelectResults);
|
||||
given(this.mockTemplate.find(eq(expectedOql), eq(principalName))).willReturn(mockSelectResults);
|
||||
|
||||
Map<String, ExpiringSession> sessions = this.sessionRepository
|
||||
.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
principalName);
|
||||
Map<String, ExpiringSession> sessions = this.sessionRepository.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principalName);
|
||||
|
||||
assertThat(sessions).isNotNull();
|
||||
assertThat(sessions.isEmpty()).isTrue();
|
||||
@@ -227,11 +207,11 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
|
||||
@Test
|
||||
public void prepareQueryReturnsPrincipalNameOql() {
|
||||
String actualQql = this.sessionRepository
|
||||
.prepareQuery(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
|
||||
String expectedOql = String.format(
|
||||
GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
|
||||
this.sessionRepository.getFullyQualifiedRegionName());
|
||||
String actualQql =
|
||||
this.sessionRepository.prepareQuery(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
|
||||
|
||||
String expectedOql = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_PRINCIPAL_NAME_QUERY,
|
||||
this.sessionRepository.getFullyQualifiedRegionName());
|
||||
|
||||
assertThat(actualQql).isEqualTo(expectedOql);
|
||||
}
|
||||
@@ -240,29 +220,24 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
public void prepareQueryReturnsIndexNameValueOql() {
|
||||
String attributeName = "testAttributeName";
|
||||
String actualOql = this.sessionRepository.prepareQuery(attributeName);
|
||||
String expectedOql = String.format(
|
||||
GemFireOperationsSessionRepository.FIND_SESSIONS_BY_INDEX_NAME_VALUE_QUERY,
|
||||
this.sessionRepository.getFullyQualifiedRegionName(), attributeName);
|
||||
String expectedOql = String.format(GemFireOperationsSessionRepository.FIND_SESSIONS_BY_INDEX_NAME_VALUE_QUERY,
|
||||
this.sessionRepository.getFullyQualifiedRegionName(), attributeName);
|
||||
|
||||
assertThat(actualOql).isEqualTo(expectedOql);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createProperlyInitializedSession() {
|
||||
final long beforeOrAtCreationTime = System.currentTimeMillis();
|
||||
long beforeOrAtCreationTime = System.currentTimeMillis();
|
||||
|
||||
ExpiringSession session = this.sessionRepository.createSession();
|
||||
|
||||
assertThat(session).isInstanceOf(
|
||||
AbstractGemFireOperationsSessionRepository.GemFireSession.class);
|
||||
assertThat(session).isInstanceOf(AbstractGemFireOperationsSessionRepository.GemFireSession.class);
|
||||
assertThat(session.getId()).isNotNull();
|
||||
assertThat(session.getAttributeNames().isEmpty()).isTrue();
|
||||
assertThat(session.getCreationTime())
|
||||
.isGreaterThanOrEqualTo(beforeOrAtCreationTime);
|
||||
assertThat(session.getLastAccessedTime())
|
||||
.isGreaterThanOrEqualTo(beforeOrAtCreationTime);
|
||||
assertThat(session.getMaxInactiveIntervalInSeconds())
|
||||
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
assertThat(session.getCreationTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime);
|
||||
assertThat(session.getLastAccessedTime()).isGreaterThanOrEqualTo(beforeOrAtCreationTime);
|
||||
assertThat(session.getMaxInactiveIntervalInSeconds()).isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -277,23 +252,21 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
given(this.mockTemplate.remove(eq(expectedSessionId))).willReturn(mockSession);
|
||||
|
||||
willAnswer(new Answer<Void>() {
|
||||
public Void answer(final InvocationOnMock invocation) throws Throwable {
|
||||
ApplicationEvent applicationEvent = invocation.getArgumentAt(0,
|
||||
ApplicationEvent.class);
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
ApplicationEvent applicationEvent = invocation.getArgumentAt(0, ApplicationEvent.class);
|
||||
|
||||
assertThat(applicationEvent).isInstanceOf(SessionDeletedEvent.class);
|
||||
|
||||
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
|
||||
|
||||
assertThat(sessionEvent.getSource()).isSameAs(
|
||||
GemFireOperationsSessionRepositoryTest.this.sessionRepository);
|
||||
assertThat(sessionEvent.getSource())
|
||||
.isSameAs(GemFireOperationsSessionRepositoryTest.this.sessionRepository);
|
||||
assertThat(sessionEvent.getSession()).isSameAs(mockSession);
|
||||
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);
|
||||
|
||||
return null;
|
||||
}
|
||||
}).given(this.mockApplicationEventPublisher)
|
||||
.publishEvent(any(ApplicationEvent.class));
|
||||
}).given(this.mockApplicationEventPublisher).publishEvent(any(ApplicationEvent.class));
|
||||
|
||||
assertThat(this.sessionRepository.getSession(expectedSessionId)).isNull();
|
||||
|
||||
@@ -302,16 +275,15 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
verify(mockSession, times(1)).isExpired();
|
||||
verify(mockSession, times(2)).getId();
|
||||
verify(this.mockApplicationEventPublisher, times(1))
|
||||
.publishEvent(isA(SessionDeletedEvent.class));
|
||||
.publishEvent(isA(SessionDeletedEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSessionFindsMatchingNonExpiredSessionById() {
|
||||
final String expectedId = "1";
|
||||
String expectedId = "1";
|
||||
|
||||
final long expectedCreationTime = System.currentTimeMillis();
|
||||
final long currentLastAccessedTime = (expectedCreationTime
|
||||
+ TimeUnit.MINUTES.toMillis(5));
|
||||
long expectedCreationTime = System.currentTimeMillis();
|
||||
long currentLastAccessedTime = (expectedCreationTime + TimeUnit.MINUTES.toMillis(5));
|
||||
|
||||
ExpiringSession mockSession = mock(ExpiringSession.class);
|
||||
|
||||
@@ -319,8 +291,7 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
given(mockSession.getId()).willReturn(expectedId);
|
||||
given(mockSession.getCreationTime()).willReturn(expectedCreationTime);
|
||||
given(mockSession.getLastAccessedTime()).willReturn(currentLastAccessedTime);
|
||||
given(mockSession.getAttributeNames())
|
||||
.willReturn(Collections.singleton("attrOne"));
|
||||
given(mockSession.getAttributeNames()).willReturn(Collections.singleton("attrOne"));
|
||||
given(mockSession.getAttribute(eq("attrOne"))).willReturn("test");
|
||||
given(this.mockTemplate.get(eq(expectedId))).willReturn(mockSession);
|
||||
|
||||
@@ -329,14 +300,10 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
assertThat(actualSession).isNotSameAs(mockSession);
|
||||
assertThat(actualSession.getId()).isEqualTo(expectedId);
|
||||
assertThat(actualSession.getCreationTime()).isEqualTo(expectedCreationTime);
|
||||
assertThat(actualSession.getLastAccessedTime())
|
||||
.isNotEqualTo(currentLastAccessedTime);
|
||||
assertThat(actualSession.getLastAccessedTime())
|
||||
.isGreaterThanOrEqualTo(expectedCreationTime);
|
||||
assertThat(actualSession.getAttributeNames())
|
||||
.isEqualTo(Collections.singleton("attrOne"));
|
||||
assertThat(String.valueOf(actualSession.getAttribute("attrOne")))
|
||||
.isEqualTo("test");
|
||||
assertThat(actualSession.getLastAccessedTime()).isNotEqualTo(currentLastAccessedTime);
|
||||
assertThat(actualSession.getLastAccessedTime()).isGreaterThanOrEqualTo(expectedCreationTime);
|
||||
assertThat(actualSession.getAttributeNames()).isEqualTo(Collections.singleton("attrOne"));
|
||||
assertThat(String.valueOf(actualSession.getAttribute("attrOne"))).isEqualTo("test");
|
||||
|
||||
verify(this.mockTemplate, times(1)).get(eq(expectedId));
|
||||
verify(mockSession, times(1)).isExpired();
|
||||
@@ -358,8 +325,7 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
final String expectedSessionId = "1";
|
||||
|
||||
final long expectedCreationTime = System.currentTimeMillis();
|
||||
final long expectedLastAccessTime = (expectedCreationTime
|
||||
+ TimeUnit.MINUTES.toMillis(5));
|
||||
final long expectedLastAccessTime = (expectedCreationTime + TimeUnit.MINUTES.toMillis(5));
|
||||
|
||||
ExpiringSession mockSession = mock(ExpiringSession.class);
|
||||
|
||||
@@ -371,27 +337,22 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
given(mockSession.getAttributeNames()).willReturn(Collections.<String>emptySet());
|
||||
|
||||
given(this.mockTemplate.put(eq(expectedSessionId),
|
||||
isA(AbstractGemFireOperationsSessionRepository.GemFireSession.class)))
|
||||
.willAnswer(new Answer<ExpiringSession>() {
|
||||
public ExpiringSession answer(
|
||||
final InvocationOnMock invocation) throws Throwable {
|
||||
ExpiringSession session = invocation.getArgumentAt(1,
|
||||
ExpiringSession.class);
|
||||
isA(AbstractGemFireOperationsSessionRepository.GemFireSession.class)))
|
||||
.willAnswer(new Answer<ExpiringSession>() {
|
||||
public ExpiringSession answer(InvocationOnMock invocation) throws Throwable {
|
||||
ExpiringSession session = invocation.getArgumentAt(1, ExpiringSession.class);
|
||||
|
||||
assertThat(session).isNotNull();
|
||||
assertThat(session.getId()).isEqualTo(expectedSessionId);
|
||||
assertThat(session.getCreationTime())
|
||||
.isEqualTo(expectedCreationTime);
|
||||
assertThat(session.getLastAccessedTime())
|
||||
.isEqualTo(expectedLastAccessTime);
|
||||
assertThat(session.getMaxInactiveIntervalInSeconds())
|
||||
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
assertThat(session.getAttributeNames().isEmpty())
|
||||
.isTrue();
|
||||
assertThat(session).isNotNull();
|
||||
assertThat(session.getId()).isEqualTo(expectedSessionId);
|
||||
assertThat(session.getCreationTime()).isEqualTo(expectedCreationTime);
|
||||
assertThat(session.getLastAccessedTime()).isEqualTo(expectedLastAccessTime);
|
||||
assertThat(session.getMaxInactiveIntervalInSeconds())
|
||||
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
|
||||
assertThat(session.getAttributeNames().isEmpty()).isTrue();
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
this.sessionRepository.save(mockSession);
|
||||
|
||||
@@ -401,7 +362,7 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
verify(mockSession, times(1)).getMaxInactiveIntervalInSeconds();
|
||||
verify(mockSession, times(1)).getAttributeNames();
|
||||
verify(this.mockTemplate, times(1)).put(eq(expectedSessionId),
|
||||
isA(AbstractGemFireOperationsSessionRepository.GemFireSession.class));
|
||||
isA(AbstractGemFireOperationsSessionRepository.GemFireSession.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -415,29 +376,27 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
|
||||
willAnswer(new Answer<Void>() {
|
||||
public Void answer(final InvocationOnMock invocation) throws Throwable {
|
||||
ApplicationEvent applicationEvent = invocation.getArgumentAt(0,
|
||||
ApplicationEvent.class);
|
||||
ApplicationEvent applicationEvent = invocation.getArgumentAt(0, ApplicationEvent.class);
|
||||
|
||||
assertThat(applicationEvent).isInstanceOf(SessionDeletedEvent.class);
|
||||
|
||||
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
|
||||
|
||||
assertThat(sessionEvent.getSource()).isSameAs(
|
||||
GemFireOperationsSessionRepositoryTest.this.sessionRepository);
|
||||
assertThat(sessionEvent.getSource())
|
||||
.isSameAs(GemFireOperationsSessionRepositoryTest.this.sessionRepository);
|
||||
assertThat(sessionEvent.getSession()).isSameAs(mockSession);
|
||||
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);
|
||||
|
||||
return null;
|
||||
}
|
||||
}).given(this.mockApplicationEventPublisher)
|
||||
.publishEvent(isA(SessionDeletedEvent.class));
|
||||
}).given(this.mockApplicationEventPublisher).publishEvent(isA(SessionDeletedEvent.class));
|
||||
|
||||
this.sessionRepository.delete(expectedSessionId);
|
||||
|
||||
verify(mockSession, times(1)).getId();
|
||||
verify(this.mockTemplate, times(1)).remove(eq(expectedSessionId));
|
||||
verify(this.mockApplicationEventPublisher, times(1))
|
||||
.publishEvent(isA(SessionDeletedEvent.class));
|
||||
.publishEvent(isA(SessionDeletedEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -448,32 +407,29 @@ public class GemFireOperationsSessionRepositoryTest {
|
||||
|
||||
willAnswer(new Answer<Void>() {
|
||||
public Void answer(final InvocationOnMock invocation) throws Throwable {
|
||||
ApplicationEvent applicationEvent = invocation.getArgumentAt(0,
|
||||
ApplicationEvent.class);
|
||||
ApplicationEvent applicationEvent = invocation.getArgumentAt(0, ApplicationEvent.class);
|
||||
|
||||
assertThat(applicationEvent).isInstanceOf(SessionDeletedEvent.class);
|
||||
|
||||
AbstractSessionEvent sessionEvent = (AbstractSessionEvent) applicationEvent;
|
||||
|
||||
assertThat(sessionEvent.getSource()).isSameAs(
|
||||
GemFireOperationsSessionRepositoryTest.this.sessionRepository);
|
||||
assertThat(sessionEvent.getSource()).
|
||||
isSameAs(GemFireOperationsSessionRepositoryTest.this.sessionRepository);
|
||||
assertThat(sessionEvent.getSession()).isNull();
|
||||
assertThat(sessionEvent.getSessionId()).isEqualTo(expectedSessionId);
|
||||
|
||||
return null;
|
||||
}
|
||||
}).given(this.mockApplicationEventPublisher)
|
||||
.publishEvent(isA(SessionDeletedEvent.class));
|
||||
}).given(this.mockApplicationEventPublisher).publishEvent(isA(SessionDeletedEvent.class));
|
||||
|
||||
this.sessionRepository.delete(expectedSessionId);
|
||||
|
||||
verify(this.mockTemplate, times(1)).remove(eq(expectedSessionId));
|
||||
verify(this.mockApplicationEventPublisher, times(1))
|
||||
.publishEvent(isA(SessionDeletedEvent.class));
|
||||
.publishEvent(isA(SessionDeletedEvent.class));
|
||||
}
|
||||
|
||||
protected abstract class GemfireOperationsAccessor extends GemfireAccessor
|
||||
implements GemfireOperations {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,13 +20,18 @@ import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.gemstone.gemfire.cache.Cache;
|
||||
import com.gemstone.gemfire.cache.DataPolicy;
|
||||
import com.gemstone.gemfire.cache.GemFireCache;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.RegionAttributes;
|
||||
import com.gemstone.gemfire.cache.RegionShortcut;
|
||||
import com.gemstone.gemfire.cache.client.ClientCache;
|
||||
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.willThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -52,8 +57,7 @@ public class GemFireUtilsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void closeNonNullCloseableObjectThrowingIOExceptionReturnsFalse()
|
||||
throws IOException {
|
||||
public void closeNonNullCloseableObjectThrowingIOExceptionReturnsFalse() throws IOException {
|
||||
Closeable mockCloseable = mock(Closeable.class);
|
||||
willThrow(new IOException("test")).given(mockCloseable).close();
|
||||
assertThat(GemFireUtils.close(mockCloseable)).isFalse();
|
||||
@@ -101,17 +105,14 @@ public class GemFireUtilsTest {
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL_HEAP_LRU)).isTrue();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL_OVERFLOW)).isTrue();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL_PERSISTENT)).isTrue();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL_PERSISTENT_OVERFLOW))
|
||||
.isTrue();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.LOCAL_PERSISTENT_OVERFLOW)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clientRegionShortcutIsNotLocal() {
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.CACHING_PROXY)).isFalse();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU))
|
||||
.isFalse();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.CACHING_PROXY_OVERFLOW))
|
||||
.isFalse();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU)).isFalse();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.CACHING_PROXY_OVERFLOW)).isFalse();
|
||||
assertThat(GemFireUtils.isLocal(ClientRegionShortcut.PROXY)).isFalse();
|
||||
}
|
||||
|
||||
@@ -123,56 +124,72 @@ public class GemFireUtilsTest {
|
||||
@Test
|
||||
public void clientRegionShortcutIsNotProxy() {
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.CACHING_PROXY)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU))
|
||||
.isFalse();
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.CACHING_PROXY_OVERFLOW))
|
||||
.isFalse();
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.CACHING_PROXY_OVERFLOW)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.LOCAL)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.LOCAL_HEAP_LRU)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.LOCAL_OVERFLOW)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.LOCAL_PERSISTENT)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.LOCAL_PERSISTENT_OVERFLOW))
|
||||
.isFalse();
|
||||
assertThat(GemFireUtils.isProxy(ClientRegionShortcut.LOCAL_PERSISTENT_OVERFLOW)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regionShortcutIsProxy() {
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PROXY)).isTrue();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PROXY_REDUNDANT))
|
||||
.isTrue();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PROXY_REDUNDANT)).isTrue();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_PROXY)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regionIsProxy() {
|
||||
Region mockRegion = mock(Region.class);
|
||||
RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
given(mockRegion.getAttributes()).willReturn(mockRegionAttributes);
|
||||
given(mockRegionAttributes.getDataPolicy()).willReturn(DataPolicy.EMPTY);
|
||||
|
||||
assertThat(GemFireUtils.isProxy(mockRegion)).isTrue();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regionIsNotProxy() {
|
||||
Region mockRegion = mock(Region.class);
|
||||
RegionAttributes mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
given(mockRegion.getAttributes()).willReturn(mockRegionAttributes);
|
||||
given(mockRegionAttributes.getDataPolicy()).willReturn(DataPolicy.NORMAL);
|
||||
|
||||
assertThat(GemFireUtils.isProxy(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regionShortcutIsNotProxy() {
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL_HEAP_LRU)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL_OVERFLOW)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL_PERSISTENT)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL_PERSISTENT_OVERFLOW))
|
||||
.isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.LOCAL_PERSISTENT_OVERFLOW)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_HEAP_LRU)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_OVERFLOW)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_PERSISTENT)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_PERSISTENT_OVERFLOW))
|
||||
.isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.REPLICATE_PERSISTENT_OVERFLOW)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_HEAP_LRU)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_OVERFLOW)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PERSISTENT)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PERSISTENT_OVERFLOW))
|
||||
.isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_PERSISTENT_OVERFLOW)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT_HEAP_LRU))
|
||||
.isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT_OVERFLOW))
|
||||
.isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT))
|
||||
.isFalse();
|
||||
assertThat(GemFireUtils
|
||||
.isProxy(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW))
|
||||
.isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT_HEAP_LRU)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT_OVERFLOW)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT)).isFalse();
|
||||
assertThat(GemFireUtils.isProxy(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -183,5 +200,4 @@ public class GemFireUtilsTest {
|
||||
assertThat(GemFireUtils.toRegionPath("/")).isEqualTo("//");
|
||||
assertThat(GemFireUtils.toRegionPath("")).isEqualTo("/");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.session.data.mongo;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class MongoExpiringSessionTests {
|
||||
|
||||
@Test
|
||||
public void isExpiredWhenIntervalNegativeThenFalse() {
|
||||
MongoExpiringSession session = new MongoExpiringSession();
|
||||
session.setMaxInactiveIntervalInSeconds(-1);
|
||||
session.setLastAccessedTime(0L);
|
||||
|
||||
assertThat(session.isExpired()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.session.data.mongo;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -44,28 +45,44 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link MongoOperationsSessionRepository}.
|
||||
*
|
||||
* @author Jakub Kubrynski
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MongoOperationsSessionRepositoryTests {
|
||||
|
||||
@Mock
|
||||
MongoOperations mongoOperations;
|
||||
@Mock
|
||||
AbstractMongoSessionConverter converter;
|
||||
private MongoOperations mongoOperations;
|
||||
|
||||
MongoOperationsSessionRepository sut;
|
||||
@Mock
|
||||
private AbstractMongoSessionConverter converter;
|
||||
|
||||
private MongoOperationsSessionRepository repository;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.sut = new MongoOperationsSessionRepository(this.mongoOperations);
|
||||
this.sut.setMongoSessionConverter(this.converter);
|
||||
this.repository = new MongoOperationsSessionRepository(this.mongoOperations);
|
||||
this.repository.setMongoSessionConverter(this.converter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateSession() throws Exception {
|
||||
// when
|
||||
ExpiringSession session = this.sut.createSession();
|
||||
ExpiringSession session = this.repository.createSession();
|
||||
|
||||
// then
|
||||
assertThat(session.getId()).isNotEmpty();
|
||||
assertThat(session.getMaxInactiveIntervalInSeconds())
|
||||
.isEqualTo(MongoOperationsSessionRepository.DEFAULT_INACTIVE_INTERVAL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateSessionWhenMaxInactiveIntervalNotDefined() throws Exception {
|
||||
// when
|
||||
this.repository.setMaxInactiveIntervalInSeconds(null);
|
||||
ExpiringSession session = this.repository.createSession();
|
||||
|
||||
// then
|
||||
assertThat(session.getId()).isNotEmpty();
|
||||
@@ -87,7 +104,7 @@ public class MongoOperationsSessionRepositoryTests {
|
||||
.getCollection(MongoOperationsSessionRepository.DEFAULT_COLLECTION_NAME))
|
||||
.willReturn(collection);
|
||||
// when
|
||||
this.sut.save(session);
|
||||
this.repository.save(session);
|
||||
|
||||
// then
|
||||
verify(collection).save(dbSession);
|
||||
@@ -106,7 +123,7 @@ public class MongoOperationsSessionRepositoryTests {
|
||||
TypeDescriptor.valueOf(MongoExpiringSession.class))).willReturn(session);
|
||||
|
||||
// when
|
||||
ExpiringSession retrievedSession = this.sut.getSession(sessionId);
|
||||
ExpiringSession retrievedSession = this.repository.getSession(sessionId);
|
||||
|
||||
// then
|
||||
assertThat(retrievedSession).isEqualTo(session);
|
||||
@@ -127,7 +144,7 @@ public class MongoOperationsSessionRepositoryTests {
|
||||
TypeDescriptor.valueOf(MongoExpiringSession.class))).willReturn(session);
|
||||
|
||||
// when
|
||||
this.sut.getSession(sessionId);
|
||||
this.repository.getSession(sessionId);
|
||||
|
||||
// then
|
||||
verify(this.mongoOperations).remove(any(DBObject.class),
|
||||
@@ -140,7 +157,7 @@ public class MongoOperationsSessionRepositoryTests {
|
||||
String sessionId = UUID.randomUUID().toString();
|
||||
|
||||
// when
|
||||
this.sut.delete(sessionId);
|
||||
this.repository.delete(sessionId);
|
||||
|
||||
// then
|
||||
verify(this.mongoOperations).remove(any(DBObject.class),
|
||||
@@ -165,7 +182,7 @@ public class MongoOperationsSessionRepositoryTests {
|
||||
given(this.converter.convert(dbSession, TypeDescriptor.valueOf(DBObject.class),
|
||||
TypeDescriptor.valueOf(MongoExpiringSession.class))).willReturn(session);
|
||||
// when
|
||||
Map<String, MongoExpiringSession> sessionsMap = this.sut
|
||||
Map<String, MongoExpiringSession> sessionsMap = this.repository
|
||||
.findByIndexNameAndIndexValue(principalNameIndexName, "john");
|
||||
|
||||
// then
|
||||
@@ -179,7 +196,7 @@ public class MongoOperationsSessionRepositoryTests {
|
||||
String index = "some_not_supported_index_name";
|
||||
|
||||
// when
|
||||
Map<String, MongoExpiringSession> sessionsMap = this.sut
|
||||
Map<String, MongoExpiringSession> sessionsMap = this.repository
|
||||
.findByIndexNameAndIndexValue(index, "some_value");
|
||||
|
||||
// then
|
||||
|
||||
@@ -137,4 +137,36 @@ public class RedisSessionExpirationPolicyTests {
|
||||
verify(this.hashOperations).expire(this.session.getMaxInactiveIntervalInSeconds()
|
||||
+ TimeUnit.MINUTES.toSeconds(5), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onExpirationUpdatedDeleteOnZero() throws Exception {
|
||||
String sessionKey = this.policy.getSessionKey("expires:" + this.session.getId());
|
||||
|
||||
long originalExpirationTimeInMs = ONE_MINUTE_AGO;
|
||||
|
||||
this.session.setMaxInactiveIntervalInSeconds(0);
|
||||
|
||||
this.policy.onExpirationUpdated(originalExpirationTimeInMs, this.session);
|
||||
|
||||
// verify the original is removed
|
||||
verify(this.setOperations).remove("expires:" + this.session.getId());
|
||||
verify(this.setOperations).add("expires:" + this.session.getId());
|
||||
verify(this.sessionRedisOperations).delete(sessionKey);
|
||||
verify(this.setOperations).expire(this.session.getMaxInactiveIntervalInSeconds()
|
||||
+ TimeUnit.MINUTES.toSeconds(5), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onExpirationUpdatedPersistOnNegativeExpiration() throws Exception {
|
||||
long originalExpirationTimeInMs = ONE_MINUTE_AGO;
|
||||
|
||||
this.session.setMaxInactiveIntervalInSeconds(-1);
|
||||
|
||||
this.policy.onExpirationUpdated(originalExpirationTimeInMs, this.session);
|
||||
|
||||
verify(this.setOperations).remove("expires:" + this.session.getId());
|
||||
verify(this.valueOperations).append("");
|
||||
verify(this.valueOperations).persist();
|
||||
verify(this.hashOperations).persist();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,7 @@ import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.hazelcast.core.IMap;
|
||||
import com.hazelcast.map.EntryProcessor;
|
||||
import com.hazelcast.query.impl.predicates.EqualPredicate;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -40,6 +41,7 @@ import org.springframework.session.hazelcast.HazelcastSessionRepository.Hazelcas
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.isA;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -104,8 +106,8 @@ public class HazelcastSessionRepositoryTests {
|
||||
verifyZeroInteractions(this.sessions);
|
||||
|
||||
this.repository.save(session);
|
||||
verify(this.sessions, times(1)).put(eq(session.getId()), eq(session.getDelegate()),
|
||||
isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).set(eq(session.getId()),
|
||||
eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -113,8 +115,8 @@ public class HazelcastSessionRepositoryTests {
|
||||
this.repository.setHazelcastFlushMode(HazelcastFlushMode.IMMEDIATE);
|
||||
|
||||
HazelcastSession session = this.repository.createSession();
|
||||
verify(this.sessions, times(1)).put(eq(session.getId()), eq(session.getDelegate()),
|
||||
isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).set(eq(session.getId()),
|
||||
eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -124,8 +126,8 @@ public class HazelcastSessionRepositoryTests {
|
||||
verifyZeroInteractions(this.sessions);
|
||||
|
||||
this.repository.save(session);
|
||||
verify(this.sessions, times(1)).put(eq(session.getId()), eq(session.getDelegate()),
|
||||
isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).set(eq(session.getId()),
|
||||
eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -134,8 +136,10 @@ public class HazelcastSessionRepositoryTests {
|
||||
|
||||
HazelcastSession session = this.repository.createSession();
|
||||
session.setAttribute("testName", "testValue");
|
||||
verify(this.sessions, times(2)).put(eq(session.getId()), eq(session.getDelegate()),
|
||||
isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).set(eq(session.getId()),
|
||||
eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).executeOnKey(eq(session.getId()),
|
||||
any(EntryProcessor.class));
|
||||
|
||||
this.repository.save(session);
|
||||
verifyZeroInteractions(this.sessions);
|
||||
@@ -148,8 +152,8 @@ public class HazelcastSessionRepositoryTests {
|
||||
verifyZeroInteractions(this.sessions);
|
||||
|
||||
this.repository.save(session);
|
||||
verify(this.sessions, times(1)).put(eq(session.getId()), eq(session.getDelegate()),
|
||||
isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).set(eq(session.getId()),
|
||||
eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -158,8 +162,10 @@ public class HazelcastSessionRepositoryTests {
|
||||
|
||||
HazelcastSession session = this.repository.createSession();
|
||||
session.removeAttribute("testName");
|
||||
verify(this.sessions, times(2)).put(eq(session.getId()), eq(session.getDelegate()),
|
||||
isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).set(eq(session.getId()),
|
||||
eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).executeOnKey(eq(session.getId()),
|
||||
any(EntryProcessor.class));
|
||||
|
||||
this.repository.save(session);
|
||||
verifyZeroInteractions(this.sessions);
|
||||
@@ -172,8 +178,8 @@ public class HazelcastSessionRepositoryTests {
|
||||
verifyZeroInteractions(this.sessions);
|
||||
|
||||
this.repository.save(session);
|
||||
verify(this.sessions, times(1)).put(eq(session.getId()), eq(session.getDelegate()),
|
||||
isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).set(eq(session.getId()),
|
||||
eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -182,8 +188,10 @@ public class HazelcastSessionRepositoryTests {
|
||||
|
||||
HazelcastSession session = this.repository.createSession();
|
||||
session.setLastAccessedTime(System.currentTimeMillis());
|
||||
verify(this.sessions, times(2)).put(eq(session.getId()), eq(session.getDelegate()),
|
||||
isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).set(eq(session.getId()),
|
||||
eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).executeOnKey(eq(session.getId()),
|
||||
any(EntryProcessor.class));
|
||||
|
||||
this.repository.save(session);
|
||||
verifyZeroInteractions(this.sessions);
|
||||
@@ -196,8 +204,8 @@ public class HazelcastSessionRepositoryTests {
|
||||
verifyZeroInteractions(this.sessions);
|
||||
|
||||
this.repository.save(session);
|
||||
verify(this.sessions, times(1)).put(eq(session.getId()), eq(session.getDelegate()),
|
||||
isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).set(eq(session.getId()),
|
||||
eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -206,8 +214,10 @@ public class HazelcastSessionRepositoryTests {
|
||||
|
||||
HazelcastSession session = this.repository.createSession();
|
||||
session.setMaxInactiveIntervalInSeconds(1);
|
||||
verify(this.sessions, times(2)).put(eq(session.getId()), eq(session.getDelegate()),
|
||||
isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).set(eq(session.getId()),
|
||||
eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).executeOnKey(eq(session.getId()),
|
||||
any(EntryProcessor.class));
|
||||
|
||||
this.repository.save(session);
|
||||
verifyZeroInteractions(this.sessions);
|
||||
@@ -217,8 +227,8 @@ public class HazelcastSessionRepositoryTests {
|
||||
public void saveUnchangedFlushModeOnSave() {
|
||||
HazelcastSession session = this.repository.createSession();
|
||||
this.repository.save(session);
|
||||
verify(this.sessions, times(1)).put(eq(session.getId()), eq(session.getDelegate()),
|
||||
isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).set(eq(session.getId()),
|
||||
eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
|
||||
this.repository.save(session);
|
||||
verifyZeroInteractions(this.sessions);
|
||||
@@ -229,8 +239,8 @@ public class HazelcastSessionRepositoryTests {
|
||||
this.repository.setHazelcastFlushMode(HazelcastFlushMode.IMMEDIATE);
|
||||
|
||||
HazelcastSession session = this.repository.createSession();
|
||||
verify(this.sessions, times(1)).put(eq(session.getId()), eq(session.getDelegate()),
|
||||
isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions, times(1)).set(eq(session.getId()),
|
||||
eq(session.getDelegate()), isA(Long.class), eq(TimeUnit.SECONDS));
|
||||
|
||||
this.repository.save(session);
|
||||
verifyZeroInteractions(this.sessions);
|
||||
@@ -249,8 +259,8 @@ public class HazelcastSessionRepositoryTests {
|
||||
@Test
|
||||
public void getSessionExpired() {
|
||||
MapSession expired = new MapSession();
|
||||
expired.setLastAccessedTime(System.currentTimeMillis() -
|
||||
(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS * 1000 + 1000));
|
||||
expired.setLastAccessedTime(System.currentTimeMillis()
|
||||
- (MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS * 1000 + 1000));
|
||||
given(this.sessions.get(eq(expired.getId()))).willReturn(expired);
|
||||
|
||||
HazelcastSession session = this.repository.getSession(expired.getId());
|
||||
@@ -286,8 +296,8 @@ public class HazelcastSessionRepositoryTests {
|
||||
public void findByIndexNameAndIndexValueUnknownIndexName() {
|
||||
String indexValue = "testIndexValue";
|
||||
|
||||
Map<String, HazelcastSession> sessions = this.repository.findByIndexNameAndIndexValue(
|
||||
"testIndexName", indexValue);
|
||||
Map<String, HazelcastSession> sessions = this.repository
|
||||
.findByIndexNameAndIndexValue("testIndexName", indexValue);
|
||||
|
||||
assertThat(sessions).isEmpty();
|
||||
verifyZeroInteractions(this.sessions);
|
||||
@@ -297,8 +307,10 @@ public class HazelcastSessionRepositoryTests {
|
||||
public void findByIndexNameAndIndexValuePrincipalIndexNameNotFound() {
|
||||
String principal = "username";
|
||||
|
||||
Map<String, HazelcastSession> sessions = this.repository.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principal);
|
||||
Map<String, HazelcastSession> sessions = this.repository
|
||||
.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
principal);
|
||||
|
||||
assertThat(sessions).isEmpty();
|
||||
verify(this.sessions, times(1)).values(isA(EqualPredicate.class));
|
||||
@@ -318,8 +330,10 @@ public class HazelcastSessionRepositoryTests {
|
||||
saved.add(saved2);
|
||||
given(this.sessions.values(isA(EqualPredicate.class))).willReturn(saved);
|
||||
|
||||
Map<String, HazelcastSession> sessions = this.repository.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principal);
|
||||
Map<String, HazelcastSession> sessions = this.repository
|
||||
.findByIndexNameAndIndexValue(
|
||||
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
|
||||
principal);
|
||||
|
||||
assertThat(sessions).hasSize(2);
|
||||
verify(this.sessions, times(1)).values(isA(EqualPredicate.class));
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -103,8 +104,9 @@ public class SpringSessionRememberMeServicesTests {
|
||||
verifyZeroInteractions(request, response);
|
||||
}
|
||||
|
||||
// gh-752
|
||||
@Test
|
||||
public void loginFailInvalidatesSession() {
|
||||
public void loginFailRemoveSecurityContext() {
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
HttpSession session = mock(HttpSession.class);
|
||||
@@ -112,7 +114,7 @@ public class SpringSessionRememberMeServicesTests {
|
||||
this.rememberMeServices = new SpringSessionRememberMeServices();
|
||||
this.rememberMeServices.loginFail(request, response);
|
||||
verify(request, times(1)).getSession(eq(false));
|
||||
verify(session, times(1)).invalidate();
|
||||
verify(session, times(1)).removeAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
||||
verifyZeroInteractions(request, response, session);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -710,19 +710,19 @@ public class CookieHttpSessionStrategyTests {
|
||||
}
|
||||
|
||||
private String createSessionCookieValue(long size) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (long i = 0; i < size; i++) {
|
||||
String hex = Long.toHexString(i);
|
||||
buffer.append(hex);
|
||||
buffer.append(" ");
|
||||
buffer.append(i);
|
||||
sb.append(hex);
|
||||
sb.append(" ");
|
||||
sb.append(i);
|
||||
if (i < size - 1) {
|
||||
buffer.append(" ");
|
||||
sb.append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -568,6 +568,27 @@ public class SessionRepositoryFilterTests {
|
||||
});
|
||||
}
|
||||
|
||||
// gh-951
|
||||
@Test
|
||||
public void doFilterChangeSessionIdCopyAttributes() throws Exception {
|
||||
// change the session id
|
||||
doFilter(new DoInFilter() {
|
||||
@Override
|
||||
public void doFilter(HttpServletRequest wrappedRequest) {
|
||||
HttpSession session = wrappedRequest.getSession();
|
||||
session.setMaxInactiveInterval(300);
|
||||
String originalSessionId = session.getId();
|
||||
int originalMaxInactiveInterval = session.getMaxInactiveInterval();
|
||||
|
||||
String changeSessionId = ReflectionTestUtils.invokeMethod(wrappedRequest,
|
||||
"changeSessionId");
|
||||
assertThat(changeSessionId).isNotEqualTo(originalSessionId);
|
||||
assertThat(session.getMaxInactiveInterval())
|
||||
.isEqualTo(originalMaxInactiveInterval);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// gh-142, gh-153
|
||||
@Test
|
||||
public void doFilterIsRequestedValidSessionFalseInvalidId() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user