Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
029e7c8158 | ||
|
|
d489709886 | ||
|
|
e31280846f | ||
|
|
6cec3098ef | ||
|
|
8084e0bab9 | ||
|
|
b3b5dd4533 | ||
|
|
aca350a86e | ||
|
|
d8af71927f | ||
|
|
d0429dc1e9 | ||
|
|
4e884cdaf2 | ||
|
|
f0450fa2aa | ||
|
|
a6cb9340a1 | ||
|
|
cde82afa9e | ||
|
|
d42caa2dbb | ||
|
|
a9e9f8c46d | ||
|
|
30e9dc0a17 | ||
|
|
c92808fa32 | ||
|
|
bdc3a51409 | ||
|
|
e80021f334 | ||
|
|
a739b0794c | ||
|
|
384633f8b4 | ||
|
|
30f17f96f5 | ||
|
|
ac9077b9d6 | ||
|
|
c4c7d8e233 | ||
|
|
1ce7640fc5 | ||
|
|
a50a2fe3c9 | ||
|
|
74a21dd876 | ||
|
|
c800c7af40 | ||
|
|
0033adf74e | ||
|
|
0f63b0c4c8 | ||
|
|
b1d68c0731 | ||
|
|
7ec5add1bd | ||
|
|
05e103d9c5 | ||
|
|
8190072d3f | ||
|
|
ce16374c15 | ||
|
|
e41ebd8a77 | ||
|
|
8550aeca5c | ||
|
|
5cb8a6b79a | ||
|
|
5b48e7e8e7 | ||
|
|
9e2b729d62 | ||
|
|
524ee0d9bc | ||
|
|
26be3218fb | ||
|
|
8d4fd80add | ||
|
|
6969ea0049 | ||
|
|
ce938fd2fe | ||
|
|
98d7448b40 | ||
|
|
4bb2bd6fda | ||
|
|
0e5dd1863f | ||
|
|
548b58ee55 |
@@ -1,9 +1,9 @@
|
||||
name: CI
|
||||
name: 2.5.x CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- 2.5.x
|
||||
schedule:
|
||||
- cron: '0 10 * * *' # Once per day at 10am UTC
|
||||
workflow_dispatch: # Manual trigger
|
||||
@@ -29,13 +29,16 @@ jobs:
|
||||
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"
|
||||
@@ -51,18 +54,22 @@ jobs:
|
||||
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"
|
||||
export GRADLE_ENTERPRISE_CACHE_PASSWORD="$GRADLE_ENTERPRISE_CACHE_PASSWORD"
|
||||
export GRADLE_ENTERPRISE_ACCESS_KEY="$GRADLE_ENTERPRISE_SECRET_ACCESS_KEY"
|
||||
export VERSION_HEADER=$'Version: GnuPG v2\n\n'
|
||||
export ORG_GRADLE_PROJECT_signingKey=${GPG_PRIVATE_KEY_NO_HEADER#"$VERSION_HEADER"}
|
||||
export ORG_GRADLE_PROJECT_signingKey=${GPG_PRIVATE_KEY#"$VERSION_HEADER"}
|
||||
export ORG_GRADLE_PROJECT_signingPassword="$GPG_PASSPHRASE"
|
||||
./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 }}
|
||||
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY_NO_HEADER }}
|
||||
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||
OSSRH_TOKEN_USERNAME: ${{ secrets.OSSRH_TOKEN_USERNAME }}
|
||||
OSSRH_TOKEN_PASSWORD: ${{ secrets.OSSRH_TOKEN_PASSWORD }}
|
||||
@@ -78,6 +85,10 @@ jobs:
|
||||
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"
|
||||
|
||||
7
.github/workflows/pr-build-workflow.yml
vendored
7
.github/workflows/pr-build-workflow.yml
vendored
@@ -1,6 +1,9 @@
|
||||
name: PR Build
|
||||
name: 2.5.x PR Build
|
||||
|
||||
on: pull_request
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- 2.5.x
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -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/master/CODE_OF_CONDUCT.md[code of conduct].
|
||||
Please see our https://github.com/spring-projects/.github/blob/main/CODE_OF_CONDUCT.md[code of conduct].
|
||||
|
||||
|
||||
== Reporting Security Vulnerabilities
|
||||
|
||||
@@ -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=master["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=main["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:
|
||||
@@ -29,12 +29,12 @@ We recommend you visit the https://docs.spring.io/spring-session/docs/current/re
|
||||
|
||||
== Samples
|
||||
|
||||
Spring Session samples are available in the https://github.com/spring-projects/spring-session/tree/master/spring-session-samples[spring-session-samples] directory.
|
||||
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/master/CONTRIBUTING.adoc[Contributing guidelines]
|
||||
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
|
||||
@@ -67,7 +67,7 @@ For more in depth information, visit the https://docs.spring.io/spring-session/d
|
||||
|
||||
== Code of Conduct
|
||||
|
||||
Please see our https://github.com/spring-projects/.github/blob/master/CODE_OF_CONDUCT.md[code of conduct].
|
||||
Please see our https://github.com/spring-projects/.github/blob/main/CODE_OF_CONDUCT.md[code of conduct].
|
||||
|
||||
== License
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ buildscript {
|
||||
snapshotBuild = version.endsWith('SNAPSHOT')
|
||||
milestoneBuild = !(releaseBuild || snapshotBuild)
|
||||
|
||||
springBootVersion = '2.4.4'
|
||||
springBootVersion = '2.4.7'
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
org.gradle.parallel=true
|
||||
version=2.5.0-RC1
|
||||
version=2.5.3
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom 'io.projectreactor:reactor-bom:2020.0.6'
|
||||
mavenBom 'org.junit:junit-bom:5.7.1'
|
||||
mavenBom 'org.springframework:spring-framework-bom:5.3.5'
|
||||
mavenBom 'org.springframework.data:spring-data-bom:2021.0.0-RC1'
|
||||
mavenBom 'org.springframework.security:spring-security-bom:5.5.0-RC1'
|
||||
mavenBom 'org.testcontainers:testcontainers-bom:1.15.2'
|
||||
mavenBom 'io.projectreactor:reactor-bom:2020.0.12'
|
||||
mavenBom 'org.junit:junit-bom:5.7.2'
|
||||
mavenBom 'org.springframework:spring-framework-bom:5.3.11'
|
||||
mavenBom 'org.springframework.data:spring-data-bom:2021.0.6'
|
||||
mavenBom 'org.springframework.security:spring-security-bom:5.5.3'
|
||||
mavenBom 'org.testcontainers:testcontainers-bom:1.15.3'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -14,23 +14,23 @@ dependencyManagement {
|
||||
entry 'hazelcast-client'
|
||||
}
|
||||
|
||||
dependency 'org.aspectj:aspectjweaver:1.9.6'
|
||||
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.microsoft.sqlserver:mssql-jdbc:7.4.1.jre8'
|
||||
dependency 'com.oracle.database.jdbc:ojdbc8:19.10.0.0'
|
||||
dependency 'com.zaxxer:HikariCP:3.4.5'
|
||||
dependency 'edu.umd.cs.mtc:multithreadedtc:1.01'
|
||||
dependency 'io.lettuce:lettuce-core:6.1.0.RELEASE'
|
||||
dependency 'io.lettuce:lettuce-core:6.1.5.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.23'
|
||||
dependency 'mysql:mysql-connector-java:8.0.26'
|
||||
dependency 'org.apache.derby:derby:10.14.2.0'
|
||||
dependency 'org.assertj:assertj-core:3.18.1'
|
||||
dependency 'org.hsqldb:hsqldb:2.5.1'
|
||||
dependency 'org.mariadb.jdbc:mariadb-java-client:2.7.2'
|
||||
dependency 'org.mockito:mockito-core:3.9.0'
|
||||
dependency 'org.postgresql:postgresql:42.2.18'
|
||||
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.postgresql:postgresql:42.2.24'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ asciidoctor {
|
||||
}
|
||||
|
||||
asciidoctorj {
|
||||
def ghTag = snapshotBuild ? 'master' : project.version
|
||||
def ghTag = snapshotBuild ? 'main' : 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/",
|
||||
|
||||
@@ -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/docs/{spring-framework-version}/spring-framework-reference/web-reactive.html[Spring Framework Reference Documentation].
|
||||
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].
|
||||
|
||||
[[spring-security]]
|
||||
== Spring Security Integration
|
||||
|
||||
@@ -31,7 +31,7 @@ artifacts {
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-session-core')
|
||||
optional "com.hazelcast:hazelcast:4.2"
|
||||
optional "com.hazelcast:hazelcast:4.2.2"
|
||||
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.2.2"
|
||||
integrationTestCompile project(":spring-session-hazelcast")
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.session.hazelcast;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.hazelcast.map.IMap;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -198,4 +201,51 @@ abstract class AbstractHazelcast4IndexedSessionRepositoryITests {
|
||||
this.repository.deleteById(sessionId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createAndUpdateSessionWhileKeepingOriginalTimeToLiveConfiguredOnRepository() {
|
||||
final Duration defaultSessionTimeout = Duration.ofSeconds(1800);
|
||||
|
||||
final IMap<String, MapSession> hazelcastMap = this.hazelcastInstance
|
||||
.getMap(Hazelcast4IndexedSessionRepository.DEFAULT_SESSION_MAP_NAME);
|
||||
|
||||
HazelcastSession session = this.repository.createSession();
|
||||
String sessionId = session.getId();
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.getMaxInactiveInterval()).isEqualTo(defaultSessionTimeout);
|
||||
assertThat(hazelcastMap.getEntryView(sessionId).getTtl()).isEqualTo(defaultSessionTimeout.toMillis());
|
||||
|
||||
session = this.repository.findById(sessionId);
|
||||
session.setLastAccessedTime(Instant.now());
|
||||
this.repository.save(session);
|
||||
|
||||
session = this.repository.findById(sessionId);
|
||||
assertThat(session.getMaxInactiveInterval()).isEqualTo(defaultSessionTimeout);
|
||||
assertThat(hazelcastMap.getEntryView(sessionId).getTtl()).isEqualTo(defaultSessionTimeout.toMillis());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createAndUpdateSessionWhileKeepingTimeToLiveSetOnSession() {
|
||||
final Duration individualSessionTimeout = Duration.ofSeconds(23);
|
||||
|
||||
final IMap<String, MapSession> hazelcastMap = this.hazelcastInstance
|
||||
.getMap(Hazelcast4IndexedSessionRepository.DEFAULT_SESSION_MAP_NAME);
|
||||
|
||||
HazelcastSession session = this.repository.createSession();
|
||||
session.setMaxInactiveInterval(individualSessionTimeout);
|
||||
String sessionId = session.getId();
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.getMaxInactiveInterval()).isEqualTo(individualSessionTimeout);
|
||||
assertThat(hazelcastMap.getEntryView(sessionId).getTtl()).isEqualTo(individualSessionTimeout.toMillis());
|
||||
|
||||
session = this.repository.findById(sessionId);
|
||||
session.setAttribute("attribute", "value");
|
||||
this.repository.save(session);
|
||||
|
||||
session = this.repository.findById(sessionId);
|
||||
assertThat(session.getMaxInactiveInterval()).isEqualTo(individualSessionTimeout);
|
||||
assertThat(hazelcastMap.getEntryView(sessionId).getTtl()).isEqualTo(individualSessionTimeout.toMillis());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2020 the original author or authors.
|
||||
* Copyright 2014-2021 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,8 +45,8 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
@WebAppConfiguration
|
||||
class ClientServerHazelcast4IndexedSessionRepositoryITests extends AbstractHazelcast4IndexedSessionRepositoryITests {
|
||||
|
||||
private static GenericContainer container = new GenericContainer<>("hazelcast/hazelcast:4.2").withExposedPorts(5701)
|
||||
.withCopyFileToContainer(MountableFile.forClasspathResource("/hazelcast-server.xml"),
|
||||
private static GenericContainer container = new GenericContainer<>("hazelcast/hazelcast:4.2.2")
|
||||
.withExposedPorts(5701).withCopyFileToContainer(MountableFile.forClasspathResource("/hazelcast-server.xml"),
|
||||
"/opt/hazelcast/hazelcast.xml");
|
||||
|
||||
@BeforeAll
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2020 the original author or authors.
|
||||
* Copyright 2014-2021 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.
|
||||
@@ -57,7 +57,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@WebAppConfiguration
|
||||
class SessionEventHazelcast4IndexedSessionRepositoryTests<S extends Session> {
|
||||
|
||||
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 1;
|
||||
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 2;
|
||||
|
||||
@Autowired
|
||||
private SessionRepository<S> repository;
|
||||
@@ -199,6 +199,29 @@ class SessionEventHazelcast4IndexedSessionRepositoryTests<S extends Session> {
|
||||
assertThat(this.repository.findById(sessionToUpdate.getId())).isNull();
|
||||
}
|
||||
|
||||
@Test // gh-1899
|
||||
void updateSessionAndExpireAfterOriginalTimeToLiveTest() throws InterruptedException {
|
||||
S sessionToSave = this.repository.createSession();
|
||||
this.repository.save(sessionToSave);
|
||||
|
||||
assertThat(this.registry.receivedEvent(sessionToSave.getId())).isTrue();
|
||||
assertThat(this.registry.<SessionCreatedEvent>getEvent(sessionToSave.getId()))
|
||||
.isInstanceOf(SessionCreatedEvent.class);
|
||||
this.registry.clear();
|
||||
|
||||
S sessionToUpdate = this.repository.findById(sessionToSave.getId());
|
||||
sessionToUpdate.setLastAccessedTime(Instant.now());
|
||||
this.repository.save(sessionToUpdate);
|
||||
|
||||
assertThat(this.registry.receivedEvent(sessionToUpdate.getId())).isTrue();
|
||||
assertThat(this.registry.<SessionExpiredEvent>getEvent(sessionToUpdate.getId()))
|
||||
.isInstanceOf(SessionExpiredEvent.class);
|
||||
// Assert this after the expired event was received because it would otherwise do
|
||||
// its own expiration check and explicitly delete the session from Hazelcast
|
||||
// regardless of the TTL of the IMap entry.
|
||||
assertThat(this.repository.findById(sessionToUpdate.getId())).isNull();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableHazelcastHttpSession(maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
|
||||
static class HazelcastSessionConfig {
|
||||
|
||||
@@ -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.1.xsd">
|
||||
xsi:schemaLocation="http://www.hazelcast.com/schema/config https://www.hazelcast.com/schema/config/hazelcast-config-4.2.xsd">
|
||||
|
||||
<network>
|
||||
<join>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2020 the original author or authors.
|
||||
* Copyright 2014-2021 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,6 @@ import org.springframework.session.events.SessionCreatedEvent;
|
||||
import org.springframework.session.events.SessionDeletedEvent;
|
||||
import org.springframework.session.events.SessionExpiredEvent;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.session.SessionRepository} implementation using Hazelcast
|
||||
@@ -128,8 +127,6 @@ public class Hazelcast4IndexedSessionRepository
|
||||
|
||||
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
|
||||
|
||||
private static final boolean SUPPORTS_SET_TTL = ClassUtils.hasAtLeastOneMethodWithName(IMap.class, "setTtl");
|
||||
|
||||
private static final Log logger = LogFactory.getLog(Hazelcast4IndexedSessionRepository.class);
|
||||
|
||||
private final HazelcastInstance hazelcastInstance;
|
||||
@@ -262,9 +259,6 @@ public class Hazelcast4IndexedSessionRepository
|
||||
entryProcessor.setLastAccessedTime(session.getLastAccessedTime());
|
||||
}
|
||||
if (session.maxInactiveIntervalChanged) {
|
||||
if (SUPPORTS_SET_TTL) {
|
||||
updateTtl(session);
|
||||
}
|
||||
entryProcessor.setMaxInactiveInterval(session.getMaxInactiveInterval());
|
||||
}
|
||||
if (!session.delta.isEmpty()) {
|
||||
@@ -275,10 +269,6 @@ public class Hazelcast4IndexedSessionRepository
|
||||
session.clearChangeFlags();
|
||||
}
|
||||
|
||||
private void updateTtl(HazelcastSession session) {
|
||||
this.sessions.setTtl(session.getId(), session.getMaxInactiveInterval().getSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HazelcastSession findById(String id) {
|
||||
MapSession saved = this.sessions.get(id);
|
||||
@@ -416,6 +406,7 @@ public class Hazelcast4IndexedSessionRepository
|
||||
|
||||
@Override
|
||||
public void setMaxInactiveInterval(Duration interval) {
|
||||
Assert.notNull(interval, "interval must not be null");
|
||||
this.delegate.setMaxInactiveInterval(interval);
|
||||
this.maxInactiveIntervalChanged = true;
|
||||
flushImmediateIfNecessary();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2020 the original author or authors.
|
||||
* Copyright 2014-2021 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.
|
||||
@@ -63,13 +63,8 @@ public class Hazelcast4SessionUpdateEntryProcessor implements EntryProcessor<Str
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.maxInactiveInterval != null) {
|
||||
((ExtendedMapEntry<String, MapSession>) entry).setValue(value, this.maxInactiveInterval.getSeconds(),
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
else {
|
||||
entry.setValue(value);
|
||||
}
|
||||
((ExtendedMapEntry<String, MapSession>) entry).setValue(value, value.getMaxInactiveInterval().getSeconds(),
|
||||
TimeUnit.SECONDS);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2020 the original author or authors.
|
||||
* Copyright 2014-2021 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.
|
||||
@@ -46,7 +46,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
@@ -254,7 +253,6 @@ class Hazelcast4IndexedSessionRepositoryTests {
|
||||
session.setMaxInactiveInterval(Duration.ofSeconds(1));
|
||||
verify(this.sessions, times(1)).set(eq(sessionId), eq(session.getDelegate()), isA(Long.class),
|
||||
eq(TimeUnit.SECONDS));
|
||||
verify(this.sessions).setTtl(eq(sessionId), anyLong(), any());
|
||||
verify(this.sessions, times(1)).executeOnKey(eq(sessionId), any(EntryProcessor.class));
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2014-2021 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.hazelcast;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.hazelcast.map.ExtendedMapEntry;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.session.MapSession;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
class Hazelcast4SessionUpdateEntryProcessorTest {
|
||||
|
||||
private Hazelcast4SessionUpdateEntryProcessor processor;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.processor = new Hazelcast4SessionUpdateEntryProcessor();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnFalseIfNoSessionExistsInHazelcastMapEntry() {
|
||||
@SuppressWarnings("unchecked")
|
||||
ExtendedMapEntry<String, MapSession> mapEntry = mock(ExtendedMapEntry.class);
|
||||
|
||||
Object result = this.processor.process(mapEntry);
|
||||
|
||||
assertThat(result).isEqualTo(Boolean.FALSE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUpdateMaxInactiveIntervalOnSessionAndSetMapEntryValueWithNewTimeToLive() {
|
||||
Duration newMaxInactiveInterval = Duration.ofSeconds(123L);
|
||||
MapSession mapSession = new MapSession();
|
||||
@SuppressWarnings("unchecked")
|
||||
ExtendedMapEntry<String, MapSession> mapEntry = mock(ExtendedMapEntry.class);
|
||||
given(mapEntry.getValue()).willReturn(mapSession);
|
||||
|
||||
this.processor.setMaxInactiveInterval(newMaxInactiveInterval);
|
||||
Object result = this.processor.process(mapEntry);
|
||||
|
||||
assertThat(result).isEqualTo(Boolean.TRUE);
|
||||
assertThat(mapSession.getMaxInactiveInterval()).isEqualTo(newMaxInactiveInterval);
|
||||
verify(mapEntry).setValue(mapSession, newMaxInactiveInterval.getSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSetMapEntryValueWithOldTimeToLiveIfNoChangeToMaxInactiveIntervalIsRegistered() {
|
||||
Duration maxInactiveInterval = Duration.ofSeconds(123L);
|
||||
MapSession mapSession = new MapSession();
|
||||
mapSession.setMaxInactiveInterval(maxInactiveInterval);
|
||||
@SuppressWarnings("unchecked")
|
||||
ExtendedMapEntry<String, MapSession> mapEntry = mock(ExtendedMapEntry.class);
|
||||
given(mapEntry.getValue()).willReturn(mapSession);
|
||||
|
||||
Object result = this.processor.process(mapEntry);
|
||||
|
||||
assertThat(result).isEqualTo(Boolean.TRUE);
|
||||
assertThat(mapSession.getMaxInactiveInterval()).isEqualTo(maxInactiveInterval);
|
||||
verify(mapEntry).setValue(mapSession, maxInactiveInterval.getSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUpdateLastAccessTimeOnSessionAndSetMapEntryValueWithOldTimeToLive() {
|
||||
Instant lastAccessTime = Instant.ofEpochSecond(1234L);
|
||||
MapSession mapSession = new MapSession();
|
||||
@SuppressWarnings("unchecked")
|
||||
ExtendedMapEntry<String, MapSession> mapEntry = mock(ExtendedMapEntry.class);
|
||||
given(mapEntry.getValue()).willReturn(mapSession);
|
||||
|
||||
this.processor.setLastAccessedTime(lastAccessTime);
|
||||
Object result = this.processor.process(mapEntry);
|
||||
|
||||
assertThat(result).isEqualTo(Boolean.TRUE);
|
||||
assertThat(mapSession.getLastAccessedTime()).isEqualTo(lastAccessTime);
|
||||
verify(mapEntry).setValue(mapSession, mapSession.getMaxInactiveInterval().getSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUpdateSessionAttributesFromDeltaAndSetMapEntryValueWithOldTimeToLive() {
|
||||
MapSession mapSession = new MapSession();
|
||||
mapSession.setAttribute("changed", "oldValue");
|
||||
mapSession.setAttribute("removed", "existingValue");
|
||||
@SuppressWarnings("unchecked")
|
||||
ExtendedMapEntry<String, MapSession> mapEntry = mock(ExtendedMapEntry.class);
|
||||
given(mapEntry.getValue()).willReturn(mapSession);
|
||||
|
||||
HashMap<String, Object> delta = new HashMap<>();
|
||||
delta.put("added", "addedValue");
|
||||
delta.put("changed", "newValue");
|
||||
delta.put("removed", null);
|
||||
this.processor.setDelta(delta);
|
||||
|
||||
Object result = this.processor.process(mapEntry);
|
||||
|
||||
assertThat(result).isEqualTo(Boolean.TRUE);
|
||||
assertThat((String) mapSession.getAttribute("added")).isEqualTo("addedValue");
|
||||
assertThat((String) mapSession.getAttribute("changed")).isEqualTo("newValue");
|
||||
assertThat((String) mapSession.getAttribute("removed")).isNull();
|
||||
verify(mapEntry).setValue(mapSession, mapSession.getMaxInactiveInterval().getSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
* Copyright 2014-2021 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.
|
||||
@@ -58,7 +58,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@WebAppConfiguration
|
||||
class SessionEventHazelcastIndexedSessionRepositoryTests<S extends Session> {
|
||||
|
||||
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 1;
|
||||
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 2;
|
||||
|
||||
@Autowired
|
||||
private SessionRepository<S> repository;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2020 the original author or authors.
|
||||
* Copyright 2014-2021 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.
|
||||
@@ -30,12 +30,12 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.session.FindByIndexNameSessionRepository;
|
||||
import org.springframework.session.FlushMode;
|
||||
import org.springframework.session.IndexResolver;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.config.SessionRepositoryCustomizer;
|
||||
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
|
||||
import org.springframework.session.hazelcast.Hazelcast4IndexedSessionRepository;
|
||||
@@ -85,7 +85,7 @@ public class HazelcastHttpSessionConfiguration extends SpringHttpSessionConfigur
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SessionRepository<?> sessionRepository() {
|
||||
public FindByIndexNameSessionRepository<?> sessionRepository() {
|
||||
if (hazelcast4) {
|
||||
return createHazelcast4IndexedSessionRepository();
|
||||
}
|
||||
|
||||
@@ -586,6 +586,18 @@ 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";
|
||||
|
||||
@@ -42,11 +42,11 @@ final class DatabaseContainers {
|
||||
}
|
||||
|
||||
static MariaDBContainer<?> mariaDb() {
|
||||
return new MariaDBContainer<>("mariadb:10.5.7");
|
||||
return new MariaDBContainer<>("mariadb:10.6.4");
|
||||
}
|
||||
|
||||
static MySQLContainer<?> mySql() {
|
||||
return new MySQLContainer<>("mysql:8.0.22");
|
||||
return new MySQLContainer<>("mysql:8.0.27");
|
||||
}
|
||||
|
||||
static OracleContainer oracle() {
|
||||
@@ -68,7 +68,7 @@ final class DatabaseContainers {
|
||||
}
|
||||
|
||||
static PostgreSQLContainer<?> postgreSql() {
|
||||
return new PostgreSQLContainer<>("postgres:13.0");
|
||||
return new PostgreSQLContainer<>("postgres:13.3");
|
||||
}
|
||||
|
||||
static MSSQLServerContainer<?> sqlServer() {
|
||||
|
||||
@@ -185,7 +185,8 @@ public class JdbcIndexedSessionRepository
|
||||
// @formatter:off
|
||||
private static final String DELETE_SESSION_QUERY = ""
|
||||
+ "DELETE FROM %TABLE_NAME% "
|
||||
+ "WHERE SESSION_ID = ?";
|
||||
+ "WHERE SESSION_ID = ? "
|
||||
+ "AND MAX_INACTIVE_INTERVAL >= 0";
|
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
@@ -701,6 +702,9 @@ public class JdbcIndexedSessionRepository
|
||||
}
|
||||
|
||||
Instant getExpiryTime() {
|
||||
if (getMaxInactiveInterval().isNegative()) {
|
||||
return Instant.ofEpochMilli(Long.MAX_VALUE);
|
||||
}
|
||||
return getLastAccessedTime().plus(getMaxInactiveInterval());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom 'com.fasterxml.jackson:jackson-bom:2.12.3'
|
||||
mavenBom 'com.fasterxml.jackson:jackson-bom:2.12.5'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
dependency 'ch.qos.logback:logback-classic:1.2.3'
|
||||
dependency 'ch.qos.logback:logback-classic:1.2.6'
|
||||
dependency 'com.maxmind.geoip2:geoip2:2.15.0'
|
||||
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.30'
|
||||
dependency 'org.slf4j:log4j-over-slf4j:1.7.30'
|
||||
dependency 'org.slf4j:jcl-over-slf4j:1.7.32'
|
||||
dependency 'org.slf4j:log4j-over-slf4j:1.7.32'
|
||||
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: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:stomp-websocket:2.3.4'
|
||||
dependency 'org.webjars:webjars-taglib:0.3'
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
apply plugin: 'io.spring.convention.spring-sample-boot'
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-session-hazelcast')
|
||||
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-client"
|
||||
compile "nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect"
|
||||
compile "org.webjars:bootstrap"
|
||||
compile "org.webjars:html5shiv"
|
||||
compile "org.webjars:webjars-locator-core"
|
||||
compile project(':spring-session-hazelcast')
|
||||
compile "org.springframework.boot:spring-boot-starter-web"
|
||||
compile "org.springframework.boot:spring-boot-starter-actuator"
|
||||
compile "org.springframework.boot:spring-boot-starter-thymeleaf"
|
||||
compile "org.springframework.boot:spring-boot-starter-security"
|
||||
compile "com.hazelcast:hazelcast"
|
||||
compile "nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect"
|
||||
compile "org.webjars:bootstrap"
|
||||
compile "org.webjars:html5shiv"
|
||||
compile "org.webjars:webjars-locator-core"
|
||||
|
||||
testCompile "org.springframework.boot:spring-boot-starter-test"
|
||||
testCompile "org.junit.jupiter:junit-jupiter-api"
|
||||
testRuntime "org.junit.jupiter:junit-jupiter-engine"
|
||||
integrationTestCompile seleniumDependencies
|
||||
integrationTestCompile "org.testcontainers:testcontainers"
|
||||
testCompile "org.springframework.boot:spring-boot-starter-test"
|
||||
testCompile "org.junit.jupiter:junit-jupiter-api"
|
||||
testRuntime "org.junit.jupiter:junit-jupiter-engine"
|
||||
integrationTestCompile seleniumDependencies
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2020 the original author or authors.
|
||||
* Copyright 2014-2021 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.
|
||||
@@ -19,32 +19,29 @@ package sample;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import sample.pages.HomePage;
|
||||
import sample.pages.LoginPage;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.session.SessionsEndpoint;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Ellie Bahadori
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@AutoConfigureMockMvc
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
|
||||
class BootTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "hazelcast/hazelcast:latest";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@@ -60,6 +57,12 @@ class BootTests {
|
||||
this.driver.quit();
|
||||
}
|
||||
|
||||
@Test // gh-1905
|
||||
void contextLoads(ApplicationContext context) {
|
||||
assertThat(context.getBeansOfType(HazelcastIndexedSessionRepository.class)).hasSize(1);
|
||||
assertThat(context.getBeansOfType(SessionsEndpoint.class)).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void home() {
|
||||
LoginPage login = HomePage.go(this.driver);
|
||||
@@ -83,16 +86,4 @@ class BootTests {
|
||||
login.assertAt();
|
||||
}
|
||||
|
||||
@TestConfiguration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
GenericContainer hazelcastContainer() {
|
||||
GenericContainer hazelcastContainer = new GenericContainer(DOCKER_IMAGE).withExposedPorts(5701);
|
||||
hazelcastContainer.start();
|
||||
return hazelcastContainer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2020 the original author or authors.
|
||||
* Copyright 2014-2021 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.
|
||||
@@ -34,7 +34,7 @@ import org.springframework.session.hazelcast.PrincipalNameExtractor;
|
||||
public class SessionConfig {
|
||||
|
||||
@Bean
|
||||
public Config clientConfig() {
|
||||
public Config hazelcastConfig() {
|
||||
Config config = new Config();
|
||||
NetworkConfig networkConfig = config.getNetworkConfig();
|
||||
networkConfig.setPort(0);
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
management.endpoints.web.exposure.include=sessions
|
||||
spring.security.user.password=password
|
||||
|
||||
@@ -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/master/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/main/spring-session-samples">samples</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
apply plugin: 'io.spring.convention.spring-sample-boot'
|
||||
|
||||
dependencies {
|
||||
compile project(':spring-session-hazelcast')
|
||||
compile project(':hazelcast4')
|
||||
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"
|
||||
compile "nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect"
|
||||
compile "org.webjars:bootstrap"
|
||||
compile "org.webjars:html5shiv"
|
||||
compile "org.webjars:webjars-locator-core"
|
||||
compile project(':spring-session-hazelcast')
|
||||
compile project(':hazelcast4')
|
||||
compile "org.springframework.boot:spring-boot-starter-web"
|
||||
compile "org.springframework.boot:spring-boot-starter-actuator"
|
||||
compile "org.springframework.boot:spring-boot-starter-thymeleaf"
|
||||
compile "org.springframework.boot:spring-boot-starter-security"
|
||||
compile "com.hazelcast:hazelcast:4.2.2"
|
||||
compile "nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect"
|
||||
compile "org.webjars:bootstrap"
|
||||
compile "org.webjars:html5shiv"
|
||||
compile "org.webjars:webjars-locator-core"
|
||||
|
||||
testCompile "org.springframework.boot:spring-boot-starter-test"
|
||||
testCompile "org.junit.jupiter:junit-jupiter-api"
|
||||
testRuntime "org.junit.jupiter:junit-jupiter-engine"
|
||||
integrationTestCompile seleniumDependencies
|
||||
integrationTestCompile "org.testcontainers:testcontainers"
|
||||
testCompile "org.springframework.boot:spring-boot-starter-test"
|
||||
testCompile "org.junit.jupiter:junit-jupiter-api"
|
||||
testRuntime "org.junit.jupiter:junit-jupiter-engine"
|
||||
integrationTestCompile seleniumDependencies
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2020 the original author or authors.
|
||||
* Copyright 2014-2021 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.
|
||||
@@ -19,29 +19,26 @@ package sample;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import sample.pages.HomePage;
|
||||
import sample.pages.LoginPage;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.session.SessionsEndpoint;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.session.hazelcast.Hazelcast4IndexedSessionRepository;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@AutoConfigureMockMvc
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
|
||||
class BootTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "hazelcast/hazelcast:latest";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@@ -57,6 +54,12 @@ class BootTests {
|
||||
this.driver.quit();
|
||||
}
|
||||
|
||||
@Test // gh-1905
|
||||
void contextLoads(ApplicationContext context) {
|
||||
assertThat(context.getBeansOfType(Hazelcast4IndexedSessionRepository.class)).hasSize(1);
|
||||
assertThat(context.getBeansOfType(SessionsEndpoint.class)).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void home() {
|
||||
LoginPage login = HomePage.go(this.driver);
|
||||
@@ -80,16 +83,4 @@ class BootTests {
|
||||
login.assertAt();
|
||||
}
|
||||
|
||||
@TestConfiguration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
GenericContainer hazelcastContainer() {
|
||||
GenericContainer hazelcastContainer = new GenericContainer(DOCKER_IMAGE).withExposedPorts(5701);
|
||||
hazelcastContainer.start();
|
||||
return hazelcastContainer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2020 the original author or authors.
|
||||
* Copyright 2014-2021 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.
|
||||
@@ -35,7 +35,7 @@ import org.springframework.session.hazelcast.HazelcastSessionSerializer;
|
||||
public class SessionConfig {
|
||||
|
||||
@Bean
|
||||
public Config clientConfig() {
|
||||
public Config hazelcastConfig() {
|
||||
Config config = new Config();
|
||||
NetworkConfig networkConfig = config.getNetworkConfig();
|
||||
networkConfig.setPort(0);
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
management.endpoints.web.exposure.include=sessions
|
||||
spring.security.user.password=password
|
||||
|
||||
@@ -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/master/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/main/spring-session-samples">samples</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -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/master/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/main/spring-session-samples">samples</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -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/master/spring-session-samples">samples</a>.</p>
|
||||
for more <a href="https://github.com/spring-projects/spring-session/tree/main/spring-session-samples">samples</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -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/master/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/main/spring-session-samples">samples</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
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"
|
||||
|
||||
@@ -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/master/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/main/spring-session-samples">samples</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user