Compare commits

...

18 Commits

Author SHA1 Message Date
Spring Buildmaster
e44cd45668 Release version 1.3.2.RELEASE 2018-02-09 20:11:39 +00:00
Vedran Pavic
7f0de8126e Improve layout of community extensions doc section
Closes gh-993
2018-02-05 12:43:25 +01:00
Vedran Pavic
d75b03f594 Fix Gradle deprecation warnings 2018-01-29 18:45:38 +01:00
Vedran Pavic
ca0fea3a54 Upgrade Gradle to 3.5.1 2018-01-29 18:36:40 +01:00
Eddú Meléndez
92af786e6b Polish samples
Closes gh-986
2018-01-29 18:17:42 +01:00
Vedran Pavic
d271a4ad1d Polish contribution
Closes gh-920
2018-01-29 18:12:01 +01:00
Roman Cherepanov
04c1908378 Fix link to GemFire documentation
See gh-920
2018-01-29 18:11:33 +01:00
Vedran Pavic
f0e187fbd7 Update references to Spring Boot's Redis starter
Closes gh-952
2018-01-29 17:06:51 +01:00
Vedran Pavic
2d3001a24e Fix SessionRepositoryFilter not retaining original maxInactiveInterval
Closes gh-951
2018-01-29 16:45:46 +01:00
Vedran Pavic
f2d1badd60 Fix misc typos
Closes gh-985
2018-01-29 16:27:20 +01:00
Vedran Pavic
6a6d60d8f8 Improve session event handling
Closes gh-984
2018-01-29 16:27:20 +01:00
Vedran Pavic
b2cb3f6a3a Optimize HazelcastSessionRepository write operations
Closes gh-983
2018-01-29 16:27:20 +01:00
Vedran Pavic
d7ae5785eb Improve JDBC data store schema scripts
Closes gh-982
2018-01-29 16:27:15 +01:00
Kanjie Lu
96eb40439c fix typo
change "they key" to  "the key"

Closes gh-981
2018-01-29 16:26:08 +01:00
mikemassa84
8ed0999ad3 Update grails3.adoc
Add a note about spring-session and grails flash scope, with link to stackoverflow answer.

Closes gh-980
2018-01-29 16:26:08 +01:00
Vedran Pavic
b2d2335d73 Replace StringBuffer usages with StringBuilder
Closes gh-979
2018-01-29 16:25:59 +01:00
Spring Buildmaster
f597c5a824 Next development version 2017-04-27 18:57:32 +00:00
Spring Buildmaster
212eca306c Release version 1.3.1.RELEASE 2017-04-27 18:57:22 +00:00
38 changed files with 322 additions and 217 deletions

View File

@@ -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')
}
}
}

View File

@@ -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>
----

View File

@@ -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

View File

@@ -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,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/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`.

View File

@@ -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:

View File

@@ -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:

View File

@@ -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:

View File

@@ -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:

View File

@@ -192,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].
@@ -829,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.
@@ -846,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]
====
@@ -1199,8 +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]
http://infinispan.org/docs/dev/user_guide/user_guide.html#externalizing_session_using_spring_session[Spring Session Infinispan]
|===
| 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

View File

@@ -1,32 +1,31 @@
assertjVersion=2.5.0
bootstrapVersion=2.3.2
commonsLoggingVersion=1.2
commonsPoolVersion=2.4.2
gebVersion=0.13.1
groovyVersion=2.4.4
h2Version=1.4.192
hazelcastVersion=3.6.5
html5ShivVersion=3.7.3
httpClientVersion=4.5.1
jacksonVersion=2.6.5
jedisVersion=2.8.1
jspApiVersion=2.0
jstlVersion=1.2.1
jstlelVersion=1.2.5
junitVersion=4.12
lettuceVersion=3.5.0.Final
mockitoVersion=1.10.19
seleniumVersion=2.52.0
servletApiVersion=3.0.1
spockVersion=1.0-groovy-2.4
springVersion=4.3.4.RELEASE
springDataGemFireVersion=1.8.10.RELEASE
springDataGeodeVersion=1.0.0.INCUBATING-RELEASE
springDataMongoVersion=1.9.4.RELEASE
jstlelVersion=1.2.5
version=1.3.2.RELEASE
springDataRedisVersion=1.7.10.RELEASE
# We cannot go beyond this version with Spring 3 support
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.INCUBATING-RELEASE
springSecurityVersion=4.2.0.RELEASE
springVersion=4.3.4.RELEASE
httpClientVersion=4.5.1
h2Version=1.4.192
jedisVersion=2.8.1
springDataMongoVersion=1.9.4.RELEASE
springShellVersion=1.1.0.RELEASE
springDataGemFireVersion=1.8.10.RELEASE
assertjVersion=2.5.0
spockVersion=1.0-groovy-2.4
webjarsTaglibVersion=0.3
version=1.3.1.BUILD-SNAPSHOT
jstlVersion=1.2.1
groovyVersion=2.4.4

Binary file not shown.

View File

@@ -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
View File

@@ -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" "$@"

View File

@@ -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",

View File

@@ -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",

View File

@@ -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()
}
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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) {

View File

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

View File

@@ -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),

View File

@@ -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,

View File

@@ -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();

View File

@@ -8,6 +8,7 @@ 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) NOT NULL,

View File

@@ -8,6 +8,7 @@ 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) NOT NULL,

View File

@@ -8,6 +8,7 @@ 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) NOT NULL,

View File

@@ -8,6 +8,7 @@ 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) NOT NULL,

View File

@@ -8,6 +8,7 @@ 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) NOT NULL,

View File

@@ -8,6 +8,7 @@ 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) NOT NULL,

View File

@@ -8,6 +8,7 @@ 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) NOT NULL,

View File

@@ -8,6 +8,7 @@ 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) NOT NULL,

View File

@@ -8,6 +8,7 @@ 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) NOT NULL,

View File

@@ -8,6 +8,7 @@ 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) NOT NULL,

View File

@@ -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));

View File

@@ -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")

View File

@@ -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 {