Compare commits

..

44 Commits
2.5.2 ... 2.4.5

Author SHA1 Message Date
Eleftheria Stein
24fc8d94c4 Release 2.4.5 2021-08-17 18:50:46 +02:00
Eleftheria Stein
b6b99e9ffd Upgrade test dependencies 2021-08-17 17:26:33 +02:00
Eleftheria Stein
b1b10614ea Upgrade Spring Security to 5.4.8
Closes gh-1896
2021-08-17 17:17:17 +02:00
Eleftheria Stein
5f7b4266d8 Upgrade Spring Data to 2020.0.12
Closes gh-1895
2021-08-17 17:16:26 +02:00
Eleftheria Stein
8e71132a15 Upgrade Spring Framework to 5.3.9
Closes gh-1894
2021-08-17 17:15:49 +02:00
Eleftheria Stein
c37237ae98 Upgrade Reactor to 2020.0.10
Closes gh-1893
2021-08-17 17:15:10 +02:00
John Blum
12ab0029f5 Next development version 2021-06-22 12:43:47 -07:00
Eleftheria Stein
1b4fb13d4d Release 2.4.4 2021-06-22 17:52:36 +02:00
Eleftheria Stein
21be7aac9c Update JDBC test images
Closes gh-1877
2021-06-22 17:37:00 +02:00
Eleftheria Stein
67f4850024 Revert "Release 2.4.4"
This reverts commit a92abcb26f.
2021-06-22 14:11:26 +02:00
Eleftheria Stein
a92abcb26f Release 2.4.4 2021-06-22 13:15:55 +02:00
Eleftheria Stein
041fb222f9 Revert "Use GPG_PRIVATE_KEY directly in build"
This reverts commit eed2ff195a.
2021-06-22 13:15:25 +02:00
Eleftheria Stein
dc951435d4 Upgrade test dependencies 2021-06-22 11:48:32 +02:00
Eleftheria Stein
e9243ceb59 Upgrade samples to Spring Boot 2.4.7
Closes gh-1876
2021-06-22 11:37:43 +02:00
Eleftheria Stein
8fb54ac1e0 Upgrade Spring Data to 2020.0.9
Closes gh-1875
2021-06-22 11:33:00 +02:00
Eleftheria Stein
b0558c1fd2 Upgrade Spring Framework to 5.3.8
Closes gh-1874
2021-06-22 11:31:44 +02:00
Eleftheria Stein
f570c2065b Upgrade Reactor to 2020.0.7
Closes gh-1873
2021-06-22 11:30:32 +02:00
Eleftheria Stein
eed2ff195a Use GPG_PRIVATE_KEY directly in build
Closes gh-1861
2021-05-31 16:47:34 +03:00
Eleftheria Stein
c467a7d656 Next development version 2021-04-13 13:39:30 +02:00
Eleftheria Stein
b9618fe6b3 Release 2.4.3 2021-04-13 13:21:46 +02:00
Eleftheria Stein
625833f1fe Upgrade test dependencies 2021-04-13 13:20:28 +02:00
Eleftheria Stein
f1eee1e7a4 Upgrade Spring Security to 5.4.6
Closes gh-1828
2021-04-13 13:19:39 +02:00
Eleftheria Stein
a2ee77c62e Upgrade Spring Data to 2020.0.7
Closes gh-1827
2021-04-13 13:18:11 +02:00
Eleftheria Stein
3c77d76cee Upgrade Spring Framework to 5.3.5
Closes gh-1826
2021-04-13 13:16:24 +02:00
Eleftheria Stein
6a8d2f4d88 Upgrade Reactor to 2020.0.6
Closes gh-1825
2021-04-13 13:15:39 +02:00
Eleftheria Stein
4c63faece1 Upgrade Hazelcast to 3.12.12
Closes gh-1824
2021-04-13 13:14:36 +02:00
Eleftheria Stein
e2a7e71ae3 Upgrade samples to Spring Boot 2.4.4
Closes gh-1823
2021-04-13 13:13:53 +02:00
Eleftheria Stein
66f81daa20 Throw exception if session created after response
Closes gh-1798
2021-03-25 12:01:53 +02:00
Eleftheria Stein
829b62bd19 Differentiate 2.4.x CI from master CI
- rename CI workflow file
- rename CI workflow identifier
- change daily build time
- ensure checkout is always run on 2.4.x

Issue: gh-1794
2021-02-22 11:19:13 +01:00
Eleftheria Stein
b7209f8330 Make Hazelcast tests independent of ordering
Closes gh-1787
2021-02-02 15:58:02 +01:00
Eleftheria Stein
645e525b84 Upgrade samples to Spring Boot 2.4.2
Closes gh-1782
2021-01-29 17:26:15 +01:00
Eleftheria Stein
ba4bb6fcf6 Use spring-build-conventions:0.0.37 2021-01-27 12:27:27 +01:00
Eleftheria Stein
f224d571f0 Next development version 2021-01-19 18:33:23 +01:00
Eleftheria Stein
3ba76d0375 Add manual trigger to CI workflow
Closes gh-1777
2021-01-19 17:41:19 +01:00
Eleftheria Stein
eb29949996 Release 2.4.2 2021-01-19 14:25:32 +01:00
Eleftheria Stein
02a990d00e Upgrade test dependencies 2021-01-18 13:21:12 +01:00
Eleftheria Stein
56809eacb2 Upgrade Hazelcast to 3.12.11
Closes gh-1766
2021-01-18 13:19:56 +01:00
Eleftheria Stein
4ff8f73b84 Upgrade Spring Data to 2020.0.3
Closes gh-1765
2021-01-18 13:17:38 +01:00
Eleftheria Stein
0ad389633e Upgrade Spring Security to 5.4.2
Closes gh-1764
2021-01-18 13:16:00 +01:00
Eleftheria Stein
5a9046e391 Upgrade Spring Framework to 5.3.3
Closes gh-1763
2021-01-18 13:15:21 +01:00
Eleftheria Stein
690f734307 Upgrade Reactor to 2020.0.3
Closes gh-1762
2021-01-18 13:14:06 +01:00
Eleftheria Stein
823e323f68 Add artifactory credentials to build 2020-11-18 14:39:48 +01:00
Eleftheria Stein
444b5ad85a Rename workflow name to match master 2020-11-10 13:40:22 +01:00
Eleftheria Stein
b4a8c7e516 Create GitHub Actions CI for 2.4.x 2020-11-10 11:52:45 +01:00
68 changed files with 731 additions and 1098 deletions

View File

@@ -1,11 +1,11 @@
name: 2.5.x CI
name: 2.4.x CI
on:
push:
branches:
- 2.5.x
- 2.4.x
schedule:
- cron: '0 10 * * *' # Once per day at 10am UTC
- cron: '4 10 * * *' # Once per day at 10:04am UTC
workflow_dispatch: # Manual trigger
env:
@@ -25,20 +25,19 @@ jobs:
fail-fast: false
steps:
- uses: actions/checkout@v2
with:
ref: '2.4.x'
- name: Set up JDK ${{ matrix.jdk }}
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.jdk }}
- name: Setup gradle user name
run: |
mkdir -p ~/.gradle
echo 'systemProp.user.name=spring-builds' >> ~/.gradle/gradle.properties
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
- name: Build with Gradle
run: |
export GRADLE_ENTERPRISE_CACHE_USERNAME="$GRADLE_ENTERPRISE_CACHE_USER"
export GRADLE_ENTERPRISE_CACHE_PASSWORD="$GRADLE_ENTERPRISE_CACHE_PASSWORD"
@@ -50,14 +49,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: '2.4.x'
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: '8'
- name: Setup gradle user name
run: |
mkdir -p ~/.gradle
echo 'systemProp.user.name=spring-builds' >> ~/.gradle/gradle.properties
- name: Deploy artifacts
run: |
export GRADLE_ENTERPRISE_CACHE_USERNAME="$GRADLE_ENTERPRISE_CACHE_USER"
@@ -69,7 +66,7 @@ jobs:
./gradlew deployArtifacts -PossrhUsername="$OSSRH_TOKEN_USERNAME" -PossrhPassword="$OSSRH_TOKEN_PASSWORD" -PartifactoryUsername="$ARTIFACTORY_USERNAME" -PartifactoryPassword="$ARTIFACTORY_PASSWORD" --stacktrace --no-parallel
./gradlew finalizeDeployArtifacts -PossrhUsername="$OSSRH_TOKEN_USERNAME" -PossrhPassword="$OSSRH_TOKEN_PASSWORD" -PartifactoryUsername="$ARTIFACTORY_USERNAME" -PartifactoryPassword="$ARTIFACTORY_PASSWORD" --stacktrace --no-parallel
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY_NO_HEADER }}
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
OSSRH_TOKEN_USERNAME: ${{ secrets.OSSRH_TOKEN_USERNAME }}
OSSRH_TOKEN_PASSWORD: ${{ secrets.OSSRH_TOKEN_PASSWORD }}
@@ -81,14 +78,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: '2.4.x'
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: '8'
- name: Setup gradle user name
run: |
mkdir -p ~/.gradle
echo 'systemProp.user.name=spring-builds' >> ~/.gradle/gradle.properties
- name: Deploy Docs
run: |
export GRADLE_ENTERPRISE_CACHE_USERNAME="$GRADLE_ENTERPRISE_CACHE_USER"

View File

@@ -1,9 +1,6 @@
name: 2.5.x PR Build
name: PR Build
on:
pull_request:
branches:
- 2.5.x
on: pull_request
jobs:
build:

View File

@@ -6,7 +6,7 @@ something, or simply want to hack on the code this document should help you get
== Code of Conduct
Please see our https://github.com/spring-projects/.github/blob/main/CODE_OF_CONDUCT.md[code of conduct].
Please see our https://github.com/spring-projects/.github/blob/master/CODE_OF_CONDUCT.md[code of conduct]
== Reporting Security Vulnerabilities
@@ -26,6 +26,7 @@ information as possible. Ideally, that would include a small sample project that
reproduces the problem.
== Sign the Contributor License Agreement
If you have not previously done so, please fill out and
submit the https://cla.pivotal.io/sign/spring[Contributor License Agreement].

View File

@@ -2,7 +2,7 @@
image:https://badges.gitter.im/spring-projects/spring-session.svg[link="https://gitter.im/spring-projects/spring-session?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"]
image:https://github.com/spring-projects/spring-session/workflows/CI/badge.svg?branch=main["Build Status", link="https://github.com/spring-projects/spring-session/actions?query=workflow%3ACI"]
image:https://github.com/spring-projects/spring-session/workflows/CI/badge.svg?branch=master["Build Status", link="https://github.com/spring-projects/spring-session/actions?query=workflow%3ACI"]
Spring Session provides an API and implementations for managing a user's session information, while also making it trivial to support clustered sessions without being tied to an application container specific solution.
It also provides transparent integration with:
@@ -13,61 +13,27 @@ It also provides transparent integration with:
== Modules
This Spring Session repository consists of the following modules:
Spring Session consists of the following modules:
* Spring Session Core - provides core Spring Session functionalities and APIs
* Spring Session Data Redis - provides `SessionRepository` and `ReactiveSessionRepository` implementation backed by Redis and configuration support
* Spring Session JDBC - provides `SessionRepository` implementation backed by a relational database and configuration support
* Spring Session Hazelcast - provides `SessionRepository` implementation backed by Hazelcast and configuration support
Additional Spring Session modules can be found in the https://github.com/spring-projects/spring-session-data-mongodb[spring-session-data-mongodb] repository
and https://github.com/spring-projects/spring-session-data-geode[spring-session-data-geode] repository.
== Getting Started
We recommend you visit the https://docs.spring.io/spring-session/docs/current/reference/html5/#samples[Spring Session Reference] and look through the "Samples and Guides" section to see which one best suits your needs.
== Samples
Spring Session samples are available in the https://github.com/spring-projects/spring-session/tree/main/spring-session-samples[spring-session-samples] directory.
== Contributing
Please see our https://github.com/spring-projects/spring-session/blob/main/CONTRIBUTING.adoc[Contributing guidelines]
for information on how to report issues, enhancements or security vulnerabilities.
== Building from Source
Spring Session uses a https://gradle.org[Gradle]-based build system.
In the instructions below, `./gradlew` is invoked from the root of the source tree and serves as
a cross-platform, self-contained bootstrap mechanism for the build.
Check out sources
----
git clone git@github.com:spring-projects/spring-session.git
----
Install all spring-\* jars into your local Maven cache
----
./gradlew install
----
Compile and test; build all jars, distribution zips, and docs
----
./gradlew build
----
== Documentation
You can find the documentation, samples, and guides for using Spring Session on the https://projects.spring.io/spring-session/[Spring Session project site].
For more in depth information, visit the https://docs.spring.io/spring-session/docs/current/reference/html5/[Spring Session Reference].
== Code of Conduct
Please see our https://github.com/spring-projects/.github/blob/main/CODE_OF_CONDUCT.md[code of conduct].
Please see our https://github.com/spring-projects/.github/blob/master/CODE_OF_CONDUCT.md[code of conduct]
== Reporting Security Vulnerabilities
Please see our https://github.com/spring-projects/spring-session/security/policy[Security policy].
== Spring Session Project Site
You can find the documentation, issue management, support, samples, and guides for using Spring Session at https://projects.spring.io/spring-session/
== License

View File

@@ -10,15 +10,7 @@ buildscript {
repositories {
gradlePluginPortal()
maven { url 'https://repo.spring.io/plugins-release/' }
maven {
url = 'https://repo.spring.io/plugins-snapshot'
if (project.hasProperty('artifactoryUsername')) {
credentials {
username "$artifactoryUsername"
password "$artifactoryPassword"
}
}
}
maven { url 'https://repo.spring.io/plugins-snapshot' }
}
dependencies {

View File

@@ -1,3 +1,3 @@
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.parallel=true
version=2.5.2
version=2.4.5

View File

@@ -1,10 +1,10 @@
dependencyManagement {
imports {
mavenBom 'io.projectreactor:reactor-bom:2020.0.10'
mavenBom 'org.junit:junit-bom:5.7.2'
mavenBom 'org.junit:junit-bom:5.7.1'
mavenBom 'org.springframework:spring-framework-bom:5.3.9'
mavenBom 'org.springframework.data:spring-data-bom:2021.0.4'
mavenBom 'org.springframework.security:spring-security-bom:5.5.2'
mavenBom 'org.springframework.data:spring-data-bom:2020.0.12'
mavenBom 'org.springframework.security:spring-security-bom:5.4.8'
mavenBom 'org.testcontainers:testcontainers-bom:1.15.3'
}
@@ -16,21 +16,21 @@ dependencyManagement {
dependency 'org.aspectj:aspectjweaver:1.9.7'
dependency 'com.h2database:h2:1.4.200'
dependency 'com.ibm.db2:jcc:11.5.5.0'
dependency 'com.ibm.db2:jcc:11.5.0.0'
dependency 'com.microsoft.sqlserver:mssql-jdbc:7.4.1.jre8'
dependency 'com.oracle.database.jdbc:ojdbc8:19.10.0.0'
dependency 'com.oracle.database.jdbc:ojdbc8:19.8.0.0'
dependency 'com.zaxxer:HikariCP:3.4.5'
dependency 'edu.umd.cs.mtc:multithreadedtc:1.01'
dependency 'io.lettuce:lettuce-core:6.1.4.RELEASE'
dependency 'io.lettuce:lettuce-core:6.0.7.RELEASE'
dependency 'javax.annotation:javax.annotation-api:1.3.2'
dependency 'javax.servlet:javax.servlet-api:4.0.1'
dependency 'junit:junit:4.13.2'
dependency 'mysql:mysql-connector-java:8.0.26'
dependency 'mysql:mysql-connector-java:8.0.25'
dependency 'org.apache.derby:derby:10.14.2.0'
dependency 'org.assertj:assertj-core:3.19.0'
dependency 'org.hsqldb:hsqldb:2.5.2'
dependency 'org.mariadb.jdbc:mariadb-java-client:2.7.4'
dependency 'org.mockito:mockito-core:3.10.0'
dependency 'org.assertj:assertj-core:3.18.0'
dependency 'org.hsqldb:hsqldb:2.5.1'
dependency 'org.mariadb.jdbc:mariadb-java-client:2.7.3'
dependency 'org.mockito:mockito-core:3.5.15'
dependency 'org.postgresql:postgresql:42.2.23'
}
}

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

31
gradlew vendored
View File

@@ -82,7 +82,6 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -130,7 +129,6 @@ fi
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
@@ -156,19 +154,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
i=$((i+1))
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
@@ -177,9 +175,14 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
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
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

25
gradlew.bat vendored
View File

@@ -29,9 +29,6 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@@ -40,7 +37,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -54,7 +51,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -64,14 +61,28 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell

View File

@@ -1,15 +1,3 @@
pluginManagement {
repositories {
gradlePluginPortal()
maven { url 'https://repo.spring.io/plugins-release' }
}
}
plugins {
id "com.gradle.enterprise" version "3.5.1"
id "io.spring.ge.conventions" version "0.0.7"
}
rootProject.name = 'spring-session-build'
include 'spring-session-core'

View File

@@ -59,7 +59,6 @@ import org.springframework.session.SessionRepository;
* . The default is to look in a cookie named SESSION.</li>
* <li>The session id of newly created {@link org.springframework.session.Session} is sent
* to the client using
* {@link HttpSessionIdResolver#setSessionId(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, String)}
* <li>The client is notified that the session id is no longer valid with
* {@link HttpSessionIdResolver#expireSession(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
* </li>

View File

@@ -33,7 +33,7 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Tests for {@link SpringSessionRememberMeServices}.
@@ -88,7 +88,7 @@ class SpringSessionRememberMeServicesTests {
HttpServletResponse response = mock(HttpServletResponse.class);
this.rememberMeServices = new SpringSessionRememberMeServices();
this.rememberMeServices.autoLogin(request, response);
verifyNoMoreInteractions(request, response);
verifyZeroInteractions(request, response);
}
// gh-752
@@ -102,7 +102,7 @@ class SpringSessionRememberMeServicesTests {
this.rememberMeServices.loginFail(request, response);
verify(request, times(1)).getSession(eq(false));
verify(session, times(1)).removeAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
verifyNoMoreInteractions(request, response, session);
verifyZeroInteractions(request, response, session);
}
@Test
@@ -119,7 +119,7 @@ class SpringSessionRememberMeServicesTests {
verify(request, times(1)).getSession();
verify(request, times(1)).setAttribute(eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(session, times(1)).setMaxInactiveInterval(eq(2592000));
verifyNoMoreInteractions(request, response, session, authentication);
verifyZeroInteractions(request, response, session, authentication);
}
@Test
@@ -137,7 +137,7 @@ class SpringSessionRememberMeServicesTests {
verify(request, times(1)).getSession();
verify(request, times(1)).setAttribute(eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(session, times(1)).setMaxInactiveInterval(eq(2592000));
verifyNoMoreInteractions(request, response, session, authentication);
verifyZeroInteractions(request, response, session, authentication);
}
@Test
@@ -153,7 +153,7 @@ class SpringSessionRememberMeServicesTests {
verify(request, times(1)).getSession();
verify(request, times(1)).setAttribute(eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(session, times(1)).setMaxInactiveInterval(eq(2592000));
verifyNoMoreInteractions(request, response, session, authentication);
verifyZeroInteractions(request, response, session, authentication);
}
@Test
@@ -171,7 +171,7 @@ class SpringSessionRememberMeServicesTests {
verify(request, times(1)).getSession();
verify(request, times(1)).setAttribute(eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(session, times(1)).setMaxInactiveInterval(eq(100000));
verifyNoMoreInteractions(request, response, session, authentication);
verifyZeroInteractions(request, response, session, authentication);
}
}

View File

@@ -39,7 +39,7 @@ import org.springframework.session.events.SessionDestroyedEvent;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Tests for {@link SessionEventHttpSessionListenerAdapter}.
@@ -97,7 +97,7 @@ class SessionEventHttpSessionListenerAdapterTests {
this.listener.onApplicationEvent(this.destroyed);
verifyNoMoreInteractions(this.destroyed, this.listener1, this.listener2);
verifyZeroInteractions(this.destroyed, this.listener1, this.listener2);
}
@Test

View File

@@ -73,7 +73,7 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Tests for {@link SessionRepositoryFilter}.
@@ -1273,7 +1273,7 @@ class SessionRepositoryFilterTests {
}
});
verifyNoMoreInteractions(sessionRepository);
verifyZeroInteractions(sessionRepository);
}
@Test
@@ -1288,7 +1288,7 @@ class SessionRepositoryFilterTests {
}
});
verifyNoMoreInteractions(sessionRepository);
verifyZeroInteractions(sessionRepository);
}
@Test
@@ -1306,7 +1306,7 @@ class SessionRepositoryFilterTests {
}
});
verifyNoMoreInteractions(sessionRepository);
verifyZeroInteractions(sessionRepository);
}
@Test
@@ -1331,7 +1331,7 @@ class SessionRepositoryFilterTests {
verify(sessionRepository).deleteById(eq(session.getId()));
verify(sessionRepository).createSession();
verify(sessionRepository).save(any());
verifyNoMoreInteractions(sessionRepository);
verifyZeroInteractions(sessionRepository);
}
// --- order

View File

@@ -49,7 +49,7 @@ import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
class SessionRepositoryMessageInterceptorTests {
@@ -98,7 +98,7 @@ class SessionRepositoryMessageInterceptorTests {
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyNoMoreInteractions(this.sessionRepository);
verifyZeroInteractions(this.sessionRepository);
}
@Test
@@ -107,7 +107,7 @@ class SessionRepositoryMessageInterceptorTests {
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyNoMoreInteractions(this.sessionRepository);
verifyZeroInteractions(this.sessionRepository);
}
@Test
@@ -116,7 +116,7 @@ class SessionRepositoryMessageInterceptorTests {
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyNoMoreInteractions(this.sessionRepository);
verifyZeroInteractions(this.sessionRepository);
}
@Test
@@ -125,7 +125,7 @@ class SessionRepositoryMessageInterceptorTests {
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyNoMoreInteractions(this.sessionRepository);
verifyZeroInteractions(this.sessionRepository);
}
@Test
@@ -209,7 +209,7 @@ class SessionRepositoryMessageInterceptorTests {
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyNoMoreInteractions(this.sessionRepository);
verifyZeroInteractions(this.sessionRepository);
}
@Test
@@ -218,14 +218,14 @@ class SessionRepositoryMessageInterceptorTests {
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyNoMoreInteractions(this.sessionRepository);
verifyZeroInteractions(this.sessionRepository);
}
@Test
void beforeHandshakeNotServletServerHttpRequest() {
assertThat(this.interceptor.beforeHandshake(null, null, null, null)).isTrue();
verifyNoMoreInteractions(this.sessionRepository);
verifyZeroInteractions(this.sessionRepository);
}
@Test
@@ -233,7 +233,7 @@ class SessionRepositoryMessageInterceptorTests {
ServletServerHttpRequest request = new ServletServerHttpRequest(new MockHttpServletRequest());
assertThat(this.interceptor.beforeHandshake(request, null, null, null)).isTrue();
verifyNoMoreInteractions(this.sessionRepository);
verifyZeroInteractions(this.sessionRepository);
}
@Test
@@ -256,7 +256,7 @@ class SessionRepositoryMessageInterceptorTests {
void afterHandshakeDoesNothing() {
this.interceptor.afterHandshake(null, null, null, null);
verifyNoMoreInteractions(this.sessionRepository);
verifyZeroInteractions(this.sessionRepository);
}
private void setSessionId(String id) {

View File

@@ -18,7 +18,6 @@ package org.springframework.session.data.redis;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -37,7 +36,6 @@ import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.util.ByteUtils;
import org.springframework.session.DelegatingIndexResolver;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.FlushMode;
@@ -88,7 +86,7 @@ import org.springframework.util.Assert;
* details.
*
* <pre>
* HMSET spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe creationTime 1404360000000 maxInactiveInterval 1800 lastAccessedTime 1404360000000 sessionAttr:attrName someAttrValue sessionAttr:attrName2 someAttrValue2
* HMSET spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe creationTime 1404360000000 maxInactiveInterval 1800 lastAccessedTime 1404360000000 sessionAttr:attrName someAttrValue sessionAttr2:attrName someAttrValue2
* EXPIRE spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe 2100
* APPEND spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe ""
* EXPIRE spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe 1800
@@ -131,8 +129,8 @@ import org.springframework.util.Assert;
* The {@link RedisIndexedSessionRepository.RedisSession} keeps track of the properties
* that have changed and only updates those. This means if an attribute is written once
* and read many times we only need to write that attribute once. For example, assume the
* session attribute "attrName2" from earlier was updated. The following would be executed
* upon saving:
* session attribute "sessionAttr2" from earlier was updated. The following would be
* executed upon saving:
* </p>
*
* <pre>
@@ -274,20 +272,10 @@ public class RedisIndexedSessionRepository
private String sessionCreatedChannelPrefix;
private byte[] sessionCreatedChannelPrefixBytes;
private String sessionDeletedChannel;
private byte[] sessionDeletedChannelBytes;
private String sessionExpiredChannel;
private byte[] sessionExpiredChannelBytes;
private String expiredKeyPrefix;
private byte[] expiredKeyPrefixBytes;
private final RedisOperations<Object, Object> sessionRedisOperations;
private final RedisSessionExpirationPolicy expirationPolicy;
@@ -393,13 +381,8 @@ public class RedisIndexedSessionRepository
private void configureSessionChannels() {
this.sessionCreatedChannelPrefix = this.namespace + "event:" + this.database + ":created:";
this.sessionCreatedChannelPrefixBytes = this.sessionCreatedChannelPrefix.getBytes();
this.sessionDeletedChannel = "__keyevent@" + this.database + "__:del";
this.sessionDeletedChannelBytes = this.sessionDeletedChannel.getBytes();
this.sessionExpiredChannel = "__keyevent@" + this.database + "__:expired";
this.sessionExpiredChannelBytes = this.sessionExpiredChannel.getBytes();
this.expiredKeyPrefix = this.namespace + "sessions:expires:";
this.expiredKeyPrefixBytes = this.expiredKeyPrefix.getBytes();
}
/**
@@ -518,24 +501,25 @@ public class RedisIndexedSessionRepository
@Override
public void onMessage(Message message, byte[] pattern) {
byte[] messageChannel = message.getChannel();
byte[] messageBody = message.getBody();
if (ByteUtils.startsWith(messageChannel, this.sessionCreatedChannelPrefixBytes)) {
String channel = new String(messageChannel);
if (channel.startsWith(this.sessionCreatedChannelPrefix)) {
// TODO: is this thread safe?
@SuppressWarnings("unchecked")
Map<Object, Object> loaded = (Map<Object, Object>) this.defaultSerializer.deserialize(message.getBody());
handleCreated(loaded, new String(messageChannel));
handleCreated(loaded, channel);
return;
}
byte[] messageBody = message.getBody();
if (!ByteUtils.startsWith(messageBody, this.expiredKeyPrefixBytes)) {
String body = new String(messageBody);
if (!body.startsWith(getExpiredKeyPrefix())) {
return;
}
boolean isDeleted = Arrays.equals(messageChannel, this.sessionDeletedChannelBytes);
if (isDeleted || Arrays.equals(messageChannel, this.sessionExpiredChannelBytes)) {
String body = new String(messageBody);
boolean isDeleted = channel.equals(this.sessionDeletedChannel);
if (isDeleted || channel.equals(this.sessionExpiredChannel)) {
int beginIndex = body.lastIndexOf(":") + 1;
int endIndex = body.length();
String sessionId = body.substring(beginIndex, endIndex);
@@ -627,7 +611,7 @@ public class RedisIndexedSessionRepository
}
private String getExpiredKeyPrefix() {
return this.expiredKeyPrefix;
return this.namespace + "sessions:expires:";
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2021 the original author or authors.
* Copyright 2014-2019 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.
@@ -50,8 +50,6 @@ final class RedisSessionExpirationPolicy {
private static final Log logger = LogFactory.getLog(RedisSessionExpirationPolicy.class);
private static final String SESSION_EXPIRES_PREFIX = "expires:";
private final RedisOperations<Object, Object> redis;
private final Function<Long, String> lookupExpirationKey;
@@ -69,12 +67,11 @@ final class RedisSessionExpirationPolicy {
void onDelete(Session session) {
long toExpire = roundUpToNextMinute(expiresInMillis(session));
String expireKey = getExpirationKey(toExpire);
String entryToRemove = SESSION_EXPIRES_PREFIX + session.getId();
this.redis.boundSetOps(expireKey).remove(entryToRemove);
this.redis.boundSetOps(expireKey).remove(session.getId());
}
void onExpirationUpdated(Long originalExpirationTimeInMilli, Session session) {
String keyToExpire = SESSION_EXPIRES_PREFIX + session.getId();
String keyToExpire = "expires:" + session.getId();
long toExpire = roundUpToNextMinute(expiresInMillis(session));
if (originalExpirationTimeInMilli != null) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2019 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.
@@ -42,13 +42,13 @@ import org.springframework.util.Assert;
*/
public class RedisSessionRepository implements SessionRepository<RedisSessionRepository.RedisSession> {
private static final String DEFAULT_KEY_NAMESPACE = "spring:session";
private static final String DEFAULT_KEY_NAMESPACE = "spring:session:";
private final RedisOperations<String, Object> sessionRedisOperations;
private Duration defaultMaxInactiveInterval = Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
private String keyNamespace = DEFAULT_KEY_NAMESPACE + ":";
private String keyNamespace = DEFAULT_KEY_NAMESPACE;
private FlushMode flushMode = FlushMode.ON_SAVE;
@@ -76,23 +76,12 @@ public class RedisSessionRepository implements SessionRepository<RedisSessionRep
/**
* Set the key namespace.
* @param keyNamespace the key namespace
* @deprecated since 2.4.0 in favor of {@link #setRedisKeyNamespace(String)}
*/
@Deprecated
public void setKeyNamespace(String keyNamespace) {
Assert.hasText(keyNamespace, "keyNamespace must not be empty");
this.keyNamespace = keyNamespace;
}
/**
* Set the Redis key namespace.
* @param namespace the Redis key namespace
*/
public void setRedisKeyNamespace(String namespace) {
Assert.hasText(namespace, "namespace must not be empty");
this.keyNamespace = namespace.trim() + ":";
}
/**
* Set the flush mode.
* @param flushMode the flush mode

View File

@@ -43,7 +43,7 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Tests for {@link ReactiveRedisSessionRepository}.
@@ -137,8 +137,8 @@ class ReactiveRedisSessionRepositoryTests {
verify(this.redisOperations).opsForHash();
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
verify(this.redisOperations).expire(anyString(), any());
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.hashOperations);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
Map<String, Object> delta = this.delta.getAllValues().get(0);
assertThat(delta.size()).isEqualTo(3);
@@ -160,8 +160,8 @@ class ReactiveRedisSessionRepositoryTests {
StepVerifier.create(this.repository.save(session)).verifyComplete();
verify(this.redisOperations).hasKey(anyString());
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.hashOperations);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
}
@Test
@@ -179,8 +179,8 @@ class ReactiveRedisSessionRepositoryTests {
verify(this.redisOperations).opsForHash();
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
verify(this.redisOperations).expire(anyString(), any());
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.hashOperations);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
assertThat(this.delta.getAllValues().get(0)).isEqualTo(
map(RedisSessionMapper.LAST_ACCESSED_TIME_KEY, session.getLastAccessedTime().toEpochMilli()));
@@ -202,8 +202,8 @@ class ReactiveRedisSessionRepositoryTests {
verify(this.redisOperations).opsForHash();
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
verify(this.redisOperations).expire(anyString(), any());
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.hashOperations);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
assertThat(this.delta.getAllValues().get(0)).isEqualTo(
map(RedisIndexedSessionRepository.getSessionAttrNameKey(attrName), session.getAttribute(attrName)));
@@ -225,8 +225,8 @@ class ReactiveRedisSessionRepositoryTests {
verify(this.redisOperations).opsForHash();
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
verify(this.redisOperations).expire(anyString(), any());
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.hashOperations);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
assertThat(this.delta.getAllValues().get(0))
.isEqualTo(map(RedisIndexedSessionRepository.getSessionAttrNameKey(attrName), null));
@@ -252,8 +252,8 @@ class ReactiveRedisSessionRepositoryTests {
StepVerifier.create(this.repository.deleteById("test")).verifyComplete();
verify(this.redisOperations).delete(anyString());
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.hashOperations);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
}
@Test
@@ -267,8 +267,8 @@ class ReactiveRedisSessionRepositoryTests {
verify(this.redisOperations).opsForHash();
verify(this.hashOperations).entries(anyString());
verify(this.redisOperations).delete(anyString());
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.hashOperations);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
}
@Test
@@ -291,8 +291,8 @@ class ReactiveRedisSessionRepositoryTests {
StepVerifier.create(this.repository.findById("test")).consumeNextWith((session) -> {
verify(this.redisOperations).opsForHash();
verify(this.hashOperations).entries(anyString());
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.hashOperations);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
assertThat(session.getId()).isEqualTo(expected.getId());
assertThat(session.getAttributeNames()).isEqualTo(expected.getAttributeNames());
@@ -320,8 +320,8 @@ class ReactiveRedisSessionRepositoryTests {
verify(this.redisOperations).opsForHash();
verify(this.hashOperations).entries(anyString());
verify(this.redisOperations).delete(anyString());
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.hashOperations);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
}
@Test // gh-1120
@@ -357,8 +357,8 @@ class ReactiveRedisSessionRepositoryTests {
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
assertThat(this.delta.getValue()).hasSize(1);
verify(this.redisOperations).expire(anyString(), any());
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.hashOperations);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
}
@Test
@@ -381,8 +381,8 @@ class ReactiveRedisSessionRepositoryTests {
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
assertThat(this.delta.getValue()).hasSize(2);
verify(this.redisOperations).expire(anyString(), any());
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.hashOperations);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
}
@Test
@@ -405,8 +405,8 @@ class ReactiveRedisSessionRepositoryTests {
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
assertThat(this.delta.getValue()).hasSize(3);
verify(this.redisOperations).expire(anyString(), any());
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.hashOperations);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
}
private Map<String, Object> map(Object... objects) {

View File

@@ -63,7 +63,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
class RedisIndexedSessionRepositoryTests {
@@ -188,7 +188,7 @@ class RedisIndexedSessionRepositoryTests {
this.redisRepository.save(session);
verifyNoMoreInteractions(this.redisOperations);
verifyZeroInteractions(this.redisOperations);
}
@Test
@@ -511,10 +511,10 @@ class RedisIndexedSessionRepositoryTests {
verify(this.boundHashOperations).entries();
verify(this.publisher).publishEvent(this.event.capture());
assertThat(this.event.getValue().getSessionId()).isEqualTo(deletedId);
verifyNoMoreInteractions(this.defaultSerializer);
verifyNoMoreInteractions(this.publisher);
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.boundHashOperations);
verifyZeroInteractions(this.defaultSerializer);
verifyZeroInteractions(this.publisher);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.boundHashOperations);
}
@Test
@@ -534,10 +534,10 @@ class RedisIndexedSessionRepositoryTests {
verify(this.redisOperations).boundHashOps(eq(getKey(deletedId)));
verify(this.boundHashOperations).entries();
verifyNoMoreInteractions(this.defaultSerializer);
verifyNoMoreInteractions(this.publisher);
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.boundHashOperations);
verifyZeroInteractions(this.defaultSerializer);
verifyZeroInteractions(this.publisher);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.boundHashOperations);
}
@Test
@@ -561,10 +561,10 @@ class RedisIndexedSessionRepositoryTests {
verify(this.boundHashOperations).entries();
verify(this.publisher).publishEvent(this.event.capture());
assertThat(this.event.getValue().getSessionId()).isEqualTo(expiredId);
verifyNoMoreInteractions(this.defaultSerializer);
verifyNoMoreInteractions(this.publisher);
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.boundHashOperations);
verifyZeroInteractions(this.defaultSerializer);
verifyZeroInteractions(this.publisher);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.boundHashOperations);
}
@Test
@@ -584,17 +584,17 @@ class RedisIndexedSessionRepositoryTests {
verify(this.redisOperations).boundHashOps(eq(getKey(expiredId)));
verify(this.boundHashOperations).entries();
verifyNoMoreInteractions(this.defaultSerializer);
verifyNoMoreInteractions(this.publisher);
verifyNoMoreInteractions(this.redisOperations);
verifyNoMoreInteractions(this.boundHashOperations);
verifyZeroInteractions(this.defaultSerializer);
verifyZeroInteractions(this.publisher);
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.boundHashOperations);
}
@Test
void flushModeOnSaveCreate() {
this.redisRepository.createSession();
verifyNoMoreInteractions(this.boundHashOperations);
verifyZeroInteractions(this.boundHashOperations);
}
@Test
@@ -602,7 +602,7 @@ class RedisIndexedSessionRepositoryTests {
RedisSession session = this.redisRepository.createSession();
session.setAttribute("something", "here");
verifyNoMoreInteractions(this.boundHashOperations);
verifyZeroInteractions(this.boundHashOperations);
}
@Test
@@ -610,7 +610,7 @@ class RedisIndexedSessionRepositoryTests {
RedisSession session = this.redisRepository.createSession();
session.removeAttribute("remove");
verifyNoMoreInteractions(this.boundHashOperations);
verifyZeroInteractions(this.boundHashOperations);
}
@Test
@@ -618,7 +618,7 @@ class RedisIndexedSessionRepositoryTests {
RedisSession session = this.redisRepository.createSession();
session.setLastAccessedTime(Instant.ofEpochMilli(1L));
verifyNoMoreInteractions(this.boundHashOperations);
verifyZeroInteractions(this.boundHashOperations);
}
@Test
@@ -626,7 +626,7 @@ class RedisIndexedSessionRepositoryTests {
RedisSession session = this.redisRepository.createSession();
session.setMaxInactiveInterval(Duration.ofSeconds(1));
verifyNoMoreInteractions(this.boundHashOperations);
verifyZeroInteractions(this.boundHashOperations);
}
@Test
@@ -790,7 +790,7 @@ class RedisIndexedSessionRepositoryTests {
this.redisRepository.onMessage(message, "".getBytes(StandardCharsets.UTF_8));
assertThat(this.event.getAllValues()).isEmpty();
verifyNoMoreInteractions(this.publisher);
verifyZeroInteractions(this.publisher);
}
@Test
@@ -808,7 +808,7 @@ class RedisIndexedSessionRepositoryTests {
this.redisRepository.onMessage(message, "".getBytes(StandardCharsets.UTF_8));
assertThat(this.event.getAllValues()).isEmpty();
verifyNoMoreInteractions(this.publisher);
verifyZeroInteractions(this.publisher);
}
@Test
@@ -826,7 +826,7 @@ class RedisIndexedSessionRepositoryTests {
this.redisRepository.onMessage(message, "".getBytes(StandardCharsets.UTF_8));
assertThat(this.event.getAllValues()).isEmpty();
verifyNoMoreInteractions(this.publisher);
verifyZeroInteractions(this.publisher);
}
@Test

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2021 the original author or authors.
* Copyright 2014-2019 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.
@@ -164,11 +164,4 @@ class RedisSessionExpirationPolicyTests {
verify(this.hashOperations).persist();
}
@Test
void onDeleteRemoveExpirationEntry() {
this.policy.onDelete(this.session);
verify(this.setOperations).remove("expires:" + this.session.getId());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2019 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.
@@ -102,36 +102,18 @@ class RedisSessionRepositoryTests {
assertThat(ReflectionTestUtils.getField(this.sessionRepository, "keyNamespace")).isEqualTo("test:");
}
@Test
void setRedisKeyNamespace_ValidNamespace_ShouldSetNamespace() {
this.sessionRepository.setRedisKeyNamespace("test");
assertThat(ReflectionTestUtils.getField(this.sessionRepository, "keyNamespace")).isEqualTo("test:");
}
@Test
void setKeyNamespace_NullNamespace_ShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.sessionRepository.setKeyNamespace(null))
.withMessage("keyNamespace must not be empty");
}
@Test
void setRedisKeyNamespace_NullNamespace_ShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.sessionRepository.setRedisKeyNamespace(null))
.withMessage("namespace must not be empty");
}
@Test
void setKeyNamespace_EmptyNamespace_ShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.sessionRepository.setKeyNamespace(" "))
.withMessage("keyNamespace must not be empty");
}
@Test
void setRedisKeyNamespace_EmptyNamespace_ShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.sessionRepository.setRedisKeyNamespace(" "))
.withMessage("namespace must not be empty");
}
@Test
void setFlushMode_ValidFlushMode_ShouldSetFlushMode() {
this.sessionRepository.setFlushMode(FlushMode.IMMEDIATE);
@@ -203,7 +185,7 @@ class RedisSessionRepositoryTests {
@Test
void save_NewSessionAndCustomKeyNamespace_ShouldSaveSession() {
this.sessionRepository.setRedisKeyNamespace("custom");
this.sessionRepository.setKeyNamespace("custom:");
RedisSession session = this.sessionRepository.createSession();
this.sessionRepository.save(session);
String key = "custom:sessions:" + session.getId();

View File

@@ -30,7 +30,7 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
class RedisHttpSessionConfigurationMockTests {
@@ -53,7 +53,7 @@ class RedisHttpSessionConfigurationMockTests {
init.afterPropertiesSet();
verifyNoMoreInteractions(this.factory);
verifyZeroInteractions(this.factory);
}
@Test

View File

@@ -41,7 +41,7 @@ asciidoctor {
}
asciidoctorj {
def ghTag = snapshotBuild ? 'main' : project.version
def ghTag = snapshotBuild ? 'master' : project.version
def ghUrl = "https://github.com/spring-projects/spring-session/tree/$ghTag"
attributes 'docs-itest-dir': "$rootProject.projectDir.path/spring-session-docs/src/integration-test/java/",
@@ -65,7 +65,3 @@ asciidoctorj {
'highlightjsdir@': "js/highlight",
'docinfodir@': "."
}
repositories {
maven { url "https://repo.spring.io/release" }
}

View File

@@ -507,7 +507,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
====
To be detected by Spring WebFlux, this custom `WebSessionStore` needs to be registered with `ApplicationContext` as a bean named `webSessionManager`.
For additional information on Spring WebFlux, see the https://docs.spring.io/spring-framework/docs/{spring-framework-version}/reference/html/web-reactive.html[Spring Framework Reference Documentation].
For additional information on Spring WebFlux, see the https://docs.spring.io/spring/docs/{spring-framework-version}/spring-framework-reference/web-reactive.html[Spring Framework Reference Documentation].
[[spring-security]]
== Spring Security Integration
@@ -791,7 +791,7 @@ HMSET spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe creationTime
maxInactiveInterval 1800 \
lastAccessedTime 1404360000000 \
sessionAttr:attrName someAttrValue \
sessionAttr:attrName2 someAttrValue2
sessionAttr2:attrName someAttrValue2
EXPIRE spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe 2100
APPEND spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe ""
EXPIRE spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe 1800
@@ -814,7 +814,7 @@ HMSET spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe creationTime
maxInactiveInterval 1800 \
lastAccessedTime 1404360000000 \
sessionAttr:attrName someAttrValue \
sessionAttr:attrName2 someAttrValue2
sessionAttr2:attrName someAttrValue2
----
====
@@ -833,7 +833,7 @@ The second session attribute is named `attrName2`, with a value of `someAttrValu
The `Session` instances managed by `RedisIndexedSessionRepository` keeps track of the properties that have changed and updates only those.
This means that, if an attribute is written once and read many times, we need to write that attribute only once.
For example, assume the `attrName2` session attribute from the lsiting in the preceding section was updated.
For example, assume the `sessionAttr2` session attribute from the lsiting in the preceding section was updated.
The following command would be run upon saving:
====
@@ -1302,7 +1302,7 @@ WARNING: You should only match on valid domain characters, since the domain name
Doing so prevents a malicious user from performing such attacks as https://en.wikipedia.org/wiki/HTTP_response_splitting[HTTP Response Splitting].
[[custom-sessionrepository]]
== Customizing `SessionRepository`
== Customing `SessionRepository`
Implementing a custom <<api-sessionrepository,`SessionRepository`>> API should be a fairly straightforward task.
Coupling the custom implementation with <<api-enablespringhttpsession,`@EnableSpringHttpSession`>> support lets you reuse existing Spring Session configuration facilities and infrastructure.
@@ -1406,8 +1406,11 @@ Spring Session is Open Source software released under the https://www.apache.org
|===
| Name | Location
| Spring Session OrientDB
| https://github.com/maseev/spring-session-orientdb
| Spring Session Infinispan
| https://infinispan.org/infinispan-spring-boot/master/spring_boot_starter.html#_enabling_spring_session_support
| https://infinispan.org/docs/dev/user_guide/user_guide.html#externalizing_session_using_spring_session
|===

View File

@@ -31,7 +31,7 @@ artifacts {
dependencies {
compile project(':spring-session-core')
optional "com.hazelcast:hazelcast:4.2.2"
optional "com.hazelcast:hazelcast:4.0.3"
compile "org.springframework:spring-context"
compile "javax.annotation:javax.annotation-api"
@@ -42,7 +42,7 @@ dependencies {
testRuntime "org.junit.jupiter:junit-jupiter-engine"
integrationTestCompile "org.testcontainers:testcontainers"
integrationTestCompile "com.hazelcast:hazelcast:4.2"
integrationTestCompile "com.hazelcast:hazelcast:4.0.3"
integrationTestCompile project(":spring-session-hazelcast")
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2021 the original author or authors.
* Copyright 2014-2020 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.
@@ -45,7 +45,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
@WebAppConfiguration
class ClientServerHazelcast4IndexedSessionRepositoryITests extends AbstractHazelcast4IndexedSessionRepositoryITests {
private static GenericContainer container = new GenericContainer<>("hazelcast/hazelcast:4.2.2")
private static GenericContainer container = new GenericContainer<>("hazelcast/hazelcast:4.0.2")
.withExposedPorts(5701).withCopyFileToContainer(MountableFile.forClasspathResource("/hazelcast-server.xml"),
"/opt/hazelcast/hazelcast.xml");

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<hazelcast xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.hazelcast.com/schema/config https://www.hazelcast.com/schema/config/hazelcast-config-4.2.xsd">
xsi:schemaLocation="http://www.hazelcast.com/schema/config https://www.hazelcast.com/schema/config/hazelcast-config-4.0.xsd">
<network>
<join>

View File

@@ -54,7 +54,7 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Tests for {@link Hazelcast4IndexedSessionRepository}.
@@ -98,7 +98,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
assertThat(session.getMaxInactiveInterval()).isEqualTo(new MapSession().getMaxInactiveInterval());
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -111,7 +111,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(interval));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -119,12 +119,12 @@ class Hazelcast4IndexedSessionRepositoryTests {
verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean());
HazelcastSession session = this.repository.createSession();
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
this.repository.save(session);
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
eq(TimeUnit.SECONDS));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -136,7 +136,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
eq(TimeUnit.SECONDS));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -145,12 +145,12 @@ class Hazelcast4IndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
session.setAttribute("testName", "testValue");
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
this.repository.save(session);
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
eq(TimeUnit.SECONDS));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -166,7 +166,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
verify(this.sessions, times(1)).executeOnKey(eq(session.getId()), any(EntryProcessor.class));
this.repository.save(session);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -175,12 +175,12 @@ class Hazelcast4IndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
session.removeAttribute("testName");
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
this.repository.save(session);
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
eq(TimeUnit.SECONDS));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -196,7 +196,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
verify(this.sessions, times(1)).executeOnKey(eq(session.getId()), any(EntryProcessor.class));
this.repository.save(session);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -205,12 +205,12 @@ class Hazelcast4IndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
session.setLastAccessedTime(Instant.now());
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
this.repository.save(session);
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
eq(TimeUnit.SECONDS));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -226,7 +226,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
verify(this.sessions, times(1)).executeOnKey(eq(session.getId()), any(EntryProcessor.class));
this.repository.save(session);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -235,12 +235,12 @@ class Hazelcast4IndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
session.setMaxInactiveInterval(Duration.ofSeconds(1));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
this.repository.save(session);
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
eq(TimeUnit.SECONDS));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -258,7 +258,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
verify(this.sessions, times(1)).executeOnKey(eq(sessionId), any(EntryProcessor.class));
this.repository.save(session);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -271,7 +271,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
eq(TimeUnit.SECONDS));
this.repository.save(session);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -285,7 +285,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
eq(TimeUnit.SECONDS));
this.repository.save(session);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -298,7 +298,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
assertThat(session).isNull();
verify(this.sessions, times(1)).get(eq(sessionId));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -314,7 +314,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
assertThat(session).isNull();
verify(this.sessions, times(1)).get(eq(expired.getId()));
verify(this.sessions, times(1)).remove(eq(expired.getId()));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -330,7 +330,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
assertThat(session.getId()).isEqualTo(saved.getId());
assertThat(session.<String>getAttribute("savedName")).isEqualTo("savedValue");
verify(this.sessions, times(1)).get(eq(saved.getId()));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -342,7 +342,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
this.repository.deleteById(sessionId);
verify(this.sessions, times(1)).remove(eq(sessionId));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -355,7 +355,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
indexValue);
assertThat(sessions).isEmpty();
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -369,7 +369,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
assertThat(sessions).isEmpty();
verify(this.sessions, times(1)).values(isA(EqualPredicate.class));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -393,7 +393,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
assertThat(sessions).hasSize(2);
verify(this.sessions, times(1)).values(isA(EqualPredicate.class));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test // gh-1120
@@ -426,7 +426,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
.forClass(Hazelcast4SessionUpdateEntryProcessor.class);
verify(this.sessions).executeOnKey(eq(session.getId()), captor.capture());
assertThat((Map<String, Object>) ReflectionTestUtils.getField(captor.getValue(), "delta")).hasSize(1);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -446,7 +446,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
.forClass(Hazelcast4SessionUpdateEntryProcessor.class);
verify(this.sessions).executeOnKey(eq(session.getId()), captor.capture());
assertThat((Map<String, Object>) ReflectionTestUtils.getField(captor.getValue(), "delta")).hasSize(2);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -466,7 +466,7 @@ class Hazelcast4IndexedSessionRepositoryTests {
.forClass(Hazelcast4SessionUpdateEntryProcessor.class);
verify(this.sessions).executeOnKey(eq(session.getId()), captor.capture());
assertThat((Map<String, Object>) ReflectionTestUtils.getField(captor.getValue(), "delta")).hasSize(3);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
}

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<hazelcast xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.hazelcast.com/schema/config https://www.hazelcast.com/schema/config/hazelcast-config-3.13.xsd">
xsi:schemaLocation="http://www.hazelcast.com/schema/config https://www.hazelcast.com/schema/config/hazelcast-config-3.12.xsd">
<network>
<join>

View File

@@ -54,7 +54,7 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Tests for {@link HazelcastIndexedSessionRepository}.
@@ -99,7 +99,7 @@ class HazelcastIndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
assertThat(session.getMaxInactiveInterval()).isEqualTo(new MapSession().getMaxInactiveInterval());
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -112,7 +112,7 @@ class HazelcastIndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(interval));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -120,12 +120,12 @@ class HazelcastIndexedSessionRepositoryTests {
verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean());
HazelcastSession session = this.repository.createSession();
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
this.repository.save(session);
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
eq(TimeUnit.SECONDS));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -137,7 +137,7 @@ class HazelcastIndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
eq(TimeUnit.SECONDS));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -146,12 +146,12 @@ class HazelcastIndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
session.setAttribute("testName", "testValue");
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
this.repository.save(session);
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
eq(TimeUnit.SECONDS));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -167,7 +167,7 @@ class HazelcastIndexedSessionRepositoryTests {
verify(this.sessions, times(1)).executeOnKey(eq(session.getId()), any(EntryProcessor.class));
this.repository.save(session);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -176,12 +176,12 @@ class HazelcastIndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
session.removeAttribute("testName");
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
this.repository.save(session);
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
eq(TimeUnit.SECONDS));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -197,7 +197,7 @@ class HazelcastIndexedSessionRepositoryTests {
verify(this.sessions, times(1)).executeOnKey(eq(session.getId()), any(EntryProcessor.class));
this.repository.save(session);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -206,12 +206,12 @@ class HazelcastIndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
session.setLastAccessedTime(Instant.now());
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
this.repository.save(session);
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
eq(TimeUnit.SECONDS));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -227,7 +227,7 @@ class HazelcastIndexedSessionRepositoryTests {
verify(this.sessions, times(1)).executeOnKey(eq(session.getId()), any(EntryProcessor.class));
this.repository.save(session);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -236,12 +236,12 @@ class HazelcastIndexedSessionRepositoryTests {
HazelcastSession session = this.repository.createSession();
session.setMaxInactiveInterval(Duration.ofSeconds(1));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
this.repository.save(session);
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
eq(TimeUnit.SECONDS));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -259,7 +259,7 @@ class HazelcastIndexedSessionRepositoryTests {
verify(this.sessions, times(1)).executeOnKey(eq(sessionId), any(EntryProcessor.class));
this.repository.save(session);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -272,7 +272,7 @@ class HazelcastIndexedSessionRepositoryTests {
eq(TimeUnit.SECONDS));
this.repository.save(session);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -286,7 +286,7 @@ class HazelcastIndexedSessionRepositoryTests {
eq(TimeUnit.SECONDS));
this.repository.save(session);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -299,7 +299,7 @@ class HazelcastIndexedSessionRepositoryTests {
assertThat(session).isNull();
verify(this.sessions, times(1)).get(eq(sessionId));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -315,7 +315,7 @@ class HazelcastIndexedSessionRepositoryTests {
assertThat(session).isNull();
verify(this.sessions, times(1)).get(eq(expired.getId()));
verify(this.sessions, times(1)).remove(eq(expired.getId()));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -331,7 +331,7 @@ class HazelcastIndexedSessionRepositoryTests {
assertThat(session.getId()).isEqualTo(saved.getId());
assertThat(session.<String>getAttribute("savedName")).isEqualTo("savedValue");
verify(this.sessions, times(1)).get(eq(saved.getId()));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -343,7 +343,7 @@ class HazelcastIndexedSessionRepositoryTests {
this.repository.deleteById(sessionId);
verify(this.sessions, times(1)).remove(eq(sessionId));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -356,7 +356,7 @@ class HazelcastIndexedSessionRepositoryTests {
indexValue);
assertThat(sessions).isEmpty();
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -370,7 +370,7 @@ class HazelcastIndexedSessionRepositoryTests {
assertThat(sessions).isEmpty();
verify(this.sessions, times(1)).values(isA(EqualPredicate.class));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -394,7 +394,7 @@ class HazelcastIndexedSessionRepositoryTests {
assertThat(sessions).hasSize(2);
verify(this.sessions, times(1)).values(isA(EqualPredicate.class));
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test // gh-1120
@@ -426,7 +426,7 @@ class HazelcastIndexedSessionRepositoryTests {
ArgumentCaptor<SessionUpdateEntryProcessor> captor = ArgumentCaptor.forClass(SessionUpdateEntryProcessor.class);
verify(this.sessions).executeOnKey(eq(session.getId()), captor.capture());
assertThat((Map<String, Object>) ReflectionTestUtils.getField(captor.getValue(), "delta")).hasSize(1);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -445,7 +445,7 @@ class HazelcastIndexedSessionRepositoryTests {
ArgumentCaptor<SessionUpdateEntryProcessor> captor = ArgumentCaptor.forClass(SessionUpdateEntryProcessor.class);
verify(this.sessions).executeOnKey(eq(session.getId()), captor.capture());
assertThat((Map<String, Object>) ReflectionTestUtils.getField(captor.getValue(), "delta")).hasSize(2);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
@Test
@@ -464,7 +464,7 @@ class HazelcastIndexedSessionRepositoryTests {
ArgumentCaptor<SessionUpdateEntryProcessor> captor = ArgumentCaptor.forClass(SessionUpdateEntryProcessor.class);
verify(this.sessions).executeOnKey(eq(session.getId()), captor.capture());
assertThat((Map<String, Object>) ReflectionTestUtils.getField(captor.getValue(), "delta")).hasSize(3);
verifyNoMoreInteractions(this.sessions);
verifyZeroInteractions(this.sessions);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2019 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.
@@ -29,15 +29,8 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import org.springframework.jdbc.support.lob.LobCreator;
import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
@@ -45,7 +38,6 @@ import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.MapSession;
import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.jdbc.JdbcIndexedSessionRepository.JdbcSession;
import org.springframework.session.jdbc.config.annotation.web.http.EnableJdbcHttpSession;
import org.springframework.test.util.ReflectionTestUtils;
@@ -53,8 +45,6 @@ import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Base class for {@link JdbcIndexedSessionRepository} integration tests.
@@ -67,27 +57,15 @@ abstract class AbstractJdbcIndexedSessionRepositoryITests {
private static final String INDEX_NAME = FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private DataSource dataSource;
@Autowired
private JdbcIndexedSessionRepository repository;
private JdbcOperations jdbcOperations;
private LobHandler lobHandler;
private SecurityContext context;
private SecurityContext changedContext;
@BeforeEach
void setUp() {
this.jdbcOperations = new JdbcTemplate(this.dataSource);
this.lobHandler = new DefaultLobHandler();
this.context = SecurityContextHolder.createEmptyContext();
this.context.setAuthentication(new UsernamePasswordAuthenticationToken("username-" + UUID.randomUUID(), "na",
AuthorityUtils.createAuthorityList("ROLE_USER")));
@@ -586,18 +564,6 @@ abstract class AbstractJdbcIndexedSessionRepositoryITests {
assertThat(this.repository.findById(session.getId())).isNull();
}
@Test
void cleanupExpiredSessionsWhenMaxInactiveIntervalNegativeThenSessionNotDeleted() {
JdbcSession session = this.repository.createSession();
session.setMaxInactiveInterval(Duration.ofSeconds(-1));
session.setLastAccessedTime(Instant.now().minusSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS + 1));
this.repository.save(session);
this.repository.cleanUpExpiredSessions();
assertThat(this.repository.findById(session.getId())).isNotNull();
}
@Test
void changeSessionIdWhenOnlyChangeId() {
String attrName = "changeSessionId";
@@ -793,32 +759,6 @@ abstract class AbstractJdbcIndexedSessionRepositoryITests {
assertThat((byte[]) session.getAttribute(attributeName)).hasSize(arraySize);
}
@Test // gh-1213
void saveNewSessionAttributeConcurrently() {
JdbcSession session = this.repository.createSession();
this.repository.save(session);
String attributeName = "attribute1";
String attributeValue = "value1";
try (LobCreator lobCreator = this.lobHandler.getLobCreator()) {
this.jdbcOperations.update("INSERT INTO SPRING_SESSION_ATTRIBUTES VALUES (?, ?, ?)", (ps) -> {
ps.setString(1, (String) ReflectionTestUtils.getField(session, "primaryKey"));
ps.setString(2, attributeName);
lobCreator.setBlobAsBytes(ps, 3, "value2".getBytes());
});
}
session.setAttribute(attributeName, attributeValue);
if (this.applicationContext.getBeansOfType(SessionRepositoryCustomizer.class).isEmpty()) {
// without DB specific upsert configured we're seeing duplicate key error
assertThatExceptionOfType(DuplicateKeyException.class).isThrownBy(() -> this.repository.save(session));
}
else {
// with DB specific upsert configured we're fine
assertThatCode(() -> this.repository.save(session)).doesNotThrowAnyException();
assertThat((String) this.repository.findById(session.getId()).getAttribute(attributeName))
.isEqualTo(attributeValue);
}
}
private String getSecurityName() {
return this.context.getAuthentication().getName();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2019 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.
@@ -17,6 +17,7 @@
package org.springframework.session.jdbc;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import org.testcontainers.containers.Db2Container;
import org.testcontainers.containers.JdbcDatabaseContainer;
@@ -37,42 +38,169 @@ final class DatabaseContainers {
private DatabaseContainers() {
}
static Db2Container db2() {
return new Db2Container("ibmcom/db2:11.5.4.0");
static Db211Container db211() {
return new Db211Container();
}
static MariaDBContainer<?> mariaDb() {
return new MariaDBContainer<>("mariadb:10.6.4");
static MariaDBContainer mariaDb5() {
return new MariaDb5Container();
}
static MySQLContainer<?> mySql() {
return new MySQLContainer<>("mysql:8.0.26");
static MariaDBContainer mariaDb10() {
return new MariaDb10Container();
}
static OracleContainer oracle() {
return new OracleContainer() {
@Override
protected void configure() {
this.waitStrategy = new LogMessageWaitStrategy().withRegEx(".*DATABASE IS READY TO USE!.*\\s")
.withStartupTimeout(Duration.ofMinutes(10));
addEnv("ORACLE_PWD", getPassword());
}
@Override
protected void waitUntilContainerStarted() {
getWaitStrategy().waitUntilReady(this);
}
};
static MySQLContainer mySql5() {
return new MySql5Container();
}
static PostgreSQLContainer<?> postgreSql() {
return new PostgreSQLContainer<>("postgres:13.3");
static MySQLContainer mySql8() {
return new MySql8Container();
}
static MSSQLServerContainer<?> sqlServer() {
return new MSSQLServerContainer<>("mcr.microsoft.com/mssql/server:2019-CU8-ubuntu-16.04");
static OracleXeContainer oracleXe() {
return new OracleXeContainer();
}
static PostgreSQLContainer postgreSql9() {
return new PostgreSql9Container();
}
static PostgreSQLContainer postgreSql10() {
return new PostgreSql10Container();
}
static PostgreSQLContainer postgreSql11() {
return new PostgreSql11Container();
}
static MSSQLServerContainer sqlServer2017() {
return new SqlServer2017Container();
}
private static class Db211Container extends Db2Container {
Db211Container() {
super("ibmcom/db2:11.5.0.0a");
}
}
private static class MariaDb5Container extends MariaDBContainer<MariaDb5Container> {
MariaDb5Container() {
super("mariadb:5.5.64");
}
@Override
protected void configure() {
super.configure();
setCommand("mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci",
"--innodb_large_prefix", "--innodb_file_format=barracuda", "--innodb-file-per-table");
}
}
private static class MariaDb10Container extends MariaDBContainer<MariaDb10Container> {
MariaDb10Container() {
super("mariadb:10.4.8");
}
@Override
protected void configure() {
super.configure();
setCommand("mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci");
}
}
private static class MySql5Container extends MySQLContainer<MySql5Container> {
MySql5Container() {
super("mysql:5.7.34");
}
@Override
protected void configure() {
super.configure();
setCommand("mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci");
}
@Override
public String getDriverClassName() {
return "com.mysql.cj.jdbc.Driver";
}
}
private static class MySql8Container extends MySQLContainer<MySql8Container> {
MySql8Container() {
super("mysql:8.0.25");
}
@Override
protected void configure() {
super.configure();
setCommand("mysqld", "--default-authentication-plugin=mysql_native_password");
}
@Override
public String getDriverClassName() {
return "com.mysql.cj.jdbc.Driver";
}
}
private static class OracleXeContainer extends OracleContainer {
@Override
protected void configure() {
super.configure();
this.waitStrategy = new LogMessageWaitStrategy().withRegEx(".*DATABASE IS READY TO USE!.*\\s")
.withStartupTimeout(Duration.of(10, ChronoUnit.MINUTES));
setShmSize(1024L * 1024L * 1024L);
addEnv("ORACLE_PWD", getPassword());
}
@Override
protected void waitUntilContainerStarted() {
getWaitStrategy().waitUntilReady(this);
}
}
private static class PostgreSql9Container extends PostgreSQLContainer<PostgreSql9Container> {
PostgreSql9Container() {
super("postgres:9.6.22");
}
}
private static class PostgreSql10Container extends PostgreSQLContainer<PostgreSql10Container> {
PostgreSql10Container() {
super("postgres:10.10");
}
}
private static class PostgreSql11Container extends PostgreSQLContainer<PostgreSql11Container> {
PostgreSql11Container() {
super("postgres:11.5");
}
}
private static class SqlServer2017Container extends MSSQLServerContainer<SqlServer2017Container> {
SqlServer2017Container() {
super("mcr.microsoft.com/mssql/server:2017-CU16");
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2019 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.
@@ -27,21 +27,21 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using IBM DB2 database.
* Integration tests for {@link JdbcIndexedSessionRepository} using IBM DB2 11.x database.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class Db2JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
class Db211JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
@Configuration
static class Config extends BaseContainerConfig {
@Bean
Db2Container databaseContainer() {
Db2Container databaseContainer = DatabaseContainers.db2();
Db2Container databaseContainer = DatabaseContainers.db211();
databaseContainer.start();
return databaseContainer;
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2014-2020 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
*
* https://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.jdbc;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using IBM DB2 database with
* {@link Db2JdbcIndexedSessionRepositoryCustomizer}.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class Db2JdbcIndexedSessionRepositoryCustomizerITests extends Db2JdbcIndexedSessionRepositoryITests {
@Configuration
static class CustomizerConfig extends Config {
@Bean
Db2JdbcIndexedSessionRepositoryCustomizer db2JdbcIndexedSessionRepositoryCustomizer() {
return new Db2JdbcIndexedSessionRepositoryCustomizer();
}
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2014-2019 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
*
* https://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.jdbc;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testcontainers.containers.MariaDBContainer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using MariaDB 10.x database.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class MariaDb10JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
@Configuration
static class Config extends BaseContainerConfig {
@Bean
MariaDBContainer databaseContainer() {
MariaDBContainer databaseContainer = DatabaseContainers.mariaDb10();
databaseContainer.start();
return databaseContainer;
}
@Bean
ResourceDatabasePopulator databasePopulator() {
return DatabasePopulators.mySql();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2019 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.
@@ -27,21 +27,21 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using MariaDB database.
* Integration tests for {@link JdbcIndexedSessionRepository} using MariaDB 5.x database.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class MariaDbJdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
class MariaDb5JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
@Configuration
static class Config extends BaseContainerConfig {
@Bean
MariaDBContainer<?> databaseContainer() {
MariaDBContainer<?> databaseContainer = DatabaseContainers.mariaDb();
MariaDBContainer databaseContainer() {
MariaDBContainer databaseContainer = DatabaseContainers.mariaDb5();
databaseContainer.start();
return databaseContainer;
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2014-2020 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
*
* https://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.jdbc;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using MariaDB database with
* {@link MySqlJdbcIndexedSessionRepositoryCustomizer}.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class MariaDbJdbcIndexedSessionRepositoryCustomizerITests extends MariaDbJdbcIndexedSessionRepositoryITests {
@Configuration
static class CustomizerConfig extends Config {
@Bean
MySqlJdbcIndexedSessionRepositoryCustomizer mySqlJdbcIndexedSessionRepositoryCustomizer() {
return new MySqlJdbcIndexedSessionRepositoryCustomizer();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2019 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.
@@ -27,21 +27,21 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using MySQL database.
* Integration tests for {@link JdbcIndexedSessionRepository} using MySQL 5.x database.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class MySqlJdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
class MySql5JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
@Configuration
static class Config extends BaseContainerConfig {
@Bean
MySQLContainer<?> databaseContainer() {
MySQLContainer<?> databaseContainer = DatabaseContainers.mySql();
MySQLContainer databaseContainer() {
MySQLContainer databaseContainer = DatabaseContainers.mySql5();
databaseContainer.start();
return databaseContainer;
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2014-2019 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
*
* https://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.jdbc;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testcontainers.containers.MySQLContainer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using MySQL 8.x database.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class MySql8JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
@Configuration
static class Config extends BaseContainerConfig {
@Bean
MySQLContainer databaseContainer() {
MySQLContainer databaseContainer = DatabaseContainers.mySql8();
databaseContainer.start();
return databaseContainer;
}
@Bean
ResourceDatabasePopulator databasePopulator() {
return DatabasePopulators.mySql();
}
}
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2014-2020 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
*
* https://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.jdbc;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using MySQL database with
* {@link MySqlJdbcIndexedSessionRepositoryCustomizer}.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class MySqlJdbcIndexedSessionRepositoryCustomizerITests extends MySqlJdbcIndexedSessionRepositoryITests {
@Configuration
static class CustomizerConfig extends Config {
@Bean
MySqlJdbcIndexedSessionRepositoryCustomizer mySqlJdbcIndexedSessionRepositoryCustomizer() {
return new MySqlJdbcIndexedSessionRepositoryCustomizer();
}
}
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2014-2020 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
*
* https://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.jdbc;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using Oracle database with
* {@link OracleJdbcIndexedSessionRepositoryCustomizer}.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class OracleJdbcIndexedSessionRepositoryCustomizerITests extends OracleJdbcIndexedSessionRepositoryITests {
@Configuration
static class CustomizerConfig extends Config {
@Bean
OracleJdbcIndexedSessionRepositoryCustomizer oracleJdbcIndexedSessionRepositoryCustomizer() {
return new OracleJdbcIndexedSessionRepositoryCustomizer();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2019 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.
@@ -54,7 +54,7 @@ class OracleJdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcInde
@Bean
OracleContainer databaseContainer() {
OracleContainer databaseContainer = DatabaseContainers.oracle();
OracleContainer databaseContainer = DatabaseContainers.oracleXe();
databaseContainer.start();
return databaseContainer;
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2014-2019 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
*
* https://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.jdbc;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testcontainers.containers.PostgreSQLContainer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using PostgreSQL 10.x
* database.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class PostgreSql10JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
@Configuration
static class Config extends BaseContainerConfig {
@Bean
PostgreSQLContainer databaseContainer() {
PostgreSQLContainer databaseContainer = DatabaseContainers.postgreSql10();
databaseContainer.start();
return databaseContainer;
}
@Bean
ResourceDatabasePopulator databasePopulator() {
return DatabasePopulators.postgreSql();
}
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2014-2019 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
*
* https://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.jdbc;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testcontainers.containers.PostgreSQLContainer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using PostgreSQL 11.x
* database.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class PostgreSql11JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
@Configuration
static class Config extends BaseContainerConfig {
@Bean
PostgreSQLContainer databaseContainer() {
PostgreSQLContainer databaseContainer = DatabaseContainers.postgreSql11();
databaseContainer.start();
return databaseContainer;
}
@Bean
ResourceDatabasePopulator databasePopulator() {
return DatabasePopulators.postgreSql();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2019 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.
@@ -27,21 +27,22 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using PostgreSQL database.
* Integration tests for {@link JdbcIndexedSessionRepository} using PostgreSQL 9.x
* database.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class PostgreSqlJdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
class PostgreSql9JdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcIndexedSessionRepositoryITests {
@Configuration
static class Config extends BaseContainerConfig {
@Bean
PostgreSQLContainer<?> databaseContainer() {
PostgreSQLContainer<?> databaseContainer = DatabaseContainers.postgreSql();
PostgreSQLContainer databaseContainer() {
PostgreSQLContainer databaseContainer = DatabaseContainers.postgreSql9();
databaseContainer.start();
return databaseContainer;
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2014-2020 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
*
* https://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.jdbc;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using PostgreSQL database
* with {@link PostgreSqlJdbcIndexedSessionRepositoryCustomizer}.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class PostgreSqlJdbcIndexedSessionRepositoryCustomizerITests extends PostgreSqlJdbcIndexedSessionRepositoryITests {
@Configuration
static class CustomizerConfig extends Config {
@Bean
PostgreSqlJdbcIndexedSessionRepositoryCustomizer postgreSqlJdbcIndexedSessionRepositoryCustomizer() {
return new PostgreSqlJdbcIndexedSessionRepositoryCustomizer();
}
}
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2014-2020 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
*
* https://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.jdbc;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* Integration tests for {@link JdbcIndexedSessionRepository} using SQL Server database
* with {@link SqlServerJdbcIndexedSessionRepositoryCustomizer}.
*
* @author Vedran Pavic
*/
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
@ContextConfiguration
class SqlServerJdbcIndexedSessionRepositoryCustomizerITests extends SqlServerJdbcIndexedSessionRepositoryITests {
@Configuration
static class CustomizerConfig extends Config {
@Bean
SqlServerJdbcIndexedSessionRepositoryCustomizer sqlServerJdbcIndexedSessionRepositoryCustomizer() {
return new SqlServerJdbcIndexedSessionRepositoryCustomizer();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2019 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.
@@ -41,8 +41,8 @@ class SqlServerJdbcIndexedSessionRepositoryITests extends AbstractContainerJdbcI
static class Config extends BaseContainerConfig {
@Bean
MSSQLServerContainer<?> databaseContainer() {
MSSQLServerContainer<?> databaseContainer = DatabaseContainers.sqlServer();
MSSQLServerContainer databaseContainer() {
MSSQLServerContainer databaseContainer = DatabaseContainers.sqlServer2017();
databaseContainer.start();
return databaseContainer;
}

View File

@@ -1,2 +1,2 @@
ibmcom/db2:11.5.4.0
mcr.microsoft.com/mssql/server:2019-CU8-ubuntu-16.04
ibmcom/db2:11.5.0.0a
mcr.microsoft.com/mssql/server:2017-CU16

View File

@@ -1,50 +0,0 @@
/*
* Copyright 2014-2020 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
*
* https://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.jdbc;
import org.springframework.session.config.SessionRepositoryCustomizer;
/**
* A {@link SessionRepositoryCustomizer} implementation that applies IBM DB2 specific
* optimized SQL statements to {@link JdbcIndexedSessionRepository}.
*
* @author Vedran Pavic
* @since 2.5.0
*/
public class Db2JdbcIndexedSessionRepositoryCustomizer
implements SessionRepositoryCustomizer<JdbcIndexedSessionRepository> {
// @formatter:off
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = ""
+ "MERGE INTO %TABLE_NAME%_ATTRIBUTES SA "
+ "USING ( "
+ " VALUES (?, ?, ?) "
+ ") A (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
+ "ON (SA.SESSION_PRIMARY_ID = A.SESSION_PRIMARY_ID and SA.ATTRIBUTE_NAME = A.ATTRIBUTE_NAME) "
+ "WHEN MATCHED THEN "
+ " UPDATE SET ATTRIBUTE_BYTES = A.ATTRIBUTE_BYTES "
+ "WHEN NOT MATCHED THEN "
+ " INSERT (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
+ " VALUES (A.SESSION_PRIMARY_ID, A.ATTRIBUTE_NAME, A.ATTRIBUTE_BYTES)";
// @formatter:on
@Override
public void customize(JdbcIndexedSessionRepository sessionRepository) {
sessionRepository.setCreateSessionAttributeQuery(CREATE_SESSION_ATTRIBUTE_QUERY);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2019 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.
@@ -40,8 +40,6 @@ import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.ResultSetExtractor;
@@ -141,65 +139,55 @@ public class JdbcIndexedSessionRepository
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
// @formatter:off
private static final String CREATE_SESSION_QUERY = ""
+ "INSERT INTO %TABLE_NAME% (PRIMARY_ID, SESSION_ID, CREATION_TIME, LAST_ACCESS_TIME, MAX_INACTIVE_INTERVAL, EXPIRY_TIME, PRINCIPAL_NAME) "
private static final String CREATE_SESSION_QUERY = "INSERT INTO %TABLE_NAME%(PRIMARY_ID, SESSION_ID, CREATION_TIME, LAST_ACCESS_TIME, MAX_INACTIVE_INTERVAL, EXPIRY_TIME, PRINCIPAL_NAME) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?)";
// @formatter:on
// @formatter:off
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = ""
+ "INSERT INTO %TABLE_NAME%_ATTRIBUTES (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
+ "VALUES (?, ?, ?)";
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = "INSERT INTO %TABLE_NAME%_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
+ "SELECT PRIMARY_ID, ?, ? "
+ "FROM %TABLE_NAME% "
+ "WHERE SESSION_ID = ?";
// @formatter:on
// @formatter:off
private static final String GET_SESSION_QUERY = ""
+ "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES "
private static final String GET_SESSION_QUERY = "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES "
+ "FROM %TABLE_NAME% S "
+ "LEFT JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID "
+ "LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID "
+ "WHERE S.SESSION_ID = ?";
// @formatter:on
// @formatter:off
private static final String UPDATE_SESSION_QUERY = ""
+ "UPDATE %TABLE_NAME% "
+ "SET SESSION_ID = ?, LAST_ACCESS_TIME = ?, MAX_INACTIVE_INTERVAL = ?, EXPIRY_TIME = ?, PRINCIPAL_NAME = ? "
private static final String UPDATE_SESSION_QUERY = "UPDATE %TABLE_NAME% SET SESSION_ID = ?, LAST_ACCESS_TIME = ?, MAX_INACTIVE_INTERVAL = ?, EXPIRY_TIME = ?, PRINCIPAL_NAME = ? "
+ "WHERE PRIMARY_ID = ?";
// @formatter:on
// @formatter:off
private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = ""
+ "UPDATE %TABLE_NAME%_ATTRIBUTES "
+ "SET ATTRIBUTE_BYTES = ? "
private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = "UPDATE %TABLE_NAME%_ATTRIBUTES SET ATTRIBUTE_BYTES = ? "
+ "WHERE SESSION_PRIMARY_ID = ? "
+ "AND ATTRIBUTE_NAME = ?";
// @formatter:on
// @formatter:off
private static final String DELETE_SESSION_ATTRIBUTE_QUERY = ""
+ "DELETE FROM %TABLE_NAME%_ATTRIBUTES "
private static final String DELETE_SESSION_ATTRIBUTE_QUERY = "DELETE FROM %TABLE_NAME%_ATTRIBUTES "
+ "WHERE SESSION_PRIMARY_ID = ? "
+ "AND ATTRIBUTE_NAME = ?";
// @formatter:on
// @formatter:off
private static final String DELETE_SESSION_QUERY = ""
+ "DELETE FROM %TABLE_NAME% "
+ "WHERE SESSION_ID = ? "
+ "AND MAX_INACTIVE_INTERVAL >= 0";
private static final String DELETE_SESSION_QUERY = "DELETE FROM %TABLE_NAME% "
+ "WHERE SESSION_ID = ?";
// @formatter:on
// @formatter:off
private static final String LIST_SESSIONS_BY_PRINCIPAL_NAME_QUERY = ""
+ "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES "
private static final String LIST_SESSIONS_BY_PRINCIPAL_NAME_QUERY = "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES "
+ "FROM %TABLE_NAME% S "
+ "LEFT JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID "
+ "LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID "
+ "WHERE S.PRINCIPAL_NAME = ?";
// @formatter:on
// @formatter:off
private static final String DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY = ""
+ "DELETE FROM %TABLE_NAME% "
private static final String DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY = "DELETE FROM %TABLE_NAME% "
+ "WHERE EXPIRY_TIME < ?";
// @formatter:on
@@ -280,7 +268,7 @@ public class JdbcIndexedSessionRepository
*/
public void setCreateSessionQuery(String createSessionQuery) {
Assert.hasText(createSessionQuery, "Query must not be empty");
this.createSessionQuery = getQuery(createSessionQuery);
this.createSessionQuery = createSessionQuery;
}
/**
@@ -289,7 +277,7 @@ public class JdbcIndexedSessionRepository
*/
public void setCreateSessionAttributeQuery(String createSessionAttributeQuery) {
Assert.hasText(createSessionAttributeQuery, "Query must not be empty");
this.createSessionAttributeQuery = getQuery(createSessionAttributeQuery);
this.createSessionAttributeQuery = createSessionAttributeQuery;
}
/**
@@ -298,7 +286,7 @@ public class JdbcIndexedSessionRepository
*/
public void setGetSessionQuery(String getSessionQuery) {
Assert.hasText(getSessionQuery, "Query must not be empty");
this.getSessionQuery = getQuery(getSessionQuery);
this.getSessionQuery = getSessionQuery;
}
/**
@@ -307,7 +295,7 @@ public class JdbcIndexedSessionRepository
*/
public void setUpdateSessionQuery(String updateSessionQuery) {
Assert.hasText(updateSessionQuery, "Query must not be empty");
this.updateSessionQuery = getQuery(updateSessionQuery);
this.updateSessionQuery = updateSessionQuery;
}
/**
@@ -316,7 +304,7 @@ public class JdbcIndexedSessionRepository
*/
public void setUpdateSessionAttributeQuery(String updateSessionAttributeQuery) {
Assert.hasText(updateSessionAttributeQuery, "Query must not be empty");
this.updateSessionAttributeQuery = getQuery(updateSessionAttributeQuery);
this.updateSessionAttributeQuery = updateSessionAttributeQuery;
}
/**
@@ -325,7 +313,7 @@ public class JdbcIndexedSessionRepository
*/
public void setDeleteSessionAttributeQuery(String deleteSessionAttributeQuery) {
Assert.hasText(deleteSessionAttributeQuery, "Query must not be empty");
this.deleteSessionAttributeQuery = getQuery(deleteSessionAttributeQuery);
this.deleteSessionAttributeQuery = deleteSessionAttributeQuery;
}
/**
@@ -334,7 +322,7 @@ public class JdbcIndexedSessionRepository
*/
public void setDeleteSessionQuery(String deleteSessionQuery) {
Assert.hasText(deleteSessionQuery, "Query must not be empty");
this.deleteSessionQuery = getQuery(deleteSessionQuery);
this.deleteSessionQuery = deleteSessionQuery;
}
/**
@@ -343,7 +331,7 @@ public class JdbcIndexedSessionRepository
*/
public void setListSessionsByPrincipalNameQuery(String listSessionsByPrincipalNameQuery) {
Assert.hasText(listSessionsByPrincipalNameQuery, "Query must not be empty");
this.listSessionsByPrincipalNameQuery = getQuery(listSessionsByPrincipalNameQuery);
this.listSessionsByPrincipalNameQuery = listSessionsByPrincipalNameQuery;
}
/**
@@ -352,7 +340,7 @@ public class JdbcIndexedSessionRepository
*/
public void setDeleteSessionsByExpiryTimeQuery(String deleteSessionsByExpiryTimeQuery) {
Assert.hasText(deleteSessionsByExpiryTimeQuery, "Query must not be empty");
this.deleteSessionsByExpiryTimeQuery = getQuery(deleteSessionsByExpiryTimeQuery);
this.deleteSessionsByExpiryTimeQuery = deleteSessionsByExpiryTimeQuery;
}
/**
@@ -475,49 +463,30 @@ public class JdbcIndexedSessionRepository
Assert.notEmpty(attributeNames, "attributeNames must not be null or empty");
try (LobCreator lobCreator = this.lobHandler.getLobCreator()) {
if (attributeNames.size() > 1) {
try {
this.jdbcOperations.batchUpdate(this.createSessionAttributeQuery,
new BatchPreparedStatementSetter() {
this.jdbcOperations.batchUpdate(this.createSessionAttributeQuery, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
String attributeName = attributeNames.get(i);
ps.setString(1, session.primaryKey);
ps.setString(2, attributeName);
lobCreator.setBlobAsBytes(ps, 3, serialize(session.getAttribute(attributeName)));
}
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
String attributeName = attributeNames.get(i);
ps.setString(1, attributeName);
lobCreator.setBlobAsBytes(ps, 2, serialize(session.getAttribute(attributeName)));
ps.setString(3, session.getId());
}
@Override
public int getBatchSize() {
return attributeNames.size();
}
@Override
public int getBatchSize() {
return attributeNames.size();
}
});
}
catch (DuplicateKeyException ex) {
throw ex;
}
catch (DataIntegrityViolationException ex) {
// parent record not found - we are ignoring this error because we
// assume that a concurrent request has removed the session
}
});
}
else {
try {
this.jdbcOperations.update(this.createSessionAttributeQuery, (ps) -> {
String attributeName = attributeNames.get(0);
ps.setString(1, session.primaryKey);
ps.setString(2, attributeName);
lobCreator.setBlobAsBytes(ps, 3, serialize(session.getAttribute(attributeName)));
});
}
catch (DuplicateKeyException ex) {
throw ex;
}
catch (DataIntegrityViolationException ex) {
// parent record not found - we are ignoring this error because we
// assume that a concurrent request has removed the session
}
this.jdbcOperations.update(this.createSessionAttributeQuery, (ps) -> {
String attributeName = attributeNames.get(0);
ps.setString(1, attributeName);
lobCreator.setBlobAsBytes(ps, 2, serialize(session.getAttribute(attributeName)));
ps.setString(3, session.getId());
});
}
}
}
@@ -702,9 +671,6 @@ public class JdbcIndexedSessionRepository
}
Instant getExpiryTime() {
if (getMaxInactiveInterval().isNegative()) {
return Instant.ofEpochMilli(Long.MAX_VALUE);
}
return getLastAccessedTime().plus(getMaxInactiveInterval());
}

View File

@@ -1,43 +0,0 @@
/*
* Copyright 2014-2020 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
*
* https://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.jdbc;
import org.springframework.session.config.SessionRepositoryCustomizer;
/**
* A {@link SessionRepositoryCustomizer} implementation that applies MySQL specific
* optimized SQL statements to {@link JdbcIndexedSessionRepository}.
*
* @author Vedran Pavic
* @since 2.5.0
*/
public class MySqlJdbcIndexedSessionRepositoryCustomizer
implements SessionRepositoryCustomizer<JdbcIndexedSessionRepository> {
// @formatter:off
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = ""
+ "INSERT INTO %TABLE_NAME%_ATTRIBUTES (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
+ "VALUES (?, ?, ?) "
+ "ON DUPLICATE KEY UPDATE ATTRIBUTE_BYTES = VALUES(ATTRIBUTE_BYTES)";
// @formatter:on
@Override
public void customize(JdbcIndexedSessionRepository sessionRepository) {
sessionRepository.setCreateSessionAttributeQuery(CREATE_SESSION_ATTRIBUTE_QUERY);
}
}

View File

@@ -1,51 +0,0 @@
/*
* Copyright 2014-2020 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
*
* https://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.jdbc;
import org.springframework.session.config.SessionRepositoryCustomizer;
/**
* A {@link SessionRepositoryCustomizer} implementation that applies Oracle specific
* optimized SQL statements to {@link JdbcIndexedSessionRepository}.
*
* @author Vedran Pavic
* @since 2.5.0
*/
public class OracleJdbcIndexedSessionRepositoryCustomizer
implements SessionRepositoryCustomizer<JdbcIndexedSessionRepository> {
// @formatter:off
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = ""
+ "MERGE INTO %TABLE_NAME%_ATTRIBUTES SA "
+ "USING ( "
+ " SELECT ? AS SESSION_PRIMARY_ID, ? AS ATTRIBUTE_NAME, ? AS ATTRIBUTE_BYTES "
+ " FROM DUAL "
+ ") A "
+ "ON (SA.SESSION_PRIMARY_ID = A.SESSION_PRIMARY_ID and SA.ATTRIBUTE_NAME = A.ATTRIBUTE_NAME) "
+ "WHEN MATCHED THEN "
+ " UPDATE SET ATTRIBUTE_BYTES = A.ATTRIBUTE_BYTES "
+ "WHEN NOT MATCHED THEN "
+ " INSERT (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
+ " VALUES (A.SESSION_PRIMARY_ID, A.ATTRIBUTE_NAME, A.ATTRIBUTE_BYTES)";
// @formatter:on
@Override
public void customize(JdbcIndexedSessionRepository sessionRepository) {
sessionRepository.setCreateSessionAttributeQuery(CREATE_SESSION_ATTRIBUTE_QUERY);
}
}

View File

@@ -1,44 +0,0 @@
/*
* Copyright 2014-2020 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
*
* https://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.jdbc;
import org.springframework.session.config.SessionRepositoryCustomizer;
/**
* A {@link SessionRepositoryCustomizer} implementation that applies PostgreSQL specific
* optimized SQL statements to {@link JdbcIndexedSessionRepository}.
*
* @author Vedran Pavic
* @since 2.5.0
*/
public class PostgreSqlJdbcIndexedSessionRepositoryCustomizer
implements SessionRepositoryCustomizer<JdbcIndexedSessionRepository> {
// @formatter:off
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = ""
+ "INSERT INTO %TABLE_NAME%_ATTRIBUTES (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
+ "VALUES (?, ?, ?) "
+ "ON CONFLICT (SESSION_PRIMARY_ID, ATTRIBUTE_NAME) "
+ "DO UPDATE SET ATTRIBUTE_BYTES = EXCLUDED.ATTRIBUTE_BYTES";
// @formatter:on
@Override
public void customize(JdbcIndexedSessionRepository sessionRepository) {
sessionRepository.setCreateSessionAttributeQuery(CREATE_SESSION_ATTRIBUTE_QUERY);
}
}

View File

@@ -1,50 +0,0 @@
/*
* Copyright 2014-2020 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
*
* https://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.jdbc;
import org.springframework.session.config.SessionRepositoryCustomizer;
/**
* A {@link SessionRepositoryCustomizer} implementation that applies SQL Server specific
* optimized SQL statements to {@link JdbcIndexedSessionRepository}.
*
* @author Vedran Pavic
* @since 2.5.0
*/
public class SqlServerJdbcIndexedSessionRepositoryCustomizer
implements SessionRepositoryCustomizer<JdbcIndexedSessionRepository> {
// @formatter:off
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = ""
+ "MERGE INTO %TABLE_NAME%_ATTRIBUTES SA "
+ "USING ( "
+ " VALUES (?, ?, ?) "
+ ") A (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
+ "ON (SA.SESSION_PRIMARY_ID = A.SESSION_PRIMARY_ID and SA.ATTRIBUTE_NAME = A.ATTRIBUTE_NAME) "
+ "WHEN MATCHED THEN "
+ " UPDATE SET ATTRIBUTE_BYTES = A.ATTRIBUTE_BYTES "
+ "WHEN NOT MATCHED THEN "
+ " INSERT (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
+ " VALUES (A.SESSION_PRIMARY_ID, A.ATTRIBUTE_NAME, A.ATTRIBUTE_BYTES);";
// @formatter:on
@Override
public void customize(JdbcIndexedSessionRepository sessionRepository) {
sessionRepository.setCreateSessionAttributeQuery(CREATE_SESSION_ATTRIBUTE_QUERY);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2019 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.
@@ -290,9 +290,9 @@ class JdbcIndexedSessionRepositoryTests {
this.repository.save(session);
assertThat(session.isNew()).isFalse();
verify(this.jdbcOperations, times(1)).update(startsWith("INSERT INTO SPRING_SESSION ("),
verify(this.jdbcOperations, times(1)).update(startsWith("INSERT INTO SPRING_SESSION("),
isA(PreparedStatementSetter.class));
verify(this.jdbcOperations, times(1)).update(startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES ("),
verify(this.jdbcOperations, times(1)).update(startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES("),
isA(PreparedStatementSetter.class));
verifyNoMoreInteractions(this.jdbcOperations);
}
@@ -306,9 +306,9 @@ class JdbcIndexedSessionRepositoryTests {
this.repository.save(session);
assertThat(session.isNew()).isFalse();
verify(this.jdbcOperations, times(1)).update(startsWith("INSERT INTO SPRING_SESSION ("),
verify(this.jdbcOperations, times(1)).update(startsWith("INSERT INTO SPRING_SESSION("),
isA(PreparedStatementSetter.class));
verify(this.jdbcOperations, times(1)).batchUpdate(startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES ("),
verify(this.jdbcOperations, times(1)).batchUpdate(startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES("),
isA(BatchPreparedStatementSetter.class));
verifyNoMoreInteractions(this.jdbcOperations);
}
@@ -321,7 +321,7 @@ class JdbcIndexedSessionRepositoryTests {
this.repository.save(session);
assertThat(session.isNew()).isFalse();
verify(this.jdbcOperations, times(1)).update(startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES ("),
verify(this.jdbcOperations, times(1)).update(startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES("),
isA(PreparedStatementSetter.class));
verifyNoMoreInteractions(this.jdbcOperations);
}
@@ -335,7 +335,7 @@ class JdbcIndexedSessionRepositoryTests {
this.repository.save(session);
assertThat(session.isNew()).isFalse();
verify(this.jdbcOperations, times(1)).batchUpdate(startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES ("),
verify(this.jdbcOperations, times(1)).batchUpdate(startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES("),
isA(BatchPreparedStatementSetter.class));
verifyNoMoreInteractions(this.jdbcOperations);
}
@@ -424,7 +424,7 @@ class JdbcIndexedSessionRepositoryTests {
this.repository.save(session);
assertThat(session.isNew()).isFalse();
verify(this.jdbcOperations).update(startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES ("),
verify(this.jdbcOperations).update(startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES("),
isA(PreparedStatementSetter.class));
verifyNoMoreInteractions(this.jdbcOperations);
}
@@ -679,7 +679,7 @@ class JdbcIndexedSessionRepositoryTests {
JdbcSession session = this.repository.new JdbcSession(new MapSession(), "primaryKey", false);
String attrName = "someAttribute";
session.setAttribute(attrName, "someValue");
verify(this.jdbcOperations).update(startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES ("),
verify(this.jdbcOperations).update(startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES("),
isA(PreparedStatementSetter.class));
verifyNoMoreInteractions(this.jdbcOperations);
}

View File

@@ -1,6 +1,6 @@
dependencyManagement {
imports {
mavenBom 'com.fasterxml.jackson:jackson-bom:2.12.4'
mavenBom 'com.fasterxml.jackson:jackson-bom:2.11.4'
}
dependencies {
@@ -9,14 +9,14 @@ dependencyManagement {
dependency 'javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.2'
dependency 'javax.servlet.jsp:javax.servlet.jsp-api:2.3.3'
dependency 'org.apache.taglibs:taglibs-standard-jstlel:1.2.5'
dependency 'org.seleniumhq.selenium:htmlunit-driver:2.49.1'
dependency 'org.slf4j:jcl-over-slf4j:1.7.32'
dependency 'org.slf4j:log4j-over-slf4j:1.7.32'
dependency 'org.seleniumhq.selenium:htmlunit-driver:2.44.0'
dependency 'org.slf4j:jcl-over-slf4j:1.7.31'
dependency 'org.slf4j:log4j-over-slf4j:1.7.31'
dependency 'org.webjars:bootstrap:2.3.2'
dependency 'org.webjars:html5shiv:3.7.3-1'
dependency 'org.webjars:jquery:3.6.0'
dependency 'org.webjars:knockout:3.5.1'
dependency 'org.webjars:sockjs-client:1.5.1'
dependency 'org.webjars:html5shiv:3.7.3'
dependency 'org.webjars:jquery:1.12.4'
dependency 'org.webjars:knockout:2.3.0'
dependency 'org.webjars:sockjs-client:0.3.4'
dependency 'org.webjars:stomp-websocket:2.3.4'
dependency 'org.webjars:webjars-taglib:0.3'
}

View File

@@ -115,7 +115,7 @@
<div id="footer">
<div class="container">
<p class="muted credit">Visit the <a href="https://projects.spring.io/spring-session/">Spring Session</a> site for more <a href="https://github.com/spring-projects/spring-session/tree/main/spring-session-samples">samples</a>.</p>
<p class="muted credit">Visit the <a href="https://projects.spring.io/spring-session/">Spring Session</a> site for more <a href="https://github.com/spring-projects/spring-session/tree/master/spring-session-samples">samples</a>.</p>
</div>
</div>
</body>

View File

@@ -6,7 +6,7 @@ dependencies {
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework.boot:spring-boot-starter-thymeleaf"
compile "org.springframework.boot:spring-boot-starter-security"
compile "com.hazelcast:hazelcast:4.2.2"
compile "com.hazelcast:hazelcast:4.0.3"
compile "nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect"
compile "org.webjars:bootstrap"
compile "org.webjars:html5shiv"

View File

@@ -115,7 +115,7 @@
<div id="footer">
<div class="container">
<p class="muted credit">Visit the <a href="https://projects.spring.io/spring-session/">Spring Session</a> site for more <a href="https://github.com/spring-projects/spring-session/tree/main/spring-session-samples">samples</a>.</p>
<p class="muted credit">Visit the <a href="https://projects.spring.io/spring-session/">Spring Session</a> site for more <a href="https://github.com/spring-projects/spring-session/tree/master/spring-session-samples">samples</a>.</p>
</div>
</div>
</body>

View File

@@ -115,7 +115,7 @@
<div id="footer">
<div class="container">
<p class="muted credit">Visit the <a href="https://projects.spring.io/spring-session/">Spring Session</a> site for more <a href="https://github.com/spring-projects/spring-session/tree/main/spring-session-samples">samples</a>.</p>
<p class="muted credit">Visit the <a href="https://projects.spring.io/spring-session/">Spring Session</a> site for more <a href="https://github.com/spring-projects/spring-session/tree/master/spring-session-samples">samples</a>.</p>
</div>
</div>
</body>

View File

@@ -121,7 +121,7 @@
<div id="footer">
<div class="container">
<p class="muted credit">Visit the <a href="https://projects.spring.io/spring-session/">Spring Session</a> site
for more <a href="https://github.com/spring-projects/spring-session/tree/main/spring-session-samples">samples</a>.</p>
for more <a href="https://github.com/spring-projects/spring-session/tree/master/spring-session-samples">samples</a>.</p>
</div>
</div>
</body>

View File

@@ -115,7 +115,7 @@
<div id="footer">
<div class="container">
<p class="muted credit">Visit the <a href="https://projects.spring.io/spring-session/">Spring Session</a> site for more <a href="https://github.com/spring-projects/spring-session/tree/main/spring-session-samples">samples</a>.</p>
<p class="muted credit">Visit the <a href="https://projects.spring.io/spring-session/">Spring Session</a> site for more <a href="https://github.com/spring-projects/spring-session/tree/master/spring-session-samples">samples</a>.</p>
</div>
</div>
</body>

View File

@@ -1,5 +1,7 @@
apply plugin: 'io.spring.convention.spring-sample-boot'
ext['spring-data-bom.version'] = '2020.0.0'
dependencies {
compile project(':spring-session-data-redis')
compile "org.springframework.boot:spring-boot-starter-webflux"

View File

@@ -117,7 +117,7 @@
<div id="footer">
<div class="container">
<p class="muted credit">Visit the <a href="https://projects.spring.io/spring-session/">Spring Session</a> site for more <a href="https://github.com/spring-projects/spring-session/tree/main/spring-session-samples">samples</a>.</p>
<p class="muted credit">Visit the <a href="https://projects.spring.io/spring-session/">Spring Session</a> site for more <a href="https://github.com/spring-projects/spring-session/tree/master/spring-session-samples">samples</a>.</p>
</div>
</div>
</body>