Compare commits
77 Commits
2.1.6.RELE
...
2.1.x
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d521aa9bc | ||
|
|
e14c840354 | ||
|
|
f36713d0ee | ||
|
|
12721d83ad | ||
|
|
92c7302103 | ||
|
|
1adb9bb481 | ||
|
|
8faef3613b | ||
|
|
65702d159e | ||
|
|
48f061450c | ||
|
|
a77196a851 | ||
|
|
4d18ed1826 | ||
|
|
b20dd33af7 | ||
|
|
ad51021e22 | ||
|
|
41a84efd21 | ||
|
|
6cb1764066 | ||
|
|
07f16ffc6a | ||
|
|
54b428dbeb | ||
|
|
e789fcc628 | ||
|
|
15d22a9dd4 | ||
|
|
40cb8de232 | ||
|
|
b394f56731 | ||
|
|
e7fd59ccf9 | ||
|
|
6e5352d48f | ||
|
|
2507c86cba | ||
|
|
01f7ff9a51 | ||
|
|
1ce95f8591 | ||
|
|
a9d003af4d | ||
|
|
797b0a62a8 | ||
|
|
943abb8eca | ||
|
|
9f78688ffa | ||
|
|
c391adfea1 | ||
|
|
9befe44769 | ||
|
|
6aa85236e0 | ||
|
|
5ebe699d7c | ||
|
|
f6a670d78e | ||
|
|
c63761317d | ||
|
|
f0aed6b8b8 | ||
|
|
4a3f0d5f34 | ||
|
|
5d88b6bf28 | ||
|
|
b7857db5bb | ||
|
|
8e97ac9acd | ||
|
|
ca943b6717 | ||
|
|
08c3056fb5 | ||
|
|
ca41542113 | ||
|
|
2e4f12e1a7 | ||
|
|
d582343a7e | ||
|
|
2505270f5f | ||
|
|
02e182ab4a | ||
|
|
8f13a7b356 | ||
|
|
51252a55e6 | ||
|
|
4487b07bb1 | ||
|
|
84479a0ba0 | ||
|
|
643f9cfd1a | ||
|
|
95e6d710ba | ||
|
|
0cf723c6aa | ||
|
|
66cc442b5f | ||
|
|
23d8c18b22 | ||
|
|
28d1d4fd00 | ||
|
|
e82a856d00 | ||
|
|
e40e55d1e9 | ||
|
|
a289938c7c | ||
|
|
63927aa4da | ||
|
|
88071796a2 | ||
|
|
76bc9563bb | ||
|
|
819b341a9f | ||
|
|
3b0be07c8e | ||
|
|
6761f2cc68 | ||
|
|
c8f266cea2 | ||
|
|
7d71aa5d00 | ||
|
|
bee9c7c2e2 | ||
|
|
8788165966 | ||
|
|
aadc806447 | ||
|
|
0fb942f795 | ||
|
|
49ebaa5cb7 | ||
|
|
a48edd5e71 | ||
|
|
17ddfc0fa8 | ||
|
|
f2f9562a01 |
18
.travis.yml
18
.travis.yml
@@ -1,20 +1,16 @@
|
||||
language: java
|
||||
|
||||
sudo: required
|
||||
|
||||
services: docker
|
||||
|
||||
jdk: oraclejdk8
|
||||
|
||||
language: java
|
||||
jdk:
|
||||
- openjdk8
|
||||
- openjdk11
|
||||
services:
|
||||
- docker
|
||||
before_cache:
|
||||
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.gradle/caches/
|
||||
- $HOME/.gradle/wrapper/
|
||||
|
||||
install: true
|
||||
|
||||
script: ./gradlew clean build --refresh-dependencies --no-daemon
|
||||
script: ./gradlew clean check --no-daemon --refresh-dependencies --stacktrace
|
||||
|
||||
149
Jenkinsfile
vendored
149
Jenkinsfile
vendored
@@ -1,149 +0,0 @@
|
||||
properties([
|
||||
buildDiscarder(logRotator(numToKeepStr: '10')),
|
||||
pipelineTriggers([
|
||||
cron('@daily')
|
||||
]),
|
||||
])
|
||||
|
||||
def SUCCESS = hudson.model.Result.SUCCESS.toString()
|
||||
currentBuild.result = SUCCESS
|
||||
|
||||
try {
|
||||
parallel check: {
|
||||
stage('Check') {
|
||||
timeout(time: 45, unit: 'MINUTES') {
|
||||
node('ubuntu1804') {
|
||||
checkout scm
|
||||
try {
|
||||
sh './gradlew clean check --no-daemon --refresh-dependencies'
|
||||
}
|
||||
catch (e) {
|
||||
currentBuild.result = 'FAILED: check'
|
||||
throw e
|
||||
}
|
||||
finally {
|
||||
junit '**/build/test-results/*/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
jdk9: {
|
||||
stage('JDK 9') {
|
||||
timeout(time: 45, unit: 'MINUTES') {
|
||||
node {
|
||||
checkout scm
|
||||
try {
|
||||
withEnv(["JAVA_HOME=${tool 'jdk9'}"]) {
|
||||
sh './gradlew clean test --no-daemon --refresh-dependencies'
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
currentBuild.result = 'FAILED: jdk9'
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
jdk10: {
|
||||
stage('JDK 10') {
|
||||
timeout(time: 45, unit: 'MINUTES') {
|
||||
node {
|
||||
checkout scm
|
||||
try {
|
||||
withEnv(["JAVA_HOME=${tool 'jdk10'}"]) {
|
||||
sh './gradlew clean test --no-daemon --refresh-dependencies'
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
currentBuild.result = 'FAILED: jdk10'
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
jdk11: {
|
||||
stage('JDK 11') {
|
||||
timeout(time: 45, unit: 'MINUTES') {
|
||||
node('ubuntu1804') {
|
||||
checkout scm
|
||||
try {
|
||||
withEnv(["JAVA_HOME=${tool 'jdk11'}"]) {
|
||||
sh './gradlew clean test integrationTest --no-daemon --refresh-dependencies'
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
currentBuild.result = 'FAILED: jdk11'
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentBuild.result == 'SUCCESS') {
|
||||
parallel artifacts: {
|
||||
stage('Deploy Artifacts') {
|
||||
node {
|
||||
checkout scm
|
||||
try {
|
||||
withCredentials([file(credentialsId: 'spring-signing-secring.gpg', variable: 'SIGNING_KEYRING_FILE')]) {
|
||||
withCredentials([string(credentialsId: 'spring-gpg-passphrase', variable: 'SIGNING_PASSWORD')]) {
|
||||
withCredentials([usernamePassword(credentialsId: 'oss-token', passwordVariable: 'OSSRH_PASSWORD', usernameVariable: 'OSSRH_USERNAME')]) {
|
||||
withCredentials([usernamePassword(credentialsId: '02bd1690-b54f-4c9f-819d-a77cb7a9822c', usernameVariable: 'ARTIFACTORY_USERNAME', passwordVariable: 'ARTIFACTORY_PASSWORD')]) {
|
||||
sh './gradlew deployArtifacts finalizeDeployArtifacts --stacktrace --no-daemon --refresh-dependencies -Psigning.secretKeyRingFile=$SIGNING_KEYRING_FILE -Psigning.keyId=$SPRING_SIGNING_KEYID -Psigning.password=$SIGNING_PASSWORD -PossrhUsername=$OSSRH_USERNAME -PossrhPassword=$OSSRH_PASSWORD -PartifactoryUsername=$ARTIFACTORY_USERNAME -PartifactoryPassword=$ARTIFACTORY_PASSWORD'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
currentBuild.result = 'FAILED: artifacts'
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
docs: {
|
||||
stage('Deploy Docs') {
|
||||
node {
|
||||
checkout scm
|
||||
try {
|
||||
withCredentials([file(credentialsId: 'docs.spring.io-jenkins_private_ssh_key', variable: 'DEPLOY_SSH_KEY')]) {
|
||||
sh './gradlew deployDocs --stacktrace --no-daemon --refresh-dependencies -PdeployDocsSshKeyPath=$DEPLOY_SSH_KEY -PdeployDocsSshUsername=$SPRING_DOCS_USERNAME'
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
currentBuild.result = 'FAILED: docs'
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
def buildStatus = currentBuild.result
|
||||
def buildNotSuccess = !SUCCESS.equals(buildStatus)
|
||||
def lastBuildNotSuccess = !SUCCESS.equals(currentBuild.previousBuild?.result)
|
||||
|
||||
if (buildNotSuccess || lastBuildNotSuccess) {
|
||||
stage('Notify') {
|
||||
node {
|
||||
final def RECIPIENTS = [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']]
|
||||
|
||||
def subject = "${buildStatus}: Build ${env.JOB_NAME} ${env.BUILD_NUMBER} status is now ${buildStatus}"
|
||||
def details = "The build status changed to ${buildStatus}. For details see ${env.BUILD_URL}"
|
||||
|
||||
emailext(
|
||||
subject: subject,
|
||||
body: details,
|
||||
recipientProviders: RECIPIENTS,
|
||||
to: "$SPRING_SESSION_TEAM_EMAILS"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,9 @@
|
||||
[NOTE]
|
||||
======
|
||||
This branch of Spring Session has reached its https://github.com/spring-projects/spring-boot/wiki/Supported-Versions[End of Life], meaning that there are no further maintenance releases or security patches planned.
|
||||
Please migrate to a supported branch as soon as possible.
|
||||
======
|
||||
|
||||
= Spring Session
|
||||
|
||||
image:https://travis-ci.org/spring-projects/spring-session.svg?branch=master["Build Status", link="https://travis-ci.org/spring-projects/spring-session"] 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"]
|
||||
|
||||
16
build.gradle
16
build.gradle
@@ -4,7 +4,7 @@ buildscript {
|
||||
snapshotBuild = version.endsWith('SNAPSHOT')
|
||||
milestoneBuild = !(releaseBuild || snapshotBuild)
|
||||
|
||||
springBootVersion = '2.1.4.RELEASE'
|
||||
springBootVersion = '2.1.16.RELEASE'
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -23,16 +23,8 @@ apply plugin: 'io.spring.convention.root'
|
||||
group = 'org.springframework.session'
|
||||
description = 'Spring Session'
|
||||
|
||||
gradle.taskGraph.whenReady { graph ->
|
||||
def jacocoEnabled = graph.allTasks.any { it instanceof JacocoReport }
|
||||
subprojects {
|
||||
plugins.withType(JavaPlugin) {
|
||||
sourceCompatibility = 1.8
|
||||
}
|
||||
plugins.withType(JacocoPlugin) {
|
||||
tasks.withType(Test) {
|
||||
jacoco.enabled = jacocoEnabled
|
||||
}
|
||||
}
|
||||
subprojects {
|
||||
plugins.withType(JavaPlugin) {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
version=2.1.6.RELEASE
|
||||
version=2.1.14.BUILD-SNAPSHOT
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom 'com.fasterxml.jackson:jackson-bom:2.9.6'
|
||||
mavenBom 'io.projectreactor:reactor-bom:Californium-SR8'
|
||||
mavenBom 'org.springframework:spring-framework-bom:5.1.7.RELEASE'
|
||||
mavenBom 'org.springframework.data:spring-data-releasetrain:Lovelace-SR8'
|
||||
mavenBom 'org.springframework.security:spring-security-bom:5.1.5.RELEASE'
|
||||
mavenBom 'org.testcontainers:testcontainers-bom:1.11.2'
|
||||
mavenBom 'io.projectreactor:reactor-bom:Californium-SR21'
|
||||
mavenBom 'org.springframework:spring-framework-bom:5.1.18.RELEASE'
|
||||
mavenBom 'org.springframework.data:spring-data-releasetrain:Lovelace-SR20'
|
||||
mavenBom 'org.springframework.security:spring-security-bom:5.1.12.RELEASE'
|
||||
mavenBom 'org.testcontainers:testcontainers-bom:1.12.5'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -14,20 +13,20 @@ dependencyManagement {
|
||||
entry 'hazelcast-client'
|
||||
}
|
||||
|
||||
dependency 'com.h2database:h2:1.4.199'
|
||||
dependency 'com.microsoft.sqlserver:mssql-jdbc:7.2.2.jre8'
|
||||
dependency 'com.zaxxer:HikariCP:3.3.1'
|
||||
dependency 'com.h2database:h2:1.4.200'
|
||||
dependency 'com.microsoft.sqlserver:mssql-jdbc:7.4.1.jre8'
|
||||
dependency 'com.zaxxer:HikariCP:3.4.5'
|
||||
dependency 'edu.umd.cs.mtc:multithreadedtc:1.01'
|
||||
dependency 'io.lettuce:lettuce-core:5.1.6.RELEASE'
|
||||
dependency 'io.lettuce:lettuce-core:5.2.0.RELEASE'
|
||||
dependency 'javax.annotation:javax.annotation-api:1.3.2'
|
||||
dependency 'javax.servlet:javax.servlet-api:4.0.1'
|
||||
dependency 'junit:junit:4.12'
|
||||
dependency 'mysql:mysql-connector-java:8.0.16'
|
||||
dependency 'mysql:mysql-connector-java:8.0.21'
|
||||
dependency 'org.apache.derby:derby:10.14.2.0'
|
||||
dependency 'org.assertj:assertj-core:3.12.2'
|
||||
dependency 'org.hsqldb:hsqldb:2.4.1'
|
||||
dependency 'org.mariadb.jdbc:mariadb-java-client:2.4.1'
|
||||
dependency 'org.mockito:mockito-core:2.27.0'
|
||||
dependency 'org.postgresql:postgresql:42.2.5'
|
||||
dependency 'org.assertj:assertj-core:3.13.2'
|
||||
dependency 'org.hsqldb:hsqldb:2.5.1'
|
||||
dependency 'org.mariadb.jdbc:mariadb-java-client:2.4.4'
|
||||
dependency 'org.mockito:mockito-core:3.0.0'
|
||||
dependency 'org.postgresql:postgresql:42.2.16'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDr
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
|
||||
public class FindByUsernameTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@@ -50,7 +50,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@AutoConfigureMockMvc
|
||||
public class HttpRedisJsonTest {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@@ -39,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@SpringBootTest
|
||||
public class RedisSerializerTest {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@SpringSessionRedisOperations
|
||||
private RedisTemplate<Object, Object> sessionRedisTemplate;
|
||||
|
||||
@@ -45,7 +45,7 @@ import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDr
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
|
||||
public class BootTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@@ -47,7 +47,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class AttributeTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
@@ -52,7 +52,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class ApplicationTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Value("${local.server.port}")
|
||||
private String port;
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom 'com.fasterxml.jackson:jackson-bom:2.10.5'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
dependency 'ch.qos.logback:logback-classic:1.2.3'
|
||||
dependency 'com.maxmind.geoip2:geoip2:2.3.1'
|
||||
dependency 'javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1'
|
||||
dependency 'javax.servlet.jsp:javax.servlet.jsp-api:2.3.2-b02'
|
||||
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.32.0'
|
||||
dependency 'org.slf4j:jcl-over-slf4j:1.7.25'
|
||||
dependency 'org.slf4j:log4j-over-slf4j:1.7.25'
|
||||
dependency 'org.seleniumhq.selenium:htmlunit-driver:2.33.0'
|
||||
dependency 'org.slf4j:jcl-over-slf4j:1.7.30'
|
||||
dependency 'org.slf4j:log4j-over-slf4j:1.7.30'
|
||||
dependency 'org.webjars:bootstrap:2.3.2'
|
||||
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.0'
|
||||
dependency 'org.webjars:stomp-websocket:2.3.3'
|
||||
dependency 'org.webjars:webjars-taglib:0.3'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
@Profile("embedded-redis")
|
||||
public class EmbeddedRedisConfig {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Description</h1>
|
||||
<p>This application demonstrates how to use a Redis instance to back your session. Notice that there is no JSESSIONID cookie. We are also able to customize the way of identifying what the requested session id is.</p>
|
||||
<p>This application demonstrates how to customize the session cookie. Notice that the name of the cookie is JSESSIONID.</p>
|
||||
|
||||
<h1>Try it</h1>
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
@Profile("embedded-redis")
|
||||
public class EmbeddedRedisConfig {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
|
||||
@@ -54,7 +54,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
@WebAppConfiguration
|
||||
public class RestMockMvcTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Autowired
|
||||
private SessionRepositoryFilter<? extends Session> sessionRepositoryFilter;
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
@Profile("embedded-redis")
|
||||
public class EmbeddedRedisConfig {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
@Profile("embedded-redis")
|
||||
public class EmbeddedRedisConfig {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
@Profile("embedded-redis")
|
||||
public class EmbeddedRedisConfig {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 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.
|
||||
@@ -16,9 +16,10 @@
|
||||
|
||||
package org.springframework.session.web.http;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
@@ -62,6 +63,8 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
domainValid.set('-');
|
||||
}
|
||||
|
||||
private Clock clock = Clock.systemUTC();
|
||||
|
||||
private String cookieName = "SESSION";
|
||||
|
||||
private Boolean useSecureCookie;
|
||||
@@ -135,9 +138,9 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
int maxAge = getMaxAge(cookieValue);
|
||||
if (maxAge > -1) {
|
||||
sb.append("; Max-Age=").append(cookieValue.getCookieMaxAge());
|
||||
OffsetDateTime expires = (maxAge != 0)
|
||||
? OffsetDateTime.now().plusSeconds(maxAge)
|
||||
: Instant.EPOCH.atOffset(ZoneOffset.UTC);
|
||||
ZonedDateTime expires = (maxAge != 0)
|
||||
? ZonedDateTime.now(this.clock).plusSeconds(maxAge)
|
||||
: Instant.EPOCH.atZone(ZoneOffset.UTC);
|
||||
sb.append("; Expires=")
|
||||
.append(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME));
|
||||
}
|
||||
@@ -267,6 +270,10 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
void setClock(Clock clock) {
|
||||
this.clock = clock.withZone(ZoneOffset.UTC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if a Cookie marked as secure should be used. The default is to use the value
|
||||
* of {@link HttpServletRequest#isSecure()}.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 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.
|
||||
@@ -68,6 +68,12 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
|
||||
super.addHeader(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentLengthLong(long len) {
|
||||
setContentLength(len);
|
||||
super.setContentLengthLong(len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentLength(int len) {
|
||||
setContentLength((long) len);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.session.web.http;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
@@ -66,27 +67,66 @@ abstract class OncePerRequestFilter implements Filter {
|
||||
}
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
String alreadyFilteredAttributeName = this.alreadyFilteredAttributeName;
|
||||
boolean hasAlreadyFilteredAttribute = request
|
||||
.getAttribute(this.alreadyFilteredAttributeName) != null;
|
||||
.getAttribute(alreadyFilteredAttributeName) != null;
|
||||
|
||||
if (hasAlreadyFilteredAttribute) {
|
||||
|
||||
if (DispatcherType.ERROR.equals(request.getDispatcherType())) {
|
||||
doFilterNestedErrorDispatch(httpRequest, httpResponse, filterChain);
|
||||
return;
|
||||
}
|
||||
// Proceed without invoking this filter...
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
else {
|
||||
// Do invoke this filter...
|
||||
request.setAttribute(this.alreadyFilteredAttributeName, Boolean.TRUE);
|
||||
request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
|
||||
try {
|
||||
doFilterInternal(httpRequest, httpResponse, filterChain);
|
||||
}
|
||||
finally {
|
||||
// Remove the "already filtered" request attribute for this request.
|
||||
request.removeAttribute(this.alreadyFilteredAttributeName);
|
||||
request.removeAttribute(alreadyFilteredAttributeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the request attribute that identifies that a request is already
|
||||
* filtered.
|
||||
* <p>
|
||||
* The default implementation takes the configured name of the concrete filter
|
||||
* instance and appends ".FILTERED". If the filter is not fully initialized, it falls
|
||||
* back to its class name.
|
||||
* @return the name of request attribute indicating already filtered request
|
||||
* @see #ALREADY_FILTERED_SUFFIX
|
||||
*/
|
||||
protected String getAlreadyFilteredAttributeName() {
|
||||
return this.alreadyFilteredAttributeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Typically an ERROR dispatch happens after the REQUEST dispatch completes, and the
|
||||
* filter chain starts anew. On some servers however the ERROR dispatch may be nested
|
||||
* within the REQUEST dispatch, e.g. as a result of calling {@code sendError} on the
|
||||
* response. In that case we are still in the filter chain, on the same thread, but
|
||||
* the request and response have been switched to the original, unwrapped ones.
|
||||
* <p>
|
||||
* Sub-classes may use this method to filter such nested ERROR dispatches and re-apply
|
||||
* wrapping on the request or response. {@code ThreadLocal} context, if any, should
|
||||
* still be active as we are still nested within the filter chain.
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @param filterChain the filter chain
|
||||
* @throws ServletException if request is not HTTP request
|
||||
* @throws IOException in case of I/O operation exception
|
||||
*/
|
||||
protected void doFilterNestedErrorDispatch(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
doFilter(request, response, filterChain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same contract as for {@code doFilter}, but guaranteed to be just invoked once per
|
||||
* request within a single request thread.
|
||||
|
||||
@@ -159,6 +159,12 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterNestedErrorDispatch(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
doFilterInternal(request, response, filterChain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows ensuring that the session is saved if the response is committed.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 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.
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.session.web.http;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
@@ -26,6 +29,7 @@ import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.mock.web.MockCookie;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
@@ -56,7 +60,7 @@ public class DefaultCookieSerializerTests {
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private MockHttpServletResponse response;
|
||||
private CookiePreservingMockHttpServletResponse response;
|
||||
|
||||
private DefaultCookieSerializer serializer;
|
||||
|
||||
@@ -70,7 +74,7 @@ public class DefaultCookieSerializerTests {
|
||||
public void setup() {
|
||||
this.cookieName = "SESSION";
|
||||
this.request = new MockHttpServletRequest();
|
||||
this.response = new MockHttpServletResponse();
|
||||
this.response = new CookiePreservingMockHttpServletResponse();
|
||||
this.sessionId = "sessionId";
|
||||
this.serializer = new DefaultCookieSerializer();
|
||||
this.serializer.setUseBase64Encoding(this.useBase64Encoding);
|
||||
@@ -232,7 +236,7 @@ public class DefaultCookieSerializerTests {
|
||||
this.serializer.writeCookieValue(cookieValue(this.sessionId));
|
||||
assertThat(getCookie().getDomain()).isEqualTo("example.com");
|
||||
|
||||
this.response = new MockHttpServletResponse();
|
||||
this.response = new CookiePreservingMockHttpServletResponse();
|
||||
}
|
||||
|
||||
String[] notMatchingDomains = { "example.com", "localhost", "127.0.0.1" };
|
||||
@@ -241,7 +245,7 @@ public class DefaultCookieSerializerTests {
|
||||
this.serializer.writeCookieValue(cookieValue(this.sessionId));
|
||||
assertThat(getCookie().getDomain()).isNull();
|
||||
|
||||
this.response = new MockHttpServletResponse();
|
||||
this.response = new CookiePreservingMockHttpServletResponse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,34 +330,41 @@ public class DefaultCookieSerializerTests {
|
||||
this.serializer.writeCookieValue(cookieValue(this.sessionId));
|
||||
|
||||
assertThat(getCookie().getMaxAge()).isEqualTo(-1);
|
||||
assertThat(this.response.rawCookie).doesNotContain("Expires");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void writeCookieCookieMaxAgeExplicit() {
|
||||
this.serializer.setClock(Clock.fixed(Instant.parse("2019-10-07T20:10:00Z"), ZoneOffset.UTC));
|
||||
this.serializer.setCookieMaxAge(100);
|
||||
|
||||
this.serializer.writeCookieValue(cookieValue(this.sessionId));
|
||||
|
||||
assertThat(getCookie().getMaxAge()).isEqualTo(100);
|
||||
assertThat(this.response.rawCookie).contains("Expires=Mon, 7 Oct 2019 20:11:40 GMT");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void writeCookieCookieMaxAgeExplicitEmptyCookie() {
|
||||
this.serializer.setClock(Clock.fixed(Instant.parse("2019-10-07T20:10:00Z"), ZoneOffset.UTC));
|
||||
this.serializer.setCookieMaxAge(100);
|
||||
|
||||
this.serializer.writeCookieValue(cookieValue(""));
|
||||
|
||||
assertThat(getCookie().getMaxAge()).isEqualTo(0);
|
||||
assertThat(this.response.rawCookie).contains("Expires=Thu, 1 Jan 1970 00:00:00 GMT");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void writeCookieCookieMaxAgeExplicitCookieValue() {
|
||||
this.serializer.setClock(Clock.fixed(Instant.parse("2019-10-07T20:10:00Z"), ZoneOffset.UTC));
|
||||
CookieValue cookieValue = cookieValue(this.sessionId);
|
||||
cookieValue.setCookieMaxAge(100);
|
||||
|
||||
this.serializer.writeCookieValue(cookieValue);
|
||||
|
||||
assertThat(getCookie().getMaxAge()).isEqualTo(100);
|
||||
assertThat(this.response.rawCookie).contains("Expires=Mon, 7 Oct 2019 20:11:40 GMT");
|
||||
}
|
||||
|
||||
// --- secure ---
|
||||
@@ -531,4 +542,18 @@ public class DefaultCookieSerializerTests {
|
||||
return new CookieValue(this.request, this.response, cookieValue);
|
||||
}
|
||||
|
||||
private static class CookiePreservingMockHttpServletResponse extends MockHttpServletResponse {
|
||||
|
||||
private String rawCookie;
|
||||
|
||||
@Override
|
||||
public void addHeader(String name, String value) {
|
||||
if (HttpHeaders.SET_COOKIE.equals(name)) {
|
||||
this.rawCookie = value;
|
||||
}
|
||||
super.addHeader(name, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -1102,6 +1102,17 @@ public class OnCommittedResponseWrapperTests {
|
||||
assertThat(this.committed).isTrue();
|
||||
}
|
||||
|
||||
// gh-7261
|
||||
@Test
|
||||
public void contentLengthLongOutputStreamWriteStringCommits() throws IOException {
|
||||
String body = "something";
|
||||
this.response.setContentLengthLong(body.length());
|
||||
|
||||
this.response.getOutputStream().print(body);
|
||||
|
||||
assertThat(this.committed).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bufferSizeCommitsOnce() throws Exception {
|
||||
String expected = "1234567890";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -20,6 +20,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
@@ -32,6 +33,7 @@ import org.junit.Test;
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -95,4 +97,36 @@ public class OncePerRequestFilterTests {
|
||||
|
||||
assertThat(this.invocations).containsOnly(this.filter, filter2);
|
||||
}
|
||||
|
||||
@Test // gh-1470
|
||||
public void filterNestedErrorDispatch() throws ServletException, IOException {
|
||||
TestOncePerRequestFilter filter = new TestOncePerRequestFilter();
|
||||
this.request.setAttribute(filter.getAlreadyFilteredAttributeName(), Boolean.TRUE);
|
||||
this.request.setDispatcherType(DispatcherType.ERROR);
|
||||
this.request.setAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE, "/error");
|
||||
filter.doFilter(this.request, new MockHttpServletResponse(), this.chain);
|
||||
assertThat(filter.didFilter).isFalse();
|
||||
assertThat(filter.didFilterNestedErrorDispatch).isTrue();
|
||||
}
|
||||
|
||||
private static class TestOncePerRequestFilter extends OncePerRequestFilter {
|
||||
|
||||
private boolean didFilter;
|
||||
|
||||
private boolean didFilterNestedErrorDispatch;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) {
|
||||
this.didFilter = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterNestedErrorDispatch(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) {
|
||||
this.didFilterNestedErrorDispatch = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
*/
|
||||
public abstract class AbstractRedisITests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.4";
|
||||
private static final String DOCKER_IMAGE = "redis:5.0.6";
|
||||
|
||||
protected static class BaseConfig {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 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.
|
||||
@@ -20,6 +20,7 @@ import java.time.Instant;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -68,6 +69,17 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
|
||||
assertThat(this.repository.findById(toSave.getId()).block()).isNull();
|
||||
}
|
||||
|
||||
@Test // gh-1399
|
||||
public void saveMultipleTimes() {
|
||||
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository
|
||||
.createSession().block();
|
||||
session.setAttribute("attribute1", "value1");
|
||||
Mono<Void> save1 = this.repository.save(session);
|
||||
session.setAttribute("attribute2", "value2");
|
||||
Mono<Void> save2 = this.repository.save(session);
|
||||
Mono.zip(save1, save2).block();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putAllOnSingleAttrDoesNotRemoveOld() {
|
||||
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 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.
|
||||
@@ -143,23 +143,15 @@ public class ReactiveRedisOperationsSessionRepository implements
|
||||
|
||||
@Override
|
||||
public Mono<Void> save(RedisSession session) {
|
||||
Mono<Void> result = session.saveChangeSessionId().and(session.saveDelta())
|
||||
.and((s) -> {
|
||||
session.isNew = false;
|
||||
s.onComplete();
|
||||
});
|
||||
if (session.isNew) {
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
String sessionKey = getSessionKey(
|
||||
session.hasChangedSessionId() ? session.originalSessionId
|
||||
: session.getId());
|
||||
return this.sessionRedisOperations.hasKey(sessionKey)
|
||||
.flatMap((exists) -> exists ? result
|
||||
: Mono.error(new IllegalStateException(
|
||||
"Session was invalidated")));
|
||||
return session.save();
|
||||
}
|
||||
String sessionKey = getSessionKey(
|
||||
session.hasChangedSessionId() ? session.originalSessionId
|
||||
: session.getId());
|
||||
return this.sessionRedisOperations.hasKey(sessionKey).flatMap((exists) -> exists
|
||||
? session.save()
|
||||
: Mono.error(new IllegalStateException("Session was invalidated")));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -305,7 +297,7 @@ public class ReactiveRedisOperationsSessionRepository implements
|
||||
|
||||
private void flushImmediateIfNecessary() {
|
||||
if (ReactiveRedisOperationsSessionRepository.this.redisFlushMode == RedisFlushMode.IMMEDIATE) {
|
||||
saveDelta();
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,6 +306,11 @@ public class ReactiveRedisOperationsSessionRepository implements
|
||||
flushImmediateIfNecessary();
|
||||
}
|
||||
|
||||
private Mono<Void> save() {
|
||||
return Mono.defer(() -> saveChangeSessionId().then(saveDelta())
|
||||
.doOnSuccess((aVoid) -> this.isNew = false));
|
||||
}
|
||||
|
||||
private Mono<Void> saveDelta() {
|
||||
if (this.delta.isEmpty()) {
|
||||
return Mono.empty();
|
||||
@@ -321,7 +318,7 @@ public class ReactiveRedisOperationsSessionRepository implements
|
||||
|
||||
String sessionKey = getSessionKey(getId());
|
||||
Mono<Boolean> update = ReactiveRedisOperationsSessionRepository.this.sessionRedisOperations
|
||||
.opsForHash().putAll(sessionKey, this.delta);
|
||||
.opsForHash().putAll(sessionKey, new HashMap<>(this.delta));
|
||||
Mono<Boolean> setTtl = ReactiveRedisOperationsSessionRepository.this.sessionRedisOperations
|
||||
.expire(sessionKey, getMaxInactiveInterval());
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 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.
|
||||
@@ -132,9 +132,10 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
public void createSessionDefaultMaxInactiveInterval() {
|
||||
StepVerifier.create(this.repository.createSession()).consumeNextWith(
|
||||
(session) -> assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration
|
||||
.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS)))
|
||||
StepVerifier.create(this.repository.createSession())
|
||||
.consumeNextWith((session) -> assertThat(session.getMaxInactiveInterval())
|
||||
.isEqualTo(Duration.ofSeconds(
|
||||
MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS)))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@@ -155,30 +156,26 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
|
||||
given(this.redisOperations.expire(anyString(), any()))
|
||||
.willReturn(Mono.just(true));
|
||||
|
||||
StepVerifier
|
||||
.create(this.repository.createSession().doOnNext(this.repository::save))
|
||||
.consumeNextWith((session) -> {
|
||||
verify(this.redisOperations).opsForHash();
|
||||
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
|
||||
verify(this.redisOperations).expire(anyString(), any());
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.hashOperations);
|
||||
RedisSession newSession = this.repository.new RedisSession();
|
||||
StepVerifier.create(this.repository.save(newSession)).verifyComplete();
|
||||
|
||||
Map<String, Object> delta = this.delta.getAllValues().get(0);
|
||||
assertThat(delta.size()).isEqualTo(3);
|
||||
assertThat(delta.get(
|
||||
ReactiveRedisOperationsSessionRepository.CREATION_TIME_KEY))
|
||||
.isEqualTo(session.getCreationTime().toEpochMilli());
|
||||
assertThat(delta.get(
|
||||
ReactiveRedisOperationsSessionRepository.MAX_INACTIVE_INTERVAL_KEY))
|
||||
.isEqualTo((int) Duration.ofSeconds(
|
||||
MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS)
|
||||
.getSeconds());
|
||||
assertThat(delta.get(
|
||||
ReactiveRedisOperationsSessionRepository.LAST_ACCESSED_TIME_KEY))
|
||||
.isEqualTo(
|
||||
session.getLastAccessedTime().toEpochMilli());
|
||||
}).verifyComplete();
|
||||
verify(this.redisOperations).opsForHash();
|
||||
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
|
||||
verify(this.redisOperations).expire(anyString(), any());
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.hashOperations);
|
||||
|
||||
Map<String, Object> delta = this.delta.getAllValues().get(0);
|
||||
assertThat(delta.size()).isEqualTo(3);
|
||||
assertThat(delta.get(ReactiveRedisOperationsSessionRepository.CREATION_TIME_KEY))
|
||||
.isEqualTo(newSession.getCreationTime().toEpochMilli());
|
||||
assertThat(delta
|
||||
.get(ReactiveRedisOperationsSessionRepository.MAX_INACTIVE_INTERVAL_KEY))
|
||||
.isEqualTo(
|
||||
(int) newSession.getMaxInactiveInterval().getSeconds());
|
||||
assertThat(delta
|
||||
.get(ReactiveRedisOperationsSessionRepository.LAST_ACCESSED_TIME_KEY))
|
||||
.isEqualTo(newSession.getLastAccessedTime().toEpochMilli());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -207,7 +204,7 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
|
||||
|
||||
RedisSession session = this.repository.new RedisSession(this.cached);
|
||||
session.setLastAccessedTime(Instant.ofEpochMilli(12345678L));
|
||||
Mono.just(session).subscribe(this.repository::save);
|
||||
StepVerifier.create(this.repository.save(session)).verifyComplete();
|
||||
|
||||
verify(this.redisOperations).hasKey(anyString());
|
||||
verify(this.redisOperations).opsForHash();
|
||||
@@ -232,7 +229,7 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
|
||||
String attrName = "attrName";
|
||||
RedisSession session = this.repository.new RedisSession(this.cached);
|
||||
session.setAttribute(attrName, "attrValue");
|
||||
Mono.just(session).subscribe(this.repository::save);
|
||||
StepVerifier.create(this.repository.save(session)).verifyComplete();
|
||||
|
||||
verify(this.redisOperations).hasKey(anyString());
|
||||
verify(this.redisOperations).opsForHash();
|
||||
@@ -257,7 +254,7 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
|
||||
String attrName = "attrName";
|
||||
RedisSession session = this.repository.new RedisSession(new MapSession());
|
||||
session.removeAttribute(attrName);
|
||||
Mono.just(session).subscribe(this.repository::save);
|
||||
StepVerifier.create(this.repository.save(session)).verifyComplete();
|
||||
|
||||
verify(this.redisOperations).hasKey(anyString());
|
||||
verify(this.redisOperations).opsForHash();
|
||||
@@ -333,24 +330,25 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
|
||||
given(this.hashOperations.entries(anyString()))
|
||||
.willReturn(Flux.fromIterable(map.entrySet()));
|
||||
|
||||
StepVerifier.create(this.repository.findById("test")).consumeNextWith((session) -> {
|
||||
verify(this.redisOperations).opsForHash();
|
||||
verify(this.hashOperations).entries(anyString());
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.hashOperations);
|
||||
StepVerifier.create(this.repository.findById("test"))
|
||||
.consumeNextWith((session) -> {
|
||||
verify(this.redisOperations).opsForHash();
|
||||
verify(this.hashOperations).entries(anyString());
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.hashOperations);
|
||||
|
||||
assertThat(session.getId()).isEqualTo(expected.getId());
|
||||
assertThat(session.getAttributeNames())
|
||||
.isEqualTo(expected.getAttributeNames());
|
||||
assertThat(session.<String>getAttribute(attribute1))
|
||||
.isEqualTo(expected.getAttribute(attribute1));
|
||||
assertThat(session.<String>getAttribute(attribute2))
|
||||
.isEqualTo(expected.getAttribute(attribute2));
|
||||
assertThat(session.getId()).isEqualTo(expected.getId());
|
||||
assertThat(session.getAttributeNames())
|
||||
.isEqualTo(expected.getAttributeNames());
|
||||
assertThat(session.<String>getAttribute(attribute1))
|
||||
.isEqualTo(expected.getAttribute(attribute1));
|
||||
assertThat(session.<String>getAttribute(attribute2))
|
||||
.isEqualTo(expected.getAttribute(attribute2));
|
||||
assertThat(session.getCreationTime().truncatedTo(ChronoUnit.MILLIS))
|
||||
.isEqualTo(expected.getCreationTime()
|
||||
.truncatedTo(ChronoUnit.MILLIS));
|
||||
assertThat(session.getMaxInactiveInterval())
|
||||
.isEqualTo(expected.getMaxInactiveInterval());
|
||||
.isEqualTo(expected.getMaxInactiveInterval());
|
||||
assertThat(
|
||||
session.getLastAccessedTime().truncatedTo(ChronoUnit.MILLIS))
|
||||
.isEqualTo(expected.getLastAccessedTime()
|
||||
|
||||
@@ -22,8 +22,8 @@ import com.hazelcast.core.HazelcastInstance;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.testcontainers.containers.BindMode;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.utility.MountableFile;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -50,11 +50,9 @@ public class HazelcastClientRepositoryITests extends AbstractHazelcastRepository
|
||||
private static GenericContainer container = new GenericContainer<>(
|
||||
"hazelcast/hazelcast:3.11.4")
|
||||
.withExposedPorts(5701)
|
||||
.withEnv("JAVA_OPTS",
|
||||
"-Dhazelcast.config=/opt/hazelcast/config_ext/hazelcast.xml")
|
||||
.withClasspathResourceMapping("/hazelcast-server.xml",
|
||||
"/opt/hazelcast/config_ext/hazelcast.xml",
|
||||
BindMode.READ_ONLY);
|
||||
.withCopyFileToContainer(
|
||||
MountableFile.forClasspathResource("/hazelcast-server.xml"),
|
||||
"/opt/hazelcast/hazelcast.xml");
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
|
||||
@@ -88,7 +88,7 @@ final class DatabaseContainers {
|
||||
private static class MariaDb10Container extends MariaDBContainer<MariaDb10Container> {
|
||||
|
||||
MariaDb10Container() {
|
||||
super("mariadb:10.3.14");
|
||||
super("mariadb:10.4.8");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,7 +103,7 @@ final class DatabaseContainers {
|
||||
private static class MySql5Container extends MySQLContainer<MySql5Container> {
|
||||
|
||||
MySql5Container() {
|
||||
super("mysql:5.7.26");
|
||||
super("mysql:5.7.27");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -123,7 +123,7 @@ final class DatabaseContainers {
|
||||
private static class MySql8Container extends MySQLContainer<MySql8Container> {
|
||||
|
||||
MySql8Container() {
|
||||
super("mysql:8.0.16");
|
||||
super("mysql:8.0.17");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -143,7 +143,7 @@ final class DatabaseContainers {
|
||||
extends PostgreSQLContainer<PostgreSql9Container> {
|
||||
|
||||
PostgreSql9Container() {
|
||||
super("postgres:9.6.13");
|
||||
super("postgres:9.6.15");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -152,7 +152,7 @@ final class DatabaseContainers {
|
||||
extends PostgreSQLContainer<PostgreSql10Container> {
|
||||
|
||||
PostgreSql10Container() {
|
||||
super("postgres:10.8");
|
||||
super("postgres:10.10");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -161,7 +161,7 @@ final class DatabaseContainers {
|
||||
extends PostgreSQLContainer<PostgreSql11Container> {
|
||||
|
||||
PostgreSql11Container() {
|
||||
super("postgres:11.3");
|
||||
super("postgres:11.5");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -170,7 +170,7 @@ final class DatabaseContainers {
|
||||
extends MSSQLServerContainer<SqlServer2017Container> {
|
||||
|
||||
SqlServer2017Container() {
|
||||
super("mcr.microsoft.com/mssql/server:2017-CU14");
|
||||
super("mcr.microsoft.com/mssql/server:2017-CU16");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
mcr.microsoft.com/mssql/server:2017-CU14
|
||||
mcr.microsoft.com/mssql/server:2017-CU16
|
||||
|
||||
Reference in New Issue
Block a user