Compare commits
60 Commits
2.0.2.RELE
...
2.0.4.RELE
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f7232f12e | ||
|
|
03f0a571b6 | ||
|
|
63a215f73b | ||
|
|
8dac35cf73 | ||
|
|
19b8583d65 | ||
|
|
6de0f44241 | ||
|
|
60d6120b9c | ||
|
|
3bc899e695 | ||
|
|
c2fe999d6c | ||
|
|
d214971e72 | ||
|
|
f4704293a1 | ||
|
|
a8c4f65903 | ||
|
|
4a52de0c18 | ||
|
|
63f105082a | ||
|
|
f55b793185 | ||
|
|
6d027900ee | ||
|
|
42818a1b90 | ||
|
|
b6348736ac | ||
|
|
60581c6427 | ||
|
|
836ea12e93 | ||
|
|
670148f182 | ||
|
|
a39295c02b | ||
|
|
02cd5a6301 | ||
|
|
5824566621 | ||
|
|
b2711600e2 | ||
|
|
06eb768721 | ||
|
|
fb05fa70c7 | ||
|
|
1e93fe87db | ||
|
|
e67f84c6b6 | ||
|
|
dfb2f2f334 | ||
|
|
c8e9630fdd | ||
|
|
751375338c | ||
|
|
538712d162 | ||
|
|
941fdb46f2 | ||
|
|
bb1c099094 | ||
|
|
1d1253e643 | ||
|
|
0e7e2eaf5c | ||
|
|
e601e03e1e | ||
|
|
2c81e50b5e | ||
|
|
ac5ff996f4 | ||
|
|
44130cba80 | ||
|
|
2cd8063c7c | ||
|
|
f42a6c7d1c | ||
|
|
6c2f6c26cc | ||
|
|
91b4efc5bd | ||
|
|
6f8359ba16 | ||
|
|
62bfeb3f05 | ||
|
|
2395582fe6 | ||
|
|
5173026aa8 | ||
|
|
d97ad2ca3e | ||
|
|
a780ee0264 | ||
|
|
d8e7a2aa9f | ||
|
|
45b18dec84 | ||
|
|
ec5406fb01 | ||
|
|
3c2f0fd485 | ||
|
|
cdfa557442 | ||
|
|
edc8a7efff | ||
|
|
a7a30dad30 | ||
|
|
be1d3d30a8 | ||
|
|
010aa5f013 |
19
.editorconfig
Normal file
19
.editorconfig
Normal file
@@ -0,0 +1,19 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
max_line_length = 120
|
||||
|
||||
[*.java]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
charset = latin1
|
||||
continuation_indent_size = 8
|
||||
|
||||
[*.xml]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
charset = latin1
|
||||
continuation_indent_size = 8
|
||||
4
.github/ISSUE_TEMPLATE.md
vendored
4
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,3 +1,7 @@
|
||||
<!--
|
||||
For Security Vulnerabilities, please use https://pivotal.io/security#reporting
|
||||
-->
|
||||
|
||||
<!--
|
||||
Thanks for raising a Spring Session issue. Please provide a brief description of your problem along with the version of Spring Session that you are using. If possible, please also consider putting together a sample application that reproduces the issue.
|
||||
-->
|
||||
|
||||
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,3 +1,7 @@
|
||||
<!--
|
||||
For Security Vulnerabilities, please use https://pivotal.io/security#reporting
|
||||
-->
|
||||
|
||||
<!--
|
||||
Thanks for contributing to Spring Session. Please provide a brief description of your pull-request and reference any related issue numbers (prefix references with #).
|
||||
-->
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -10,6 +10,6 @@ target
|
||||
out
|
||||
.springBeans
|
||||
*.rdb
|
||||
!eclispe/.checkstyle
|
||||
.checkstyle
|
||||
!etc/eclipse/.checkstyle
|
||||
!**/src/**/build
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath 'io.spring.gradle:spring-build-conventions:0.0.13.RELEASE'
|
||||
classpath 'io.spring.gradle:spring-build-conventions:0.0.16.RELEASE'
|
||||
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
|
||||
}
|
||||
repositories {
|
||||
|
||||
@@ -38,6 +38,7 @@ asciidoctor {
|
||||
'lettuce-version': versions['io.lettuce:lettuce-core'],
|
||||
'samples-dir': "$rootProject.projectDir.path/samples/",
|
||||
'session-jdbc-main-resources-dir': "${project(':spring-session-jdbc').projectDir.path}/src/main/resources/",
|
||||
'spring-boot-version': project.springBootVersion,
|
||||
'spring-data-redis-version': versions['org.springframework.data:spring-data-redis'],
|
||||
'spring-framework-version': versions['org.springframework:spring-core'],
|
||||
'spring-security-version': versions['org.springframework.security:spring-security-core'],
|
||||
|
||||
@@ -37,7 +37,7 @@ Thanks to first-class auto configuration support, setting up Spring Session back
|
||||
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
spring.session.store-type=jdbc
|
||||
spring.session.store-type=jdbc # Session store type.
|
||||
----
|
||||
|
||||
Under the hood, Spring Boot will apply configuration that is equivalent to manually adding `@EnableJdbcHttpSession` annotation.
|
||||
@@ -48,10 +48,10 @@ Further customization is possible using `application.properties`:
|
||||
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
server.session.timeout= # Session timeout in seconds.
|
||||
spring.session.jdbc.initializer.enabled= # Create the required session tables on startup if necessary. Enabled automatically if the default table name is set or a custom schema is configured.
|
||||
server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified, seconds will be used.
|
||||
spring.session.jdbc.initialize-schema=embedded # Database schema initialization mode.
|
||||
spring.session.jdbc.schema=classpath:org/springframework/session/jdbc/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema.
|
||||
spring.session.jdbc.table-name=SPRING_SESSION # Name of database table used to store sessions.
|
||||
spring.session.jdbc.table-name=SPRING_SESSION # Name of the database table used to store sessions.
|
||||
----
|
||||
|
||||
For more information, refer to https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-session[Spring Session] portion of the Spring Boot documentation.
|
||||
@@ -65,9 +65,9 @@ For example, you can include the following in your *application.properties*
|
||||
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/myapp
|
||||
spring.datasource.username=myapp
|
||||
spring.datasource.password=secret
|
||||
spring.datasource.url= # JDBC URL of the database.
|
||||
spring.datasource.username= # Login username of the database.
|
||||
spring.datasource.password= # Login password of the database.
|
||||
----
|
||||
|
||||
For more information, refer to https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-configure-datasource[Configure a DataSource] portion of the Spring Boot documentation.
|
||||
|
||||
@@ -35,7 +35,7 @@ Thanks to first-class auto configuration support, setting up Spring Session back
|
||||
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
spring.session.store-type=redis
|
||||
spring.session.store-type=redis # Session store type.
|
||||
----
|
||||
|
||||
Under the hood, Spring Boot will apply configuration that is equivalent to manually adding `@EnableRedisHttpSession` annotation.
|
||||
@@ -46,9 +46,9 @@ Further customization is possible using `application.properties`:
|
||||
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
server.session.timeout= # Session timeout in seconds.
|
||||
spring.session.redis.flush-mode= # Sessions flush mode.
|
||||
spring.session.redis.namespace= # Namespace for keys used to store sessions.
|
||||
server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified, seconds will be used.
|
||||
spring.session.redis.flush-mode=on-save # Sessions flush mode.
|
||||
spring.session.redis.namespace=spring:session # Namespace for keys used to store sessions.
|
||||
----
|
||||
|
||||
For more information, refer to https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-session[Spring Session] portion of the Spring Boot documentation.
|
||||
@@ -62,9 +62,9 @@ For example, you can include the following in your *application.properties*
|
||||
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
spring.redis.host=localhost
|
||||
spring.redis.password=secret
|
||||
spring.redis.port=6379
|
||||
spring.redis.host=localhost # Redis server host.
|
||||
spring.redis.password= # Login password of the redis server.
|
||||
spring.redis.port=6379 # Redis server port.
|
||||
----
|
||||
|
||||
For more information, refer to https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/htmlsingle/#boot-features-connecting-to-redis[Connecting to Redis] portion of the Spring Boot documentation.
|
||||
|
||||
@@ -77,7 +77,7 @@ For the purposes of testing session expiration, you may want to change the sessi
|
||||
|
||||
.src/main/resources/application.properties
|
||||
----
|
||||
server.session.timeout=60
|
||||
server.servlet.session.timeout=1m # Session timeout. If a duration suffix is not specified, seconds will be used.
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
@@ -147,11 +147,12 @@ As a part of this split, the Spring Session Data MongoDB and Spring Session Data
|
||||
* https://github.com/spring-projects/spring-session-data-mongodb[`spring-session-data-mongodb` repository]
|
||||
** Hosts Spring Session Data MongoDB module
|
||||
* https://github.com/spring-projects/spring-session-data-geode[`spring-session-data-geode` repository]
|
||||
** Hosts Spring Session Data Geode/GemFire module
|
||||
** Hosts Spring Session Data Geode and Spring Session Data Geode modules
|
||||
|
||||
Going forward, the plan is to externalize each of the `SessionRepository` implementations into a dedicated repository and provide a Maven BOM (as in "bill of materials") module in order to help users with version management concerns.
|
||||
Finally, Spring Session now also provides a Maven BOM (as in "bill of materials") module in order to help users with version management concerns:
|
||||
|
||||
Modules maintained by the members of Spring Team will be hosted within the https://github.com/spring-projects[`spring-projects` organization], while the community maintained modules will continue to be promoted via <<community-extensions,Community Extensions>> section of this manual.
|
||||
* https://github.com/spring-projects/spring-session-bom[`spring-session-bom` repository]
|
||||
** Hosts Spring Session BOM module
|
||||
|
||||
[[httpsession]]
|
||||
== HttpSession Integration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -67,8 +67,8 @@ public class RememberMeSecurityConfiguration extends WebSecurityConfigurerAdapte
|
||||
@Override
|
||||
@Bean
|
||||
public InMemoryUserDetailsManager userDetailsService() {
|
||||
return new InMemoryUserDetailsManager(User.withDefaultPasswordEncoder()
|
||||
.username("user").password("password").roles("USER").build());
|
||||
return new InMemoryUserDetailsManager(User.withUsername("user")
|
||||
.password("{noop}password").roles("USER").build());
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
springBootVersion=2.0.0.RC1
|
||||
version=2.0.2.RELEASE
|
||||
springBootVersion=2.0.2.RELEASE
|
||||
version=2.0.4.RELEASE
|
||||
|
||||
@@ -1,39 +1,31 @@
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom 'com.fasterxml.jackson:jackson-bom:2.9.4'
|
||||
mavenBom 'io.projectreactor:reactor-bom:Bismuth-SR6'
|
||||
mavenBom 'org.springframework:spring-framework-bom:5.0.4.RELEASE'
|
||||
mavenBom 'org.springframework.data:spring-data-releasetrain:Kay-SR4'
|
||||
mavenBom 'org.springframework.security:spring-security-bom:5.0.2.RELEASE'
|
||||
mavenBom 'com.fasterxml.jackson:jackson-bom:2.9.6'
|
||||
mavenBom 'io.projectreactor:reactor-bom:Bismuth-SR10'
|
||||
mavenBom 'org.springframework:spring-framework-bom:5.0.7.RELEASE'
|
||||
mavenBom 'org.springframework.data:spring-data-releasetrain:Kay-SR8'
|
||||
mavenBom 'org.springframework.security:spring-security-bom:5.0.6.RELEASE'
|
||||
mavenBom 'org.testcontainers:testcontainers-bom:1.7.3'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
dependencySet(group: 'com.hazelcast', version: '3.9.3') {
|
||||
dependencySet(group: 'com.hazelcast', version: '3.9.4') {
|
||||
entry 'hazelcast'
|
||||
entry 'hazelcast-client'
|
||||
}
|
||||
|
||||
dependencySet(group: 'org.testcontainers', version: '1.6.0') {
|
||||
entry 'mariadb'
|
||||
entry 'mssqlserver'
|
||||
entry 'mysql'
|
||||
entry 'postgresql'
|
||||
entry 'testcontainers'
|
||||
}
|
||||
|
||||
dependency 'com.h2database:h2:1.4.196'
|
||||
dependency 'com.microsoft.sqlserver:mssql-jdbc:6.2.2.jre8'
|
||||
dependency 'com.h2database:h2:1.4.197'
|
||||
dependency 'com.microsoft.sqlserver:mssql-jdbc:6.4.0.jre8'
|
||||
dependency 'edu.umd.cs.mtc:multithreadedtc:1.01'
|
||||
dependency 'io.lettuce:lettuce-core:5.0.2.RELEASE'
|
||||
dependency 'io.lettuce:lettuce-core:5.0.4.RELEASE'
|
||||
dependency 'javax.servlet:javax.servlet-api:3.1.0'
|
||||
dependency 'junit:junit:4.12'
|
||||
dependency 'mysql:mysql-connector-java:5.1.45'
|
||||
dependency 'org.apache.derby:derby:10.14.1.0'
|
||||
dependency 'org.assertj:assertj-core:3.9.0'
|
||||
dependency 'org.hsqldb:hsqldb:2.4.0'
|
||||
dependency 'org.mariadb.jdbc:mariadb-java-client:2.2.1'
|
||||
dependency 'org.mockito:mockito-core:2.15.0'
|
||||
dependency 'org.postgresql:postgresql:42.2.1'
|
||||
dependency 'org.seleniumhq.selenium:htmlunit-driver:2.29.2'
|
||||
dependency 'mysql:mysql-connector-java:8.0.11'
|
||||
dependency 'org.apache.derby:derby:10.14.2.0'
|
||||
dependency 'org.assertj:assertj-core:3.10.0'
|
||||
dependency 'org.hsqldb:hsqldb:2.4.1'
|
||||
dependency 'org.mariadb.jdbc:mariadb-java-client:2.2.5'
|
||||
dependency 'org.mockito:mockito-core:2.18.3'
|
||||
dependency 'org.postgresql:postgresql:42.2.2'
|
||||
}
|
||||
}
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-bin.zip
|
||||
|
||||
@@ -10,7 +10,7 @@ dependencies {
|
||||
compile "nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect"
|
||||
compile "org.webjars:bootstrap"
|
||||
compile "org.webjars:html5shiv"
|
||||
compile "org.webjars:webjars-locator"
|
||||
compile "org.webjars:webjars-locator-core"
|
||||
compile "com.maxmind.geoip2:geoip2"
|
||||
compile "org.apache.httpcomponents:httpclient"
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package sample;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
@@ -30,10 +29,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.util.TestPropertyValues;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder;
|
||||
@@ -45,15 +43,10 @@ import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDr
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@AutoConfigureMockMvc
|
||||
@SpringBootTest(classes = FindByUsernameApplication.class, webEnvironment = WebEnvironment.MOCK)
|
||||
@ContextConfiguration(initializers = FindByUsernameTests.Initializer.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
|
||||
public class FindByUsernameTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.8";
|
||||
|
||||
@ClassRule
|
||||
public static GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
@@ -86,16 +79,21 @@ public class FindByUsernameTests {
|
||||
home.terminateButtonDisabled();
|
||||
}
|
||||
|
||||
static class Initializer
|
||||
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
@TestConfiguration
|
||||
static class Config {
|
||||
|
||||
@Override
|
||||
public void initialize(
|
||||
ConfigurableApplicationContext configurableApplicationContext) {
|
||||
TestPropertyValues
|
||||
.of("spring.redis.host=" + redisContainer.getContainerIpAddress(),
|
||||
"spring.redis.port=" + redisContainer.getFirstMappedPort())
|
||||
.applyTo(configurableApplicationContext.getEnvironment());
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LettuceConnectionFactory redisConnectionFactory() {
|
||||
return new LettuceConnectionFactory(redisContainer().getContainerIpAddress(),
|
||||
redisContainer().getFirstMappedPort());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ dependencies {
|
||||
compile "nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect"
|
||||
compile "org.webjars:bootstrap"
|
||||
compile "org.webjars:html5shiv"
|
||||
compile "org.webjars:webjars-locator"
|
||||
compile "org.webjars:webjars-locator-core"
|
||||
compile "com.h2database:h2"
|
||||
|
||||
testCompile "org.springframework.boot:spring-boot-starter-test"
|
||||
|
||||
@@ -35,7 +35,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
public void configure(WebSecurity web) {
|
||||
web
|
||||
.ignoring().antMatchers("/h2-console/**");
|
||||
.ignoring().requestMatchers(PathRequest.toH2Console());
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ dependencies {
|
||||
compile "nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect"
|
||||
compile "org.webjars:bootstrap"
|
||||
compile "org.webjars:html5shiv"
|
||||
compile "org.webjars:webjars-locator"
|
||||
compile "org.webjars:webjars-locator-core"
|
||||
compile "org.apache.httpcomponents:httpclient"
|
||||
|
||||
testCompile "org.springframework.boot:spring-boot-starter-test"
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
@@ -33,10 +32,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.util.TestPropertyValues;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder;
|
||||
@@ -48,16 +46,11 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.MOCK)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
|
||||
@AutoConfigureMockMvc
|
||||
@ContextConfiguration(initializers = HttpRedisJsonTest.Initializer.class)
|
||||
public class HttpRedisJsonTest {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.8";
|
||||
|
||||
@ClassRule
|
||||
public static GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
@@ -110,16 +103,21 @@ public class HttpRedisJsonTest {
|
||||
assertThat(attributes).extracting("attributeValue").contains("Demo Value");
|
||||
}
|
||||
|
||||
static class Initializer
|
||||
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
@TestConfiguration
|
||||
static class Config {
|
||||
|
||||
@Override
|
||||
public void initialize(
|
||||
ConfigurableApplicationContext configurableApplicationContext) {
|
||||
TestPropertyValues
|
||||
.of("spring.redis.host=" + redisContainer.getContainerIpAddress(),
|
||||
"spring.redis.port=" + redisContainer.getFirstMappedPort())
|
||||
.applyTo(configurableApplicationContext.getEnvironment());
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LettuceConnectionFactory redisConnectionFactory() {
|
||||
return new LettuceConnectionFactory(redisContainer().getContainerIpAddress(),
|
||||
redisContainer().getFirstMappedPort());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,19 +16,17 @@
|
||||
|
||||
package sample;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||
import org.springframework.session.data.redis.config.annotation.SpringSessionRedisOperations;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -38,15 +36,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class)
|
||||
@ContextConfiguration(initializers = RedisSerializerTest.Initializer.class)
|
||||
@SpringBootTest
|
||||
public class RedisSerializerTest {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.8";
|
||||
|
||||
@ClassRule
|
||||
public static GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
@SpringSessionRedisOperations
|
||||
private RedisTemplate<Object, Object> sessionRedisTemplate;
|
||||
@@ -59,16 +52,21 @@ public class RedisSerializerTest {
|
||||
.isInstanceOf(GenericJackson2JsonRedisSerializer.class);
|
||||
}
|
||||
|
||||
static class Initializer
|
||||
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
@TestConfiguration
|
||||
static class Config {
|
||||
|
||||
@Override
|
||||
public void initialize(
|
||||
ConfigurableApplicationContext configurableApplicationContext) {
|
||||
TestPropertyValues
|
||||
.of("spring.redis.host=" + redisContainer.getContainerIpAddress(),
|
||||
"spring.redis.port=" + redisContainer.getFirstMappedPort())
|
||||
.applyTo(configurableApplicationContext.getEnvironment());
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LettuceConnectionFactory redisConnectionFactory() {
|
||||
return new LettuceConnectionFactory(redisContainer().getContainerIpAddress(),
|
||||
redisContainer().getFirstMappedPort());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ dependencies {
|
||||
compile "nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect"
|
||||
compile "org.webjars:bootstrap"
|
||||
compile "org.webjars:html5shiv"
|
||||
compile "org.webjars:webjars-locator"
|
||||
compile "org.webjars:webjars-locator-core"
|
||||
|
||||
testCompile "org.springframework.boot:spring-boot-starter-test"
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package sample;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
@@ -30,10 +29,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.util.TestPropertyValues;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder;
|
||||
@@ -44,15 +42,10 @@ import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDr
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@AutoConfigureMockMvc
|
||||
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.MOCK)
|
||||
@ContextConfiguration(initializers = BootTests.Initializer.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
|
||||
public class BootTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.8";
|
||||
|
||||
@ClassRule
|
||||
public static GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
@@ -92,16 +85,21 @@ public class BootTests {
|
||||
login.assertAt();
|
||||
}
|
||||
|
||||
static class Initializer
|
||||
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
@TestConfiguration
|
||||
static class Config {
|
||||
|
||||
@Override
|
||||
public void initialize(
|
||||
ConfigurableApplicationContext configurableApplicationContext) {
|
||||
TestPropertyValues
|
||||
.of("spring.redis.host=" + redisContainer.getContainerIpAddress(),
|
||||
"spring.redis.port=" + redisContainer.getFirstMappedPort())
|
||||
.applyTo(configurableApplicationContext.getEnvironment());
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LettuceConnectionFactory redisConnectionFactory() {
|
||||
return new LettuceConnectionFactory(redisContainer().getContainerIpAddress(),
|
||||
redisContainer().getFirstMappedPort());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
@@ -31,11 +30,10 @@ import sample.pages.HomePage.Attribute;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -43,17 +41,13 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
/**
|
||||
* @author Eddú Meléndez
|
||||
* @author Rob Winch
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = HelloWebFluxApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@ContextConfiguration(initializers = AttributeTests.Initializer.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class AttributeTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.8";
|
||||
|
||||
@ClassRule
|
||||
public static GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
@@ -99,16 +93,21 @@ public class AttributeTests {
|
||||
assertThat(row.getAttributeValue()).isEqualTo("b");
|
||||
}
|
||||
|
||||
static class Initializer
|
||||
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
@TestConfiguration
|
||||
static class Config {
|
||||
|
||||
@Override
|
||||
public void initialize(
|
||||
ConfigurableApplicationContext configurableApplicationContext) {
|
||||
TestPropertyValues
|
||||
.of("spring.redis.host=" + redisContainer.getContainerIpAddress(),
|
||||
"spring.redis.port=" + redisContainer.getFirstMappedPort())
|
||||
.applyTo(configurableApplicationContext.getEnvironment());
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LettuceConnectionFactory redisConnectionFactory() {
|
||||
return new LettuceConnectionFactory(redisContainer().getContainerIpAddress(),
|
||||
redisContainer().getFirstMappedPort());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ dependencies {
|
||||
compile "org.webjars:knockout"
|
||||
compile "org.webjars:sockjs-client"
|
||||
compile "org.webjars:stomp-websocket"
|
||||
compile "org.webjars:webjars-locator"
|
||||
compile "org.webjars:webjars-locator-core"
|
||||
compile "com.h2database:h2"
|
||||
|
||||
testCompile "org.springframework.boot:spring-boot-starter-test"
|
||||
|
||||
@@ -45,7 +45,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
public void configure(WebSecurity web) {
|
||||
web
|
||||
.ignoring().antMatchers("/h2-console/**");
|
||||
.ignoring().requestMatchers(PathRequest.toH2Console());
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
#server.session.timeout=60
|
||||
#server.servlet.session.timeout=1m
|
||||
spring.h2.console.enabled=true
|
||||
|
||||
@@ -20,10 +20,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
@@ -31,10 +28,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
import org.springframework.web.socket.TextMessage;
|
||||
@@ -46,23 +42,17 @@ import org.springframework.web.socket.sockjs.client.SockJsClient;
|
||||
import org.springframework.web.socket.sockjs.client.Transport;
|
||||
import org.springframework.web.socket.sockjs.client.WebSocketTransport;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@ContextConfiguration(initializers = ApplicationTests.Initializer.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class ApplicationTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.8";
|
||||
|
||||
@ClassRule
|
||||
public static GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
@Value("${local.server.port}")
|
||||
private String port;
|
||||
@@ -71,7 +61,7 @@ public class ApplicationTests {
|
||||
private WebSocketHandler webSocketHandler;
|
||||
|
||||
@Test
|
||||
public void run() throws Exception {
|
||||
public void run() {
|
||||
List<Transport> transports = new ArrayList<>(2);
|
||||
transports.add(new WebSocketTransport(new StandardWebSocketClient()));
|
||||
transports.add(new RestTemplateXhrTransport());
|
||||
@@ -80,20 +70,25 @@ public class ApplicationTests {
|
||||
ListenableFuture<WebSocketSession> wsSession = sockJsClient.doHandshake(
|
||||
this.webSocketHandler, "ws://localhost:" + this.port + "/sockjs");
|
||||
|
||||
this.thrown.expect(ExecutionException.class);
|
||||
wsSession.get().sendMessage(new TextMessage("a"));
|
||||
assertThatThrownBy(() -> wsSession.get().sendMessage(new TextMessage("a")))
|
||||
.isInstanceOf(ExecutionException.class);
|
||||
}
|
||||
|
||||
static class Initializer
|
||||
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
@TestConfiguration
|
||||
static class Config {
|
||||
|
||||
@Override
|
||||
public void initialize(
|
||||
ConfigurableApplicationContext configurableApplicationContext) {
|
||||
TestPropertyValues
|
||||
.of("spring.redis.host=" + redisContainer.getContainerIpAddress(),
|
||||
"spring.redis.port=" + redisContainer.getFirstMappedPort())
|
||||
.applyTo(configurableApplicationContext.getEnvironment());
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LettuceConnectionFactory redisConnectionFactory() {
|
||||
return new LettuceConnectionFactory(redisContainer().getContainerIpAddress(),
|
||||
redisContainer().getFirstMappedPort());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ dependencyManagement {
|
||||
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 'org.apache.taglibs:taglibs-standard-jstlel:1.2.5'
|
||||
dependency 'org.seleniumhq.selenium:htmlunit-driver:2.29.3'
|
||||
dependency 'org.slf4j:jcl-over-slf4j:1.7.25'
|
||||
dependency 'org.slf4j:log4j-over-slf4j:1.7.25'
|
||||
dependency 'org.webjars:bootstrap:2.3.2'
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package sample;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -30,23 +28,14 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
@Profile("embedded-redis")
|
||||
public class EmbeddedRedisConfig {
|
||||
|
||||
private static final String REDIS_DOCKER_IMAGE = "redis:4.0.8";
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
@Bean(initMethod = "start")
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
return new GenericContainer(REDIS_DOCKER_IMAGE) {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
try {
|
||||
this.dockerClient.close();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
}.withExposedPorts(6379);
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,7 +28,7 @@ import org.springframework.security.core.userdetails.User;
|
||||
public class SecurityConfig {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication().withUser(User.withDefaultPasswordEncoder()
|
||||
.username("user").password("password").roles("USER").build());
|
||||
auth.inMemoryAuthentication().withUser(User.withUsername("user")
|
||||
.password("{noop}password").roles("USER").build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package sample;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -30,23 +28,14 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
@Profile("embedded-redis")
|
||||
public class EmbeddedRedisConfig {
|
||||
|
||||
private static final String REDIS_DOCKER_IMAGE = "redis:4.0.8";
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
@Bean(initMethod = "start")
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
return new GenericContainer(REDIS_DOCKER_IMAGE) {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
try {
|
||||
this.dockerClient.close();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
}.withExposedPorts(6379);
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -17,7 +17,6 @@ dependencies {
|
||||
testCompile "org.springframework.security:spring-security-test"
|
||||
testCompile "org.assertj:assertj-core"
|
||||
testCompile "org.springframework:spring-test"
|
||||
testCompile "commons-codec:commons-codec"
|
||||
|
||||
integrationTestCompile "org.testcontainers:testcontainers"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package rest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
@@ -55,11 +54,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
@WebAppConfiguration
|
||||
public class RestMockMvcTests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.8";
|
||||
|
||||
@ClassRule
|
||||
public static GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
@Autowired
|
||||
private SessionRepositoryFilter<? extends Session> sessionRepositoryFilter;
|
||||
@@ -97,10 +92,18 @@ public class RestMockMvcTests {
|
||||
@EnableRedisHttpSession
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LettuceConnectionFactory redisConnectionFactory() {
|
||||
return new LettuceConnectionFactory(redisContainer.getContainerIpAddress(),
|
||||
redisContainer.getFirstMappedPort());
|
||||
return new LettuceConnectionFactory(redisContainer().getContainerIpAddress(),
|
||||
redisContainer().getFirstMappedPort());
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,8 +17,8 @@
|
||||
package sample;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* @author Pool Dolorier
|
||||
@@ -52,13 +53,14 @@ public class RestTests {
|
||||
this.restTemplate = new RestTemplate();
|
||||
}
|
||||
|
||||
@Test(expected = HttpClientErrorException.class)
|
||||
@Test
|
||||
public void unauthenticatedUserSentToLogInPage() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||
ResponseEntity<String> entity = getForUser(this.baseUrl + "/",
|
||||
headers, String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
assertThatThrownBy(() -> getForUser(this.baseUrl + "/", headers, String.class))
|
||||
.isInstanceOf(HttpClientErrorException.class)
|
||||
.satisfies(e -> assertThat(((HttpClientErrorException) e).getStatusCode())
|
||||
.isEqualTo(HttpStatus.UNAUTHORIZED));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -122,6 +124,6 @@ public class RestTests {
|
||||
|
||||
private String getAuth(String user, String password) {
|
||||
String auth = user + ":" + password;
|
||||
return new String(Base64.encodeBase64(auth.getBytes()));
|
||||
return Base64.getEncoder().encodeToString(auth.getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package sample;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -30,23 +28,14 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
@Profile("embedded-redis")
|
||||
public class EmbeddedRedisConfig {
|
||||
|
||||
private static final String REDIS_DOCKER_IMAGE = "redis:4.0.8";
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
@Bean(initMethod = "start")
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
return new GenericContainer(REDIS_DOCKER_IMAGE) {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
try {
|
||||
this.dockerClient.close();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
}.withExposedPorts(6379);
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,7 +43,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication().withUser(User.withDefaultPasswordEncoder()
|
||||
.username("user").password("password").roles("USER").build());
|
||||
auth.inMemoryAuthentication().withUser(User.withUsername("user")
|
||||
.password("{noop}password").roles("USER").build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package sample;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -30,23 +28,14 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
@Profile("embedded-redis")
|
||||
public class EmbeddedRedisConfig {
|
||||
|
||||
private static final String REDIS_DOCKER_IMAGE = "redis:4.0.8";
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
@Bean(initMethod = "start")
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
return new GenericContainer(REDIS_DOCKER_IMAGE) {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
try {
|
||||
this.dockerClient.close();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
}.withExposedPorts(6379);
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,7 +28,7 @@ import org.springframework.security.core.userdetails.User;
|
||||
public class SecurityConfig {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication().withUser(User.withDefaultPasswordEncoder()
|
||||
.username("user").password("password").roles("USER").build());
|
||||
auth.inMemoryAuthentication().withUser(User.withUsername("user")
|
||||
.password("{noop}password").roles("USER").build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package sample;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -30,23 +28,14 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
@Profile("embedded-redis")
|
||||
public class EmbeddedRedisConfig {
|
||||
|
||||
private static final String REDIS_DOCKER_IMAGE = "redis:4.0.8";
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
@Bean(initMethod = "start")
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
return new GenericContainer(REDIS_DOCKER_IMAGE) {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
try {
|
||||
this.dockerClient.close();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
}.withExposedPorts(6379);
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -122,7 +122,12 @@ public final class MapSession implements Session, Serializable {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
String getOriginalId() {
|
||||
/**
|
||||
* Get the original session id.
|
||||
* @return the original session id
|
||||
* @see #changeSessionId()
|
||||
*/
|
||||
public String getOriginalId() {
|
||||
return this.originalId;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,7 +22,6 @@ import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -41,7 +40,7 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
|
||||
private Boolean useSecureCookie;
|
||||
|
||||
private boolean useHttpOnlyCookie = isServlet3();
|
||||
private boolean useHttpOnlyCookie = true;
|
||||
|
||||
private String cookiePath;
|
||||
|
||||
@@ -168,16 +167,11 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if a Cookie marked as HTTP Only should be used. The default is true in Servlet
|
||||
* 3+ environments, else false.
|
||||
* Sets if a Cookie marked as HTTP Only should be used. The default is true.
|
||||
*
|
||||
* @param useHttpOnlyCookie determines if the cookie should be marked as HTTP Only.
|
||||
*/
|
||||
public void setUseHttpOnlyCookie(boolean useHttpOnlyCookie) {
|
||||
if (useHttpOnlyCookie && !isServlet3()) {
|
||||
throw new IllegalArgumentException(
|
||||
"You cannot set useHttpOnlyCookie to true in pre Servlet 3 environment");
|
||||
}
|
||||
this.useHttpOnlyCookie = useHttpOnlyCookie;
|
||||
}
|
||||
|
||||
@@ -337,19 +331,4 @@ public class DefaultCookieSerializer implements CookieSerializer {
|
||||
return this.cookiePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the Servlet 3 APIs are detected.
|
||||
*
|
||||
* @return whether the Servlet 3 APIs are detected
|
||||
*/
|
||||
private boolean isServlet3() {
|
||||
try {
|
||||
ServletRequest.class.getMethod("startAsync");
|
||||
return true;
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.session.web.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletContext;
|
||||
@@ -196,14 +197,18 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
private final class SessionRepositoryRequestWrapper
|
||||
extends HttpServletRequestWrapper {
|
||||
|
||||
private Boolean requestedSessionIdValid;
|
||||
|
||||
private boolean requestedSessionInvalidated;
|
||||
|
||||
private final HttpServletResponse response;
|
||||
|
||||
private final ServletContext servletContext;
|
||||
|
||||
private S requestedSession;
|
||||
|
||||
private boolean requestedSessionCached;
|
||||
|
||||
private Boolean requestedSessionIdValid;
|
||||
|
||||
private boolean requestedSessionInvalidated;
|
||||
|
||||
private SessionRepositoryRequestWrapper(HttpServletRequest request,
|
||||
HttpServletResponse response, ServletContext servletContext) {
|
||||
super(request);
|
||||
@@ -225,6 +230,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
}
|
||||
else {
|
||||
S session = wrappedSession.getSession();
|
||||
clearRequestedSessionCache();
|
||||
SessionRepositoryFilter.this.sessionRepository.save(session);
|
||||
String sessionId = session.getId();
|
||||
if (!isRequestedSessionIdValid()
|
||||
@@ -265,9 +271,11 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
@Override
|
||||
public boolean isRequestedSessionIdValid() {
|
||||
if (this.requestedSessionIdValid == null) {
|
||||
String sessionId = getRequestedSessionId();
|
||||
S session = sessionId == null ? null : getSession(sessionId);
|
||||
return isRequestedSessionIdValid(session);
|
||||
S requestedSession = getRequestedSession();
|
||||
if (requestedSession != null) {
|
||||
requestedSession.setLastAccessedTime(Instant.now());
|
||||
}
|
||||
return isRequestedSessionIdValid(requestedSession);
|
||||
}
|
||||
|
||||
return this.requestedSessionIdValid;
|
||||
@@ -284,28 +292,18 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
return getCurrentSession() == null && this.requestedSessionInvalidated;
|
||||
}
|
||||
|
||||
private S getSession(String sessionId) {
|
||||
S session = SessionRepositoryFilter.this.sessionRepository
|
||||
.findById(sessionId);
|
||||
if (session == null) {
|
||||
return null;
|
||||
}
|
||||
session.setLastAccessedTime(Instant.now());
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSessionWrapper getSession(boolean create) {
|
||||
HttpSessionWrapper currentSession = getCurrentSession();
|
||||
if (currentSession != null) {
|
||||
return currentSession;
|
||||
}
|
||||
String requestedSessionId = getRequestedSessionId();
|
||||
if (requestedSessionId != null) {
|
||||
S requestedSession = getRequestedSession();
|
||||
if (requestedSession != null) {
|
||||
if (getAttribute(INVALID_SESSION_ID_ATTR) == null) {
|
||||
S session = getSession(requestedSessionId);
|
||||
requestedSession.setLastAccessedTime(Instant.now());
|
||||
this.requestedSessionIdValid = true;
|
||||
currentSession = new HttpSessionWrapper(session, getServletContext());
|
||||
currentSession = new HttpSessionWrapper(requestedSession, getServletContext());
|
||||
currentSession.setNew(false);
|
||||
setCurrentSession(currentSession);
|
||||
return currentSession;
|
||||
@@ -353,11 +351,30 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
|
||||
@Override
|
||||
public String getRequestedSessionId() {
|
||||
return SessionRepositoryFilter.this.httpSessionIdResolver
|
||||
.resolveSessionIds(this).stream()
|
||||
.filter(sessionId -> SessionRepositoryFilter.this.sessionRepository
|
||||
.findById(sessionId) != null)
|
||||
.findFirst().orElse(null);
|
||||
S requestedSession = getRequestedSession();
|
||||
return (requestedSession != null ? requestedSession.getId() : null);
|
||||
}
|
||||
|
||||
private S getRequestedSession() {
|
||||
if (!this.requestedSessionCached) {
|
||||
List<String> sessionIds = SessionRepositoryFilter.this.httpSessionIdResolver
|
||||
.resolveSessionIds(this);
|
||||
for (String sessionId : sessionIds) {
|
||||
S session = SessionRepositoryFilter.this.sessionRepository
|
||||
.findById(sessionId);
|
||||
if (session != null) {
|
||||
this.requestedSession = session;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.requestedSessionCached = true;
|
||||
}
|
||||
return this.requestedSession;
|
||||
}
|
||||
|
||||
private void clearRequestedSessionCache() {
|
||||
this.requestedSessionCached = false;
|
||||
this.requestedSession = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,6 +394,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
|
||||
super.invalidate();
|
||||
SessionRepositoryRequestWrapper.this.requestedSessionInvalidated = true;
|
||||
setCurrentSession(null);
|
||||
clearRequestedSessionCache();
|
||||
SessionRepositoryFilter.this.sessionRepository.deleteById(getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,6 +46,7 @@ import org.springframework.web.server.session.WebSessionStore;
|
||||
*
|
||||
* @param <S> the {@link Session} type
|
||||
* @author Rob Winch
|
||||
* @author Vedran Pavic
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SpringSessionWebSessionStore<S extends Session> implements WebSessionStore {
|
||||
@@ -94,7 +95,9 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
|
||||
|
||||
@Override
|
||||
public Mono<WebSession> retrieveSession(String sessionId) {
|
||||
return this.sessions.findById(sessionId).map(this::existingSession);
|
||||
return this.sessions.findById(sessionId)
|
||||
.doOnNext(session -> session.setLastAccessedTime(this.clock.instant()))
|
||||
.map(this::existingSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,7 +31,6 @@ import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
|
||||
import org.springframework.messaging.simp.SimpMessageType;
|
||||
import org.springframework.messaging.support.ChannelInterceptor;
|
||||
import org.springframework.messaging.support.ChannelInterceptorAdapter;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -63,7 +62,7 @@ import org.springframework.web.socket.server.HandshakeInterceptor;
|
||||
* @since 1.0
|
||||
*/
|
||||
public final class SessionRepositoryMessageInterceptor<S extends Session>
|
||||
extends ChannelInterceptorAdapter implements HandshakeInterceptor {
|
||||
implements ChannelInterceptor, HandshakeInterceptor {
|
||||
|
||||
private static final String SPRING_SESSION_ID_ATTR_NAME = "SPRING.SESSION.ID";
|
||||
|
||||
@@ -114,7 +113,7 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
|
||||
SimpMessageType messageType = SimpMessageHeaderAccessor
|
||||
.getMessageType(message.getHeaders());
|
||||
if (!this.matchingMessageTypes.contains(messageType)) {
|
||||
return super.preSend(message, channel);
|
||||
return message;
|
||||
}
|
||||
Map<String, Object> sessionHeaders = SimpMessageHeaderAccessor
|
||||
.getSessionAttributes(message.getHeaders());
|
||||
@@ -128,7 +127,7 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
|
||||
this.sessionRepository.save(session);
|
||||
}
|
||||
}
|
||||
return super.preSend(message, channel);
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,6 +24,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
public class MapSessionTests {
|
||||
|
||||
@@ -35,9 +36,11 @@ public class MapSessionTests {
|
||||
this.session.setLastAccessedTime(Instant.ofEpochMilli(1413258262962L));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void constructorNullSession() {
|
||||
new MapSession((Session) null);
|
||||
assertThatThrownBy(() -> new MapSession((Session) null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("session cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -65,9 +68,11 @@ public class MapSessionTests {
|
||||
assertThat(result).isEqualTo(attrValue);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void getRequiredAttributeWhenNullThenException() {
|
||||
this.session.getRequiredAttribute("attrName");
|
||||
assertThatThrownBy(() -> this.session.getRequiredAttribute("attrName"))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Required attribute 'attrName' is missing.");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,6 +27,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Tests for {@link ReactiveMapSessionRepository}.
|
||||
@@ -57,10 +58,11 @@ public class ReactiveMapSessionRepositoryTests {
|
||||
assertThat(findByIdSession.getId()).isEqualTo(this.session.getId());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void constructorMapWhenNullThenThrowsIllegalArgumentException() {
|
||||
Map<String, Session> sessions = null;
|
||||
new ReactiveMapSessionRepository(sessions);
|
||||
assertThatThrownBy(() -> new ReactiveMapSessionRepository(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("sessions cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -49,6 +49,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
@@ -82,6 +83,9 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
|
||||
@Before
|
||||
public void setup() {
|
||||
this.chain = new MockFilterChain();
|
||||
|
||||
reset(this.sessionRepository);
|
||||
reset(this.cookieSerializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -99,7 +103,7 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
|
||||
|
||||
@Test
|
||||
public void usesWrite() throws Exception {
|
||||
given(this.sessionRepository.findById(anyString())).willReturn(new MapSession());
|
||||
given(this.sessionRepository.createSession()).willReturn(new MapSession());
|
||||
|
||||
this.sessionRepositoryFilter.doFilter(this.request, this.response,
|
||||
new MockFilterChain() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,11 +21,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@@ -42,18 +38,15 @@ import org.springframework.session.web.http.SessionRepositoryFilter;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpringHttpSessionConfiguration}.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SpringHttpSessionConfigurationTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
||||
@After
|
||||
@@ -70,10 +63,9 @@ public class SpringHttpSessionConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void noSessionRepositoryConfiguration() {
|
||||
this.thrown.expect(UnsatisfiedDependencyException.class);
|
||||
this.thrown.expectMessage("org.springframework.session.SessionRepository");
|
||||
|
||||
registerAndRefresh(EmptyConfiguration.class);
|
||||
assertThatThrownBy(() -> registerAndRefresh(EmptyConfiguration.class))
|
||||
.isInstanceOf(UnsatisfiedDependencyException.class)
|
||||
.hasMessageContaining("org.springframework.session.SessionRepository");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,15 +20,14 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -43,9 +42,6 @@ import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
*/
|
||||
public class SpringSessionRememberMeServicesTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private SpringSessionRememberMeServices rememberMeServices;
|
||||
|
||||
@Test
|
||||
@@ -71,10 +67,10 @@ public class SpringSessionRememberMeServicesTests {
|
||||
|
||||
@Test
|
||||
public void createWithNullParameter() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("rememberMeParameterName cannot be empty or null");
|
||||
this.rememberMeServices = new SpringSessionRememberMeServices();
|
||||
this.rememberMeServices.setRememberMeParameterName(null);
|
||||
assertThatThrownBy(() -> this.rememberMeServices.setRememberMeParameterName(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("rememberMeParameterName cannot be empty or null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -114,7 +110,8 @@ public class SpringSessionRememberMeServicesTests {
|
||||
this.rememberMeServices = new SpringSessionRememberMeServices();
|
||||
this.rememberMeServices.loginFail(request, response);
|
||||
verify(request, times(1)).getSession(eq(false));
|
||||
verify(session, times(1)).removeAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
||||
verify(session, times(1)).removeAttribute(
|
||||
HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
||||
verifyZeroInteractions(request, response, session);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,9 +21,7 @@ import java.util.Base64;
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
@@ -34,6 +32,7 @@ import org.springframework.session.web.http.CookieSerializer.CookieValue;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Tests for {@link DefaultCookieSerializer}.
|
||||
@@ -50,9 +49,6 @@ public class DefaultCookieSerializerTests {
|
||||
return new Object[] { false, true };
|
||||
}
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private boolean useBase64Encoding;
|
||||
|
||||
private String cookieName;
|
||||
@@ -214,10 +210,12 @@ public class DefaultCookieSerializerTests {
|
||||
assertThat(getCookie().getDomain()).isEqualTo(domainName);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
@Test
|
||||
public void setDomainNameAndDomainNamePatternThrows() {
|
||||
this.serializer.setDomainName("example.com");
|
||||
this.serializer.setDomainNamePattern(".*");
|
||||
assertThatThrownBy(() -> this.serializer.setDomainNamePattern(".*"))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessage("Cannot set both domainName and domainNamePattern");
|
||||
}
|
||||
|
||||
// --- domainNamePattern ---
|
||||
@@ -246,10 +244,12 @@ public class DefaultCookieSerializerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
@Test
|
||||
public void setDomainNamePatternAndDomainNameThrows() {
|
||||
this.serializer.setDomainNamePattern(".*");
|
||||
this.serializer.setDomainName("example.com");
|
||||
assertThatThrownBy(() -> this.serializer.setDomainName("example.com"))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessage("Cannot set both domainName and domainNamePattern");
|
||||
}
|
||||
|
||||
// --- cookieName ---
|
||||
@@ -271,9 +271,11 @@ public class DefaultCookieSerializerTests {
|
||||
assertThat(getCookie().getName()).isEqualTo(cookieName);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void setCookieNameNullThrows() {
|
||||
this.serializer.setCookieName(null);
|
||||
assertThatThrownBy(() -> this.serializer.setCookieName(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("cookieName cannot be null");
|
||||
}
|
||||
|
||||
// --- cookiePath ---
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,15 +20,14 @@ import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Tests for {@link HeaderHttpSessionIdResolver}.
|
||||
@@ -37,9 +36,6 @@ public class HeaderHttpSessionIdResolverTests {
|
||||
|
||||
private static final String HEADER_X_AUTH_TOKEN = "X-Auth-Token";
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private MockHttpServletResponse response;
|
||||
@@ -47,7 +43,7 @@ public class HeaderHttpSessionIdResolverTests {
|
||||
private HeaderHttpSessionIdResolver resolver;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
public void setup() {
|
||||
this.request = new MockHttpServletRequest();
|
||||
this.response = new MockHttpServletResponse();
|
||||
this.resolver = HeaderHttpSessionIdResolver.xAuthToken();
|
||||
@@ -78,9 +74,9 @@ public class HeaderHttpSessionIdResolverTests {
|
||||
|
||||
@Test
|
||||
public void createResolverWithNullHeaderName() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("headerName cannot be null");
|
||||
new HeaderHttpSessionIdResolver(null);
|
||||
assertThatThrownBy(() -> new HeaderHttpSessionIdResolver(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("headerName cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -58,6 +58,7 @@ import org.springframework.session.SessionRepository;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
@@ -66,6 +67,7 @@ import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
@@ -1334,6 +1336,32 @@ public class SessionRepositoryFilterTests {
|
||||
verifyZeroInteractions(sessionRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterSessionRetrievalIsCached() throws Exception {
|
||||
MapSession session = this.sessionRepository.createSession();
|
||||
this.sessionRepository.save(session);
|
||||
SessionRepository<MapSession> sessionRepository = spy(this.sessionRepository);
|
||||
setSessionCookie(session.getId());
|
||||
|
||||
this.filter = new SessionRepositoryFilter<>(sessionRepository);
|
||||
|
||||
doFilter(new DoInFilter() {
|
||||
@Override
|
||||
public void doFilter(HttpServletRequest wrappedRequest,
|
||||
HttpServletResponse wrappedResponse) {
|
||||
wrappedRequest.getSession().invalidate();
|
||||
wrappedRequest.getSession();
|
||||
}
|
||||
});
|
||||
|
||||
// 3 invocations expected: initial resolution, after invalidation, after commit
|
||||
verify(sessionRepository, times(3)).findById(eq(session.getId()));
|
||||
verify(sessionRepository).deleteById(eq(session.getId()));
|
||||
verify(sessionRepository).createSession();
|
||||
verify(sessionRepository).save(any());
|
||||
verifyZeroInteractions(sessionRepository);
|
||||
}
|
||||
|
||||
// --- order
|
||||
|
||||
@Test
|
||||
@@ -1343,15 +1371,19 @@ public class SessionRepositoryFilterTests {
|
||||
}
|
||||
|
||||
// We want the filter to work without any dependencies on Spring
|
||||
@Test(expected = ClassCastException.class)
|
||||
@Test
|
||||
@SuppressWarnings("unused")
|
||||
public void doesNotImplementOrdered() {
|
||||
Ordered o = (Ordered) this.filter;
|
||||
assertThatThrownBy(() -> {
|
||||
Ordered o = (Ordered) this.filter;
|
||||
}).isInstanceOf(ClassCastException.class);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void setHttpSessionIdResolverNull() {
|
||||
this.filter.setHttpSessionIdResolver(null);
|
||||
assertThatThrownBy(() -> this.filter.setHttpSessionIdResolver(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("httpSessionIdResolver cannot be null");
|
||||
}
|
||||
|
||||
// --- helper methods
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,6 +33,7 @@ import org.springframework.session.Session;
|
||||
import org.springframework.web.server.WebSession;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -41,7 +42,7 @@ import static org.mockito.Mockito.verify;
|
||||
* Tests for {@link SpringSessionWebSessionStore}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SpringSessionWebSessionStoreTests<S extends Session> {
|
||||
@@ -66,9 +67,11 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
|
||||
.willReturn(Mono.just(this.createSession));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void constructorWhenNullRepositoryThenThrowsIllegalArgumentException() {
|
||||
new SpringSessionWebSessionStore<S>(null);
|
||||
assertThatThrownBy(() -> new SpringSessionWebSessionStore<S>(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("reactiveSessionRepository cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -268,6 +271,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
|
||||
.retrieveSession(id).block();
|
||||
|
||||
assertThat(retrievedWebSession.isStarted()).isTrue();
|
||||
verify(this.findByIdSession).setLastAccessedTime(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -280,8 +284,11 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
|
||||
verify(this.sessionRepository).deleteById(sessionId);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void setClockWhenNullThenException() {
|
||||
this.webSessionStore.setClock(null);
|
||||
assertThatThrownBy(() -> this.webSessionStore.setClock(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("clock cannot be null");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,6 +31,7 @@ import org.springframework.web.socket.WebSocketHandler;
|
||||
import org.springframework.web.socket.WebSocketSession;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.BDDMockito.willThrow;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -53,9 +54,11 @@ public class WebSocketConnectHandlerDecoratorFactoryTests {
|
||||
this.factory = new WebSocketConnectHandlerDecoratorFactory(this.eventPublisher);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void constructorNullEventPublisher() {
|
||||
new WebSocketConnectHandlerDecoratorFactory(null);
|
||||
assertThatThrownBy(() -> new WebSocketConnectHandlerDecoratorFactory(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("eventPublisher cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,6 +43,7 @@ import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
@@ -79,9 +80,11 @@ public class SessionRepositoryMessageInterceptorTests {
|
||||
given(this.sessionRepository.findById(sessionId)).willReturn(this.session);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void preSendconstructorNullRepository() {
|
||||
new SessionRepositoryMessageInterceptor<>(null);
|
||||
assertThatThrownBy(() -> new SessionRepositoryMessageInterceptor<>(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("sessionRepository cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,14 +132,19 @@ public class SessionRepositoryMessageInterceptorTests {
|
||||
verifyZeroInteractions(this.sessionRepository);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void setMatchingMessageTypesNull() {
|
||||
this.interceptor.setMatchingMessageTypes(null);
|
||||
assertThatThrownBy(() -> this.interceptor.setMatchingMessageTypes(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("matchingMessageTypes cannot be null or empty");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void setMatchingMessageTypesEmpty() {
|
||||
this.interceptor.setMatchingMessageTypes(Collections.emptySet());
|
||||
assertThatThrownBy(
|
||||
() -> this.interceptor.setMatchingMessageTypes(Collections.emptySet()))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("matchingMessageTypes cannot be null or empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.session.data.redis;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -30,19 +29,23 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
|
||||
*/
|
||||
public abstract class AbstractRedisITests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.8";
|
||||
|
||||
@ClassRule
|
||||
public static GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
private static final String DOCKER_IMAGE = "redis:4.0.9";
|
||||
|
||||
protected static class BaseConfig {
|
||||
|
||||
@Bean
|
||||
public GenericContainer redisContainer() {
|
||||
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
|
||||
.withExposedPorts(6379);
|
||||
redisContainer.start();
|
||||
return redisContainer;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LettuceConnectionFactory redisConnectionFactory() {
|
||||
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(
|
||||
redisContainer.getContainerIpAddress(),
|
||||
redisContainer.getFirstMappedPort());
|
||||
redisContainer().getContainerIpAddress(),
|
||||
redisContainer().getFirstMappedPort());
|
||||
return new LettuceConnectionFactory(configuration);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -149,8 +148,7 @@ public class ReactiveRedisOperationsSessionRepository implements
|
||||
String sessionKey = getSessionKey(id);
|
||||
|
||||
return this.sessionRedisOperations.opsForHash().entries(sessionKey)
|
||||
.collect(
|
||||
Collectors.toMap(e -> e.getKey().toString(), Map.Entry::getValue))
|
||||
.collectMap(e -> e.getKey().toString(), Map.Entry::getValue)
|
||||
.filter(map -> !map.isEmpty()).map(new SessionMapper(id))
|
||||
.filter(session -> !session.isExpired()).map(RedisSession::new)
|
||||
.switchIfEmpty(Mono.defer(() -> deleteById(id).then(Mono.empty())));
|
||||
|
||||
@@ -808,7 +808,12 @@ public class RedisOperationsSessionRepository implements
|
||||
if (!isNew()) {
|
||||
String originalSessionIdKey = getSessionKey(this.originalSessionId);
|
||||
String sessionIdKey = getSessionKey(sessionId);
|
||||
RedisOperationsSessionRepository.this.sessionRedisOperations.rename(originalSessionIdKey, sessionIdKey);
|
||||
RedisOperationsSessionRepository.this.sessionRedisOperations.rename(
|
||||
originalSessionIdKey, sessionIdKey);
|
||||
String originalExpiredKey = getExpiredKey(this.originalSessionId);
|
||||
String expiredKey = getExpiredKey(sessionId);
|
||||
RedisOperationsSessionRepository.this.sessionRedisOperations.rename(
|
||||
originalExpiredKey, expiredKey);
|
||||
}
|
||||
this.originalSessionId = sessionId;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,9 +23,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -34,13 +32,16 @@ import reactor.test.StepVerifier;
|
||||
import org.springframework.data.redis.core.ReactiveHashOperations;
|
||||
import org.springframework.data.redis.core.ReactiveRedisOperations;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.data.redis.ReactiveRedisOperationsSessionRepository.RedisSession;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
/**
|
||||
@@ -50,9 +51,6 @@ import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
*/
|
||||
public class ReactiveRedisOperationsSessionRepositoryTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ReactiveRedisOperations<String, Object> redisOperations = mock(
|
||||
ReactiveRedisOperations.class);
|
||||
@@ -67,18 +65,24 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
|
||||
|
||||
private ReactiveRedisOperationsSessionRepository repository;
|
||||
|
||||
private MapSession cached;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
public void setUp() {
|
||||
this.repository = new ReactiveRedisOperationsSessionRepository(
|
||||
this.redisOperations);
|
||||
|
||||
this.cached = new MapSession();
|
||||
this.cached.setId("session-id");
|
||||
this.cached.setCreationTime(Instant.ofEpochMilli(1404360000000L));
|
||||
this.cached.setLastAccessedTime(Instant.ofEpochMilli(1404360000000L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWithNullReactiveRedisOperations() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("sessionRedisOperations cannot be null");
|
||||
|
||||
new ReactiveRedisOperationsSessionRepository(null);
|
||||
assertThatThrownBy(() -> new ReactiveRedisOperationsSessionRepository(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("sessionRedisOperations cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -91,18 +95,16 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
public void nullRedisKeyNamespace() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("namespace cannot be null or empty");
|
||||
|
||||
this.repository.setRedisKeyNamespace(null);
|
||||
assertThatThrownBy(() -> this.repository.setRedisKeyNamespace(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("namespace cannot be null or empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyRedisKeyNamespace() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("namespace cannot be null or empty");
|
||||
|
||||
this.repository.setRedisKeyNamespace("");
|
||||
assertThatThrownBy(() -> this.repository.setRedisKeyNamespace(""))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("namespace cannot be null or empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -123,148 +125,147 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
public void nullRedisFlushMode() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("redisFlushMode cannot be null");
|
||||
|
||||
this.repository.setRedisFlushMode(null);
|
||||
assertThatThrownBy(() -> this.repository.setRedisFlushMode(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("redisFlushMode cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSessionDefaultMaxInactiveInterval() {
|
||||
Mono<ReactiveRedisOperationsSessionRepository.RedisSession> session = this.repository
|
||||
.createSession();
|
||||
|
||||
StepVerifier.create(session).expectNextMatches(predicate -> {
|
||||
assertThat(predicate.getMaxInactiveInterval()).isEqualTo(
|
||||
Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
|
||||
return true;
|
||||
});
|
||||
StepVerifier.create(this.repository.createSession()).consumeNextWith(
|
||||
session -> assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration
|
||||
.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS)))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSessionCustomMaxInactiveInterval() {
|
||||
this.repository.setDefaultMaxInactiveInterval(600);
|
||||
Mono<ReactiveRedisOperationsSessionRepository.RedisSession> session = this.repository
|
||||
.createSession();
|
||||
|
||||
StepVerifier.create(session).expectNextMatches(predicate -> {
|
||||
assertThat(predicate.getMaxInactiveInterval())
|
||||
.isEqualTo(Duration.ofSeconds(600));
|
||||
return true;
|
||||
});
|
||||
StepVerifier.create(this.repository.createSession())
|
||||
.consumeNextWith(session -> assertThat(session.getMaxInactiveInterval())
|
||||
.isEqualTo(Duration.ofSeconds(600)))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveNewSession() {
|
||||
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
|
||||
given(this.hashOperations.putAll(anyString(), this.delta.capture()))
|
||||
.willReturn(Mono.just(true));
|
||||
given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true));
|
||||
given(this.redisOperations.expire(anyString(), any()))
|
||||
.willReturn(Mono.just(true));
|
||||
|
||||
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository.new RedisSession();
|
||||
Mono<Void> result = this.repository.save(session);
|
||||
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);
|
||||
|
||||
StepVerifier.create(result).expectNextMatches(predicate -> {
|
||||
Map<String, Object> delta = this.delta.getAllValues().get(0);
|
||||
assertThat(delta.size()).isEqualTo(3);
|
||||
Object creationTime = delta
|
||||
.get(ReactiveRedisOperationsSessionRepository.CREATION_TIME_KEY);
|
||||
assertThat(creationTime).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.getCreationTime().toEpochMilli());
|
||||
return true;
|
||||
});
|
||||
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();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveSessionNothingChanged() {
|
||||
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository.new RedisSession(
|
||||
new MapSession());
|
||||
given(this.redisOperations.expire(anyString(), any()))
|
||||
.willReturn(Mono.just(true));
|
||||
|
||||
Mono<Void> result = this.repository.save(session);
|
||||
RedisSession session = this.repository.new RedisSession(
|
||||
new MapSession(this.cached));
|
||||
|
||||
StepVerifier.create(result).expectNextMatches(predicate -> {
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
return true;
|
||||
});
|
||||
StepVerifier.create(this.repository.save(session)).verifyComplete();
|
||||
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.hashOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveLastAccessChanged() {
|
||||
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
|
||||
given(this.hashOperations.putAll(anyString(), this.delta.capture()))
|
||||
.willReturn(Mono.just(true));
|
||||
given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true));
|
||||
given(this.redisOperations.expire(anyString(), any()))
|
||||
.willReturn(Mono.just(true));
|
||||
|
||||
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository.new RedisSession(
|
||||
new MapSession());
|
||||
RedisSession session = this.repository.new RedisSession(this.cached);
|
||||
session.setLastAccessedTime(Instant.ofEpochMilli(12345678L));
|
||||
Mono<Void> result = this.repository.save(session);
|
||||
Mono.just(session).subscribe(this.repository::save);
|
||||
|
||||
StepVerifier.create(result).expectNextMatches(predicate -> {
|
||||
assertThat(this.delta.getAllValues().get(0))
|
||||
.isEqualTo(map(RedisOperationsSessionRepository.LAST_ACCESSED_ATTR,
|
||||
session.getLastAccessedTime().toEpochMilli()));
|
||||
return true;
|
||||
});
|
||||
verify(this.redisOperations).opsForHash();
|
||||
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
|
||||
verify(this.redisOperations).expire(anyString(), any());
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.hashOperations);
|
||||
|
||||
assertThat(this.delta.getAllValues().get(0))
|
||||
.isEqualTo(map(RedisOperationsSessionRepository.LAST_ACCESSED_ATTR,
|
||||
session.getLastAccessedTime().toEpochMilli()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveSetAttribute() {
|
||||
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
|
||||
given(this.hashOperations.putAll(anyString(), this.delta.capture()))
|
||||
.willReturn(Mono.just(true));
|
||||
given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true));
|
||||
given(this.redisOperations.expire(anyString(), any()))
|
||||
.willReturn(Mono.just(true));
|
||||
|
||||
String attrName = "attrName";
|
||||
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository.new RedisSession(
|
||||
new MapSession());
|
||||
RedisSession session = this.repository.new RedisSession(this.cached);
|
||||
session.setAttribute(attrName, "attrValue");
|
||||
Mono<Void> result = this.repository.save(session);
|
||||
Mono.just(session).subscribe(this.repository::save);
|
||||
|
||||
StepVerifier.create(result).expectNextMatches(predicate -> {
|
||||
assertThat(this.delta.getAllValues().get(0)).isEqualTo(
|
||||
map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName),
|
||||
session.getAttribute(attrName)));
|
||||
return true;
|
||||
});
|
||||
verify(this.redisOperations).opsForHash();
|
||||
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
|
||||
verify(this.redisOperations).expire(anyString(), any());
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.hashOperations);
|
||||
|
||||
assertThat(this.delta.getAllValues().get(0)).isEqualTo(
|
||||
map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName),
|
||||
session.getAttribute(attrName)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveRemoveAttribute() {
|
||||
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
|
||||
given(this.hashOperations.putAll(anyString(), this.delta.capture()))
|
||||
.willReturn(Mono.just(true));
|
||||
given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true));
|
||||
given(this.redisOperations.expire(anyString(), any()))
|
||||
.willReturn(Mono.just(true));
|
||||
|
||||
String attrName = "attrName";
|
||||
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository.new RedisSession(
|
||||
new MapSession());
|
||||
RedisSession session = this.repository.new RedisSession(new MapSession());
|
||||
session.removeAttribute(attrName);
|
||||
Mono<Void> result = this.repository.save(session);
|
||||
Mono.just(session).subscribe(this.repository::save);
|
||||
|
||||
StepVerifier.create(result).expectNextMatches(predicate -> {
|
||||
assertThat(this.delta.getAllValues().get(0)).isEqualTo(
|
||||
map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName),
|
||||
null));
|
||||
return true;
|
||||
});
|
||||
verify(this.redisOperations).opsForHash();
|
||||
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
|
||||
verify(this.redisOperations).expire(anyString(), any());
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.hashOperations);
|
||||
|
||||
assertThat(this.delta.getAllValues().get(0)).isEqualTo(map(
|
||||
RedisOperationsSessionRepository.getSessionAttrNameKey(attrName), null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redisSessionGetAttributes() {
|
||||
String attrName = "attrName";
|
||||
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository.new RedisSession();
|
||||
RedisSession session = this.repository.new RedisSession(this.cached);
|
||||
assertThat(session.getAttributeNames()).isEmpty();
|
||||
|
||||
session.setAttribute(attrName, "attrValue");
|
||||
@@ -278,88 +279,94 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
|
||||
public void delete() {
|
||||
given(this.redisOperations.delete(anyString())).willReturn(Mono.just(1L));
|
||||
|
||||
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository.new RedisSession(
|
||||
new MapSession());
|
||||
Mono<Void> result = this.repository.deleteById(session.getId());
|
||||
StepVerifier.create(this.repository.deleteById("test")).verifyComplete();
|
||||
|
||||
StepVerifier.create(result).expectNextMatches(predicate -> {
|
||||
assertThat(result).isEqualTo(1);
|
||||
return true;
|
||||
});
|
||||
verify(this.redisOperations).delete(anyString());
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.hashOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSessionNotFound() {
|
||||
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
|
||||
given(this.hashOperations.entries(anyString())).willReturn(Flux.empty());
|
||||
given(this.redisOperations.delete(anyString())).willReturn(Mono.just(0L));
|
||||
|
||||
Mono<ReactiveRedisOperationsSessionRepository.RedisSession> session = this.repository
|
||||
.findById("test");
|
||||
StepVerifier.create(this.repository.findById("test")).verifyComplete();
|
||||
|
||||
StepVerifier.create(session).expectNextMatches(predicate -> {
|
||||
assertThat(predicate).isEqualTo(Mono.empty());
|
||||
return true;
|
||||
});
|
||||
verify(this.redisOperations).opsForHash();
|
||||
verify(this.hashOperations).entries(anyString());
|
||||
verify(this.redisOperations).delete(anyString());
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.hashOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getSessionFound() {
|
||||
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
|
||||
String attrName = "attrName";
|
||||
MapSession expected = new MapSession();
|
||||
String attribute1 = "attribute1";
|
||||
String attribute2 = "attribute2";
|
||||
MapSession expected = new MapSession("test");
|
||||
expected.setLastAccessedTime(Instant.now().minusSeconds(60));
|
||||
expected.setAttribute(attrName, "attrValue");
|
||||
Map map = map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName),
|
||||
expected.getAttribute(attrName),
|
||||
RedisOperationsSessionRepository.CREATION_TIME_ATTR,
|
||||
expected.setAttribute(attribute1, "test");
|
||||
expected.setAttribute(attribute2, null);
|
||||
Map map = map(
|
||||
ReactiveRedisOperationsSessionRepository.ATTRIBUTE_PREFIX + attribute1,
|
||||
expected.getAttribute(attribute1),
|
||||
ReactiveRedisOperationsSessionRepository.ATTRIBUTE_PREFIX + attribute2,
|
||||
expected.getAttribute(attribute2),
|
||||
ReactiveRedisOperationsSessionRepository.CREATION_TIME_KEY,
|
||||
expected.getCreationTime().toEpochMilli(),
|
||||
RedisOperationsSessionRepository.MAX_INACTIVE_ATTR,
|
||||
ReactiveRedisOperationsSessionRepository.MAX_INACTIVE_INTERVAL_KEY,
|
||||
(int) expected.getMaxInactiveInterval().getSeconds(),
|
||||
RedisOperationsSessionRepository.LAST_ACCESSED_ATTR,
|
||||
ReactiveRedisOperationsSessionRepository.LAST_ACCESSED_TIME_KEY,
|
||||
expected.getLastAccessedTime().toEpochMilli());
|
||||
given(this.hashOperations.entries(anyString()))
|
||||
.willReturn(Flux.fromIterable(map.entrySet()));
|
||||
|
||||
Mono<ReactiveRedisOperationsSessionRepository.RedisSession> session = this.repository
|
||||
.findById("test");
|
||||
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(session).expectNextMatches(predicate -> {
|
||||
assertThat(predicate.getId()).isEqualTo(expected.getId());
|
||||
assertThat(predicate.getAttributeNames())
|
||||
assertThat(session.getId()).isEqualTo(expected.getId());
|
||||
assertThat(session.getAttributeNames())
|
||||
.isEqualTo(expected.getAttributeNames());
|
||||
assertThat(predicate.<String>getAttribute(attrName))
|
||||
.isEqualTo(expected.getAttribute(attrName));
|
||||
assertThat(predicate.getCreationTime()).isEqualTo(expected.getCreationTime());
|
||||
assertThat(predicate.getMaxInactiveInterval())
|
||||
assertThat(session.<String>getAttribute(attribute1))
|
||||
.isEqualTo(expected.getAttribute(attribute1));
|
||||
assertThat(session.<String>getAttribute(attribute2))
|
||||
.isEqualTo(expected.getAttribute(attribute2));
|
||||
assertThat(session.getCreationTime()).isEqualTo(expected.getCreationTime());
|
||||
assertThat(session.getMaxInactiveInterval())
|
||||
.isEqualTo(expected.getMaxInactiveInterval());
|
||||
assertThat(predicate.getLastAccessedTime())
|
||||
assertThat(session.getLastAccessedTime())
|
||||
.isEqualTo(expected.getLastAccessedTime());
|
||||
return true;
|
||||
});
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getSessionExpired() {
|
||||
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
|
||||
Map map = map(RedisOperationsSessionRepository.MAX_INACTIVE_ATTR, 1,
|
||||
RedisOperationsSessionRepository.LAST_ACCESSED_ATTR,
|
||||
Map map = map(ReactiveRedisOperationsSessionRepository.CREATION_TIME_KEY, 0L,
|
||||
ReactiveRedisOperationsSessionRepository.MAX_INACTIVE_INTERVAL_KEY, 1,
|
||||
ReactiveRedisOperationsSessionRepository.LAST_ACCESSED_TIME_KEY,
|
||||
Instant.now().minus(5, ChronoUnit.MINUTES).toEpochMilli());
|
||||
given(this.hashOperations.entries(anyString()))
|
||||
.willReturn(Flux.fromIterable(map.entrySet()));
|
||||
given(this.redisOperations.delete(anyString())).willReturn(Mono.just(0L));
|
||||
|
||||
Mono<ReactiveRedisOperationsSessionRepository.RedisSession> session = this.repository
|
||||
.findById("test");
|
||||
StepVerifier.create(this.repository.findById("test")).verifyComplete();
|
||||
|
||||
StepVerifier.create(session).expectNextMatches(predicate -> {
|
||||
assertThat(predicate).isNull();
|
||||
return true;
|
||||
});
|
||||
verify(this.redisOperations).opsForHash();
|
||||
verify(this.hashOperations).entries(anyString());
|
||||
verify(this.redisOperations).delete(anyString());
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.hashOperations);
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
private Map<String, Object> map(Object... objects) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (objects == null) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -58,9 +58,11 @@ import org.springframework.session.data.redis.RedisOperationsSessionRepository.R
|
||||
import org.springframework.session.events.AbstractSessionEvent;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -110,21 +112,54 @@ public class RedisOperationsSessionRepositoryTests {
|
||||
this.cached.setLastAccessedTime(Instant.ofEpochMilli(1404360000000L));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void setApplicationEventPublisherNull() {
|
||||
this.redisRepository.setApplicationEventPublisher(null);
|
||||
assertThatThrownBy(() -> this.redisRepository.setApplicationEventPublisher(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("applicationEventPublisher cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changeSessionId() {
|
||||
public void changeSessionIdWhenNotSaved() {
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations.boundValueOps(anyString()))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
RedisSession createSession = this.redisRepository.createSession();
|
||||
String originalId = createSession.getId();
|
||||
String changeSessionId = createSession.changeSessionId();
|
||||
this.redisRepository.save(createSession);
|
||||
|
||||
verify(this.redisOperations, never()).rename(anyString(), anyString());
|
||||
|
||||
assertThat(originalId).isNotEqualTo(changeSessionId);
|
||||
assertThat(createSession.getId()).isEqualTo(createSession.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changeSessionIdWhenSaved() {
|
||||
given(this.redisOperations.boundHashOps(anyString()))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.redisOperations.boundSetOps(anyString()))
|
||||
.willReturn(this.boundSetOperations);
|
||||
given(this.redisOperations.boundValueOps(anyString()))
|
||||
.willReturn(this.boundValueOperations);
|
||||
|
||||
RedisSession session = this.redisRepository.new RedisSession(this.cached);
|
||||
session.setLastAccessedTime(session.getLastAccessedTime());
|
||||
String originalId = session.getId();
|
||||
String changeSessionId = session.changeSessionId();
|
||||
this.redisRepository.save(session);
|
||||
|
||||
verify(this.redisOperations, times(2)).rename(anyString(), anyString());
|
||||
|
||||
assertThat(originalId).isNotEqualTo(changeSessionId);
|
||||
assertThat(session.getId()).isEqualTo(session.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSessionDefaultMaxInactiveInterval() throws Exception {
|
||||
Session session = this.redisRepository.createSession();
|
||||
@@ -369,14 +404,18 @@ public class RedisOperationsSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
public void getSessionFound() {
|
||||
String attrName = "attrName";
|
||||
String attribute1 = "attribute1";
|
||||
String attribute2 = "attribute2";
|
||||
MapSession expected = new MapSession();
|
||||
expected.setLastAccessedTime(Instant.now().minusSeconds(60));
|
||||
expected.setAttribute(attrName, "attrValue");
|
||||
expected.setAttribute(attribute1, "test");
|
||||
expected.setAttribute(attribute2, null);
|
||||
given(this.redisOperations.boundHashOps(getKey(expected.getId())))
|
||||
.willReturn(this.boundHashOperations);
|
||||
Map map = map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName),
|
||||
expected.getAttribute(attrName),
|
||||
Map map = map(RedisOperationsSessionRepository.getSessionAttrNameKey(attribute1),
|
||||
expected.getAttribute(attribute1),
|
||||
RedisOperationsSessionRepository.getSessionAttrNameKey(attribute2),
|
||||
expected.getAttribute(attribute2),
|
||||
RedisOperationsSessionRepository.CREATION_TIME_ATTR,
|
||||
expected.getCreationTime().toEpochMilli(),
|
||||
RedisOperationsSessionRepository.MAX_INACTIVE_ATTR,
|
||||
@@ -388,8 +427,10 @@ public class RedisOperationsSessionRepositoryTests {
|
||||
RedisSession session = this.redisRepository.findById(expected.getId());
|
||||
assertThat(session.getId()).isEqualTo(expected.getId());
|
||||
assertThat(session.getAttributeNames()).isEqualTo(expected.getAttributeNames());
|
||||
assertThat(session.<String>getAttribute(attrName))
|
||||
.isEqualTo(expected.getAttribute(attrName));
|
||||
assertThat(session.<String>getAttribute(attribute1))
|
||||
.isEqualTo(expected.getAttribute(attribute1));
|
||||
assertThat(session.<String>getAttribute(attribute2))
|
||||
.isEqualTo(expected.getAttribute(attribute2));
|
||||
assertThat(session.getCreationTime()).isEqualTo(expected.getCreationTime());
|
||||
assertThat(session.getMaxInactiveInterval())
|
||||
.isEqualTo(expected.getMaxInactiveInterval());
|
||||
@@ -517,6 +558,104 @@ public class RedisOperationsSessionRepositoryTests {
|
||||
verify(this.defaultSerializer).deserialize(body);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onMessageDeletedSessionFound() throws Exception {
|
||||
String deletedId = "deleted-id";
|
||||
given(this.redisOperations.boundHashOps(getKey(deletedId)))
|
||||
.willReturn(this.boundHashOperations);
|
||||
Map map = map(RedisOperationsSessionRepository.MAX_INACTIVE_ATTR, 0,
|
||||
RedisOperationsSessionRepository.LAST_ACCESSED_ATTR,
|
||||
System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(5));
|
||||
given(this.boundHashOperations.entries()).willReturn(map);
|
||||
|
||||
String channel = "__keyevent@0__:del";
|
||||
String body = "spring:session:sessions:expires:" + deletedId;
|
||||
DefaultMessage message = new DefaultMessage(channel.getBytes("UTF-8"), body.getBytes("UTF-8"));
|
||||
|
||||
this.redisRepository.setApplicationEventPublisher(this.publisher);
|
||||
this.redisRepository.onMessage(message, "".getBytes("UTF-8"));
|
||||
|
||||
verify(this.redisOperations).boundHashOps(eq(getKey(deletedId)));
|
||||
verify(this.boundHashOperations).entries();
|
||||
verify(this.publisher).publishEvent(this.event.capture());
|
||||
assertThat(this.event.getValue().getSessionId()).isEqualTo(deletedId);
|
||||
verifyZeroInteractions(this.defaultSerializer);
|
||||
verifyZeroInteractions(this.publisher);
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.boundHashOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onMessageDeletedSessionNotFound() throws Exception {
|
||||
String deletedId = "deleted-id";
|
||||
given(this.redisOperations.boundHashOps(getKey(deletedId)))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.boundHashOperations.entries()).willReturn(map());
|
||||
|
||||
String channel = "__keyevent@0__:del";
|
||||
String body = "spring:session:sessions:expires:" + deletedId;
|
||||
DefaultMessage message = new DefaultMessage(channel.getBytes("UTF-8"), body.getBytes("UTF-8"));
|
||||
|
||||
this.redisRepository.setApplicationEventPublisher(this.publisher);
|
||||
this.redisRepository.onMessage(message, "".getBytes("UTF-8"));
|
||||
|
||||
verify(this.redisOperations).boundHashOps(eq(getKey(deletedId)));
|
||||
verify(this.boundHashOperations).entries();
|
||||
verifyZeroInteractions(this.defaultSerializer);
|
||||
verifyZeroInteractions(this.publisher);
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.boundHashOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onMessageExpiredSessionFound() throws Exception {
|
||||
String expiredId = "expired-id";
|
||||
given(this.redisOperations.boundHashOps(getKey(expiredId)))
|
||||
.willReturn(this.boundHashOperations);
|
||||
Map map = map(RedisOperationsSessionRepository.MAX_INACTIVE_ATTR, 1,
|
||||
RedisOperationsSessionRepository.LAST_ACCESSED_ATTR,
|
||||
System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(5));
|
||||
given(this.boundHashOperations.entries()).willReturn(map);
|
||||
|
||||
String channel = "__keyevent@0__:expired";
|
||||
String body = "spring:session:sessions:expires:" + expiredId;
|
||||
DefaultMessage message = new DefaultMessage(channel.getBytes("UTF-8"), body.getBytes("UTF-8"));
|
||||
|
||||
this.redisRepository.setApplicationEventPublisher(this.publisher);
|
||||
this.redisRepository.onMessage(message, "".getBytes("UTF-8"));
|
||||
|
||||
verify(this.redisOperations).boundHashOps(eq(getKey(expiredId)));
|
||||
verify(this.boundHashOperations).entries();
|
||||
verify(this.publisher).publishEvent(this.event.capture());
|
||||
assertThat(this.event.getValue().getSessionId()).isEqualTo(expiredId);
|
||||
verifyZeroInteractions(this.defaultSerializer);
|
||||
verifyZeroInteractions(this.publisher);
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.boundHashOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onMessageExpiredSessionNotFound() throws Exception {
|
||||
String expiredId = "expired-id";
|
||||
given(this.redisOperations.boundHashOps(getKey(expiredId)))
|
||||
.willReturn(this.boundHashOperations);
|
||||
given(this.boundHashOperations.entries()).willReturn(map());
|
||||
|
||||
String channel = "__keyevent@0__:expired";
|
||||
String body = "spring:session:sessions:expires:" + expiredId;
|
||||
DefaultMessage message = new DefaultMessage(channel.getBytes("UTF-8"), body.getBytes("UTF-8"));
|
||||
|
||||
this.redisRepository.setApplicationEventPublisher(this.publisher);
|
||||
this.redisRepository.onMessage(message, "".getBytes("UTF-8"));
|
||||
|
||||
verify(this.redisOperations).boundHashOps(eq(getKey(expiredId)));
|
||||
verify(this.boundHashOperations).entries();
|
||||
verifyZeroInteractions(this.defaultSerializer);
|
||||
verifyZeroInteractions(this.publisher);
|
||||
verifyZeroInteractions(this.redisOperations);
|
||||
verifyZeroInteractions(this.boundHashOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePrincipalIndex() {
|
||||
PrincipalNameResolver resolver = RedisOperationsSessionRepository.PRINCIPAL_NAME_RESOLVER;
|
||||
@@ -688,9 +827,11 @@ public class RedisOperationsSessionRepositoryTests {
|
||||
session.getLastAccessedTime().toEpochMilli()));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void setRedisFlushModeNull() {
|
||||
this.redisRepository.setRedisFlushMode(null);
|
||||
assertThatThrownBy(() -> this.redisRepository.setRedisFlushMode(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("redisFlushMode cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -713,14 +854,18 @@ public class RedisOperationsSessionRepositoryTests {
|
||||
.boundValueOps(namespace + ":sessions:expires:" + id);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void setRedisKeyNamespaceNullNamespace() {
|
||||
this.redisRepository.setRedisKeyNamespace(null);
|
||||
assertThatThrownBy(() -> this.redisRepository.setRedisKeyNamespace(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("namespace cannot be null or empty");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void setRedisKeyNamespaceEmptyNamespace() {
|
||||
this.redisRepository.setRedisKeyNamespace(" ");
|
||||
assertThatThrownBy(() -> this.redisRepository.setRedisKeyNamespace(" "))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("namespace cannot be null or empty");
|
||||
}
|
||||
|
||||
private String getKey(String id) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,9 +20,7 @@ import java.util.Properties;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@@ -39,6 +37,7 @@ import org.springframework.session.data.redis.config.annotation.SpringSessionRed
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -54,9 +53,6 @@ public class RedisHttpSessionConfigurationTests {
|
||||
|
||||
private static final String CLEANUP_CRON_EXPRESSION = "0 0 * * * *";
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@Before
|
||||
@@ -188,10 +184,10 @@ public class RedisHttpSessionConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void multipleConnectionFactoryRedisConfig() {
|
||||
this.thrown.expect(BeanCreationException.class);
|
||||
this.thrown.expectMessage("expected single matching bean but found 2");
|
||||
|
||||
registerAndRefresh(RedisConfig.class, MultipleConnectionFactoryRedisConfig.class);
|
||||
assertThatThrownBy(() -> registerAndRefresh(RedisConfig.class,
|
||||
MultipleConnectionFactoryRedisConfig.class))
|
||||
.isInstanceOf(BeanCreationException.class)
|
||||
.hasMessageContaining("expected single matching bean but found 2");
|
||||
}
|
||||
|
||||
private void registerAndRefresh(Class<?>... annotatedClasses) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,9 +18,7 @@ package org.springframework.session.data.redis.config.annotation.web.server;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@@ -35,6 +33,7 @@ import org.springframework.session.data.redis.config.annotation.SpringSessionRed
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
@@ -48,9 +47,6 @@ public class RedisWebSessionConfigurationTests {
|
||||
|
||||
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600;
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@Before
|
||||
@@ -179,10 +175,10 @@ public class RedisWebSessionConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void multipleConnectionFactoryRedisConfig() {
|
||||
this.thrown.expect(BeanCreationException.class);
|
||||
this.thrown.expectMessage("expected single matching bean but found 2");
|
||||
|
||||
registerAndRefresh(RedisConfig.class, MultipleConnectionFactoryRedisConfig.class);
|
||||
assertThatThrownBy(() -> registerAndRefresh(RedisConfig.class,
|
||||
MultipleConnectionFactoryRedisConfig.class))
|
||||
.isInstanceOf(BeanCreationException.class)
|
||||
.hasMessageContaining("expected single matching bean but found 2");
|
||||
}
|
||||
|
||||
private void registerAndRefresh(Class<?>... annotatedClasses) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -153,4 +153,18 @@ public abstract class AbstractHazelcastRepositoryITests {
|
||||
|
||||
this.repository.deleteById(toSave.getId());
|
||||
}
|
||||
|
||||
@Test // gh-1076
|
||||
public void attemptToUpdateSessionAfterDelete() {
|
||||
HazelcastSession session = this.repository.createSession();
|
||||
String sessionId = session.getId();
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(sessionId);
|
||||
session.setAttribute("attributeName", "attributeValue");
|
||||
this.repository.deleteById(sessionId);
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(this.repository.findById(sessionId)).isNull();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.session.hazelcast;
|
||||
import com.hazelcast.config.Config;
|
||||
import com.hazelcast.config.MapAttributeConfig;
|
||||
import com.hazelcast.config.MapIndexConfig;
|
||||
import com.hazelcast.config.NetworkConfig;
|
||||
import com.hazelcast.core.Hazelcast;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
|
||||
@@ -46,8 +47,12 @@ public final class HazelcastITestUtils {
|
||||
|
||||
Config config = new Config();
|
||||
|
||||
config.getNetworkConfig()
|
||||
.setPort(port);
|
||||
NetworkConfig networkConfig = config.getNetworkConfig();
|
||||
|
||||
networkConfig.setPort(port);
|
||||
|
||||
networkConfig.getJoin()
|
||||
.getMulticastConfig().setEnabled(false);
|
||||
|
||||
config.getMapConfig(HazelcastSessionRepository.DEFAULT_SESSION_MAP_NAME)
|
||||
.addMapAttributeConfig(attributeConfig)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,6 +52,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* expected after each SessionEvent.
|
||||
*
|
||||
* @author Tommy Ludwig
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
@@ -168,6 +169,24 @@ public class EnableHazelcastHttpSessionEventsTests<S extends Session> {
|
||||
assertThat(this.repository.findById(sessionToUpdate.getId())).isNotNull();
|
||||
}
|
||||
|
||||
@Test // gh-1077
|
||||
public void changeSessionIdNoEventTest() throws InterruptedException {
|
||||
S sessionToSave = this.repository.createSession();
|
||||
sessionToSave.setMaxInactiveInterval(Duration.ofMinutes(30));
|
||||
|
||||
this.repository.save(sessionToSave);
|
||||
|
||||
assertThat(this.registry.receivedEvent(sessionToSave.getId())).isTrue();
|
||||
assertThat(this.registry.<SessionCreatedEvent>getEvent(sessionToSave.getId()))
|
||||
.isInstanceOf(SessionCreatedEvent.class);
|
||||
this.registry.clear();
|
||||
|
||||
sessionToSave.changeSessionId();
|
||||
this.repository.save(sessionToSave);
|
||||
|
||||
assertThat(this.registry.receivedEvent(sessionToSave.getId())).isFalse();
|
||||
}
|
||||
|
||||
@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 hazelcast-config-3.8.xsd">
|
||||
xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.9.xsd">
|
||||
|
||||
<group>
|
||||
<name>spring-session-it-test-idle-time-map-name</name>
|
||||
@@ -14,16 +14,7 @@
|
||||
<ports>0</ports>
|
||||
</outbound-ports>
|
||||
<join>
|
||||
<multicast enabled="false">
|
||||
</multicast>
|
||||
<tcp-ip enabled="true">
|
||||
<interface>127.0.0.1</interface>
|
||||
<member-list>
|
||||
<member>127.0.0.1</member>
|
||||
</member-list>
|
||||
</tcp-ip>
|
||||
<aws enabled="false">
|
||||
</aws>
|
||||
<multicast enabled="false"/>
|
||||
</join>
|
||||
</network>
|
||||
|
||||
@@ -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 hazelcast-config-3.8.xsd">
|
||||
xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.9.xsd">
|
||||
|
||||
<group>
|
||||
<name>spring-session-it-test-map-name</name>
|
||||
@@ -14,16 +14,7 @@
|
||||
<ports>0</ports>
|
||||
</outbound-ports>
|
||||
<join>
|
||||
<multicast enabled="false">
|
||||
</multicast>
|
||||
<tcp-ip enabled="true">
|
||||
<interface>127.0.0.1</interface>
|
||||
<member-list>
|
||||
<member>127.0.0.1</member>
|
||||
</member-list>
|
||||
</tcp-ip>
|
||||
<aws enabled="false">
|
||||
</aws>
|
||||
<multicast enabled="false"/>
|
||||
</join>
|
||||
</network>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -224,20 +224,30 @@ public class HazelcastSessionRepository implements
|
||||
|
||||
@Override
|
||||
public void save(HazelcastSession session) {
|
||||
if (!session.getId().equals(session.originalId)) {
|
||||
this.sessions.remove(session.originalId);
|
||||
session.originalId = session.getId();
|
||||
}
|
||||
if (session.isNew) {
|
||||
this.sessions.set(session.getId(), session.getDelegate(),
|
||||
session.getMaxInactiveInterval().getSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
else if (session.changed) {
|
||||
this.sessions.executeOnKey(session.getId(),
|
||||
new SessionUpdateEntryProcessor(session.getLastAccessedTime(),
|
||||
session.getMaxInactiveInterval(), session.delta));
|
||||
else if (session.sessionIdChanged) {
|
||||
this.sessions.delete(session.originalId);
|
||||
session.originalId = session.getId();
|
||||
this.sessions.set(session.getId(), session.getDelegate(),
|
||||
session.getMaxInactiveInterval().getSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
session.clearFlags();
|
||||
else if (session.hasChanges()) {
|
||||
SessionUpdateEntryProcessor entryProcessor = new SessionUpdateEntryProcessor();
|
||||
if (session.lastAccessedTimeChanged) {
|
||||
entryProcessor.setLastAccessedTime(session.getLastAccessedTime());
|
||||
}
|
||||
if (session.maxInactiveIntervalChanged) {
|
||||
entryProcessor.setMaxInactiveInterval(session.getMaxInactiveInterval());
|
||||
}
|
||||
if (!session.delta.isEmpty()) {
|
||||
entryProcessor.setDelta(session.delta);
|
||||
}
|
||||
this.sessions.executeOnKey(session.getId(), entryProcessor);
|
||||
}
|
||||
session.clearChangeFlags();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -275,10 +285,13 @@ public class HazelcastSessionRepository implements
|
||||
|
||||
@Override
|
||||
public void entryAdded(EntryEvent<String, MapSession> event) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Session created with id: " + event.getValue().getId());
|
||||
MapSession session = event.getValue();
|
||||
if (session.getId().equals(session.getOriginalId())) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Session created with id: " + session.getId());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new SessionCreatedEvent(this, session));
|
||||
}
|
||||
this.eventPublisher.publishEvent(new SessionCreatedEvent(this, event.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -292,11 +305,13 @@ public class HazelcastSessionRepository implements
|
||||
|
||||
@Override
|
||||
public void entryRemoved(EntryEvent<String, MapSession> event) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Session deleted with id: " + event.getOldValue().getId());
|
||||
MapSession session = event.getOldValue();
|
||||
if (session != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Session deleted with id: " + session.getId());
|
||||
}
|
||||
this.eventPublisher.publishEvent(new SessionDeletedEvent(this, session));
|
||||
}
|
||||
this.eventPublisher
|
||||
.publishEvent(new SessionDeletedEvent(this, event.getOldValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,7 +326,11 @@ public class HazelcastSessionRepository implements
|
||||
|
||||
private boolean isNew;
|
||||
|
||||
private boolean changed;
|
||||
private boolean sessionIdChanged;
|
||||
|
||||
private boolean lastAccessedTimeChanged;
|
||||
|
||||
private boolean maxInactiveIntervalChanged;
|
||||
|
||||
private String originalId;
|
||||
|
||||
@@ -341,7 +360,7 @@ public class HazelcastSessionRepository implements
|
||||
@Override
|
||||
public void setLastAccessedTime(Instant lastAccessedTime) {
|
||||
this.delegate.setLastAccessedTime(lastAccessedTime);
|
||||
this.changed = true;
|
||||
this.lastAccessedTimeChanged = true;
|
||||
flushImmediateIfNecessary();
|
||||
}
|
||||
|
||||
@@ -362,8 +381,9 @@ public class HazelcastSessionRepository implements
|
||||
|
||||
@Override
|
||||
public String changeSessionId() {
|
||||
this.isNew = true;
|
||||
return this.delegate.changeSessionId();
|
||||
String newSessionId = this.delegate.changeSessionId();
|
||||
this.sessionIdChanged = true;
|
||||
return newSessionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -374,7 +394,7 @@ public class HazelcastSessionRepository implements
|
||||
@Override
|
||||
public void setMaxInactiveInterval(Duration interval) {
|
||||
this.delegate.setMaxInactiveInterval(interval);
|
||||
this.changed = true;
|
||||
this.maxInactiveIntervalChanged = true;
|
||||
flushImmediateIfNecessary();
|
||||
}
|
||||
|
||||
@@ -397,7 +417,6 @@ public class HazelcastSessionRepository implements
|
||||
public void setAttribute(String attributeName, Object attributeValue) {
|
||||
this.delegate.setAttribute(attributeName, attributeValue);
|
||||
this.delta.put(attributeName, attributeValue);
|
||||
this.changed = true;
|
||||
flushImmediateIfNecessary();
|
||||
}
|
||||
|
||||
@@ -405,7 +424,6 @@ public class HazelcastSessionRepository implements
|
||||
public void removeAttribute(String attributeName) {
|
||||
this.delegate.removeAttribute(attributeName);
|
||||
this.delta.put(attributeName, null);
|
||||
this.changed = true;
|
||||
flushImmediateIfNecessary();
|
||||
}
|
||||
|
||||
@@ -413,9 +431,16 @@ public class HazelcastSessionRepository implements
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
void clearFlags() {
|
||||
boolean hasChanges() {
|
||||
return (this.lastAccessedTimeChanged || this.maxInactiveIntervalChanged
|
||||
|| !this.delta.isEmpty());
|
||||
}
|
||||
|
||||
void clearChangeFlags() {
|
||||
this.isNew = false;
|
||||
this.changed = false;
|
||||
this.lastAccessedTimeChanged = false;
|
||||
this.sessionIdChanged = false;
|
||||
this.maxInactiveIntervalChanged = false;
|
||||
this.delta.clear();
|
||||
}
|
||||
|
||||
@@ -436,34 +461,48 @@ public class HazelcastSessionRepository implements
|
||||
private static final class SessionUpdateEntryProcessor
|
||||
extends AbstractEntryProcessor<String, MapSession> {
|
||||
|
||||
private final Instant lastAccessedTime;
|
||||
private Instant lastAccessedTime;
|
||||
|
||||
private final Duration maxInactiveInterval;
|
||||
private Duration maxInactiveInterval;
|
||||
|
||||
private final Map<String, Object> delta;
|
||||
|
||||
SessionUpdateEntryProcessor(Instant lastAccessedTime,
|
||||
Duration maxInactiveInterval, Map<String, Object> delta) {
|
||||
this.lastAccessedTime = lastAccessedTime;
|
||||
this.maxInactiveInterval = maxInactiveInterval;
|
||||
this.delta = delta;
|
||||
}
|
||||
private Map<String, Object> delta;
|
||||
|
||||
@Override
|
||||
public Object process(Map.Entry<String, MapSession> entry) {
|
||||
MapSession value = entry.getValue();
|
||||
value.setLastAccessedTime(this.lastAccessedTime);
|
||||
value.setMaxInactiveInterval(this.maxInactiveInterval);
|
||||
for (final Map.Entry<String, Object> attribute : this.delta.entrySet()) {
|
||||
if (attribute.getValue() != null) {
|
||||
value.setAttribute(attribute.getKey(), attribute.getValue());
|
||||
}
|
||||
else {
|
||||
value.removeAttribute(attribute.getKey());
|
||||
if (value == null) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
if (this.lastAccessedTime != null) {
|
||||
value.setLastAccessedTime(this.lastAccessedTime);
|
||||
}
|
||||
if (this.maxInactiveInterval != null) {
|
||||
value.setMaxInactiveInterval(this.maxInactiveInterval);
|
||||
}
|
||||
if (this.delta != null) {
|
||||
for (final Map.Entry<String, Object> attribute : this.delta.entrySet()) {
|
||||
if (attribute.getValue() != null) {
|
||||
value.setAttribute(attribute.getKey(), attribute.getValue());
|
||||
}
|
||||
else {
|
||||
value.removeAttribute(attribute.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
entry.setValue(value);
|
||||
return value;
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
public void setLastAccessedTime(Instant lastAccessedTime) {
|
||||
this.lastAccessedTime = lastAccessedTime;
|
||||
}
|
||||
|
||||
public void setMaxInactiveInterval(Duration maxInactiveInterval) {
|
||||
this.maxInactiveInterval = maxInactiveInterval;
|
||||
}
|
||||
|
||||
public void setDelta(Map<String, Object> delta) {
|
||||
this.delta = delta;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,12 +29,7 @@ import com.hazelcast.map.EntryProcessor;
|
||||
import com.hazelcast.map.listener.MapListener;
|
||||
import com.hazelcast.query.impl.predicates.EqualPredicate;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -44,12 +39,14 @@ import org.springframework.session.MapSession;
|
||||
import org.springframework.session.hazelcast.HazelcastSessionRepository.HazelcastSession;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
@@ -60,19 +57,14 @@ import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
* @author Vedran Pavic
|
||||
* @author Aleksandar Stojsavljevic
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class HazelcastSessionRepositoryTests {
|
||||
|
||||
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
private HazelcastInstance hazelcastInstance = mock(HazelcastInstance.class);
|
||||
|
||||
@Mock
|
||||
private HazelcastInstance hazelcastInstance;
|
||||
|
||||
@Mock
|
||||
private IMap<String, MapSession> sessions;
|
||||
@SuppressWarnings("unchecked")
|
||||
private IMap<String, MapSession> sessions = mock(IMap.class);
|
||||
|
||||
private HazelcastSessionRepository repository;
|
||||
|
||||
@@ -86,14 +78,13 @@ public class HazelcastSessionRepositoryTests {
|
||||
|
||||
@Test
|
||||
public void constructorNullHazelcastInstance() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("HazelcastInstance must not be null");
|
||||
|
||||
new HazelcastSessionRepository(null);
|
||||
assertThatThrownBy(() -> new HazelcastSessionRepository(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("HazelcastInstance must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSessionDefaultMaxInactiveInterval() throws Exception {
|
||||
public void createSessionDefaultMaxInactiveInterval() {
|
||||
verify(this.sessions, times(1)).addEntryListener(any(MapListener.class),
|
||||
anyBoolean());
|
||||
|
||||
@@ -105,7 +96,7 @@ public class HazelcastSessionRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSessionCustomMaxInactiveInterval() throws Exception {
|
||||
public void createSessionCustomMaxInactiveInterval() {
|
||||
verify(this.sessions, times(1)).addEntryListener(any(MapListener.class),
|
||||
anyBoolean());
|
||||
|
||||
|
||||
@@ -19,9 +19,7 @@ package org.springframework.session.hazelcast.config.annotation.web.http;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.hazelcast.core.IMap;
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@@ -34,6 +32,7 @@ import org.springframework.session.hazelcast.config.annotation.SpringSessionHaze
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -52,9 +51,6 @@ public class HazelcastHttpSessionConfigurationTests {
|
||||
|
||||
private static final HazelcastFlushMode HAZELCAST_FLUSH_MODE = HazelcastFlushMode.IMMEDIATE;
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
||||
@After
|
||||
@@ -66,10 +62,10 @@ public class HazelcastHttpSessionConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void noHazelcastInstanceConfiguration() {
|
||||
this.thrown.expect(BeanCreationException.class);
|
||||
this.thrown.expectMessage("HazelcastInstance");
|
||||
|
||||
registerAndRefresh(NoHazelcastInstanceConfiguration.class);
|
||||
assertThatThrownBy(
|
||||
() -> registerAndRefresh(NoHazelcastInstanceConfiguration.class))
|
||||
.isInstanceOf(BeanCreationException.class)
|
||||
.hasMessageContaining("HazelcastInstance");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -210,10 +206,10 @@ public class HazelcastHttpSessionConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void multipleHazelcastInstanceConfiguration() {
|
||||
this.thrown.expect(BeanCreationException.class);
|
||||
this.thrown.expectMessage("expected single matching bean but found 2");
|
||||
|
||||
registerAndRefresh(MultipleHazelcastInstanceConfiguration.class);
|
||||
assertThatThrownBy(
|
||||
() -> registerAndRefresh(MultipleHazelcastInstanceConfiguration.class))
|
||||
.isInstanceOf(BeanCreationException.class)
|
||||
.hasMessageContaining("expected single matching bean but found 2");
|
||||
}
|
||||
|
||||
private void registerAndRefresh(Class<?>... annotatedClasses) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,7 +37,6 @@ import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.session.FindByIndexNameSessionRepository;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.jdbc.config.annotation.web.http.EnableJdbcHttpSession;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -82,8 +81,11 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
.createSession();
|
||||
|
||||
this.repository.save(toSave);
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.findById(toSave.getId());
|
||||
|
||||
assertThat(this.repository.findById(toSave.getId())).isNotNull();
|
||||
assertThat(session).isNotNull();
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -104,9 +106,11 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
this.repository.save(toSave);
|
||||
|
||||
Session session = this.repository.findById(toSave.getId());
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.findById(toSave.getId());
|
||||
|
||||
assertThat(session.getId()).isEqualTo(toSave.getId());
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
assertThat(session.getAttributeNames()).isEqualTo(toSave.getAttributeNames());
|
||||
assertThat(session.<String>getAttribute(expectedAttributeName))
|
||||
.isEqualTo(toSave.getAttribute(expectedAttributeName));
|
||||
@@ -139,7 +143,9 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
this.repository.save(toSave);
|
||||
toSave = this.repository.findById(toSave.getId());
|
||||
|
||||
Session session = this.repository.findById(toSave.getId());
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.findById(toSave.getId());
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
assertThat(session.getAttributeNames().size()).isEqualTo(2);
|
||||
assertThat(session.<String>getAttribute("a")).isEqualTo("b");
|
||||
assertThat(session.<String>getAttribute("1")).isEqualTo("2");
|
||||
@@ -160,9 +166,11 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
toSave.setLastAccessedTime(lastAccessedTime);
|
||||
this.repository.save(toSave);
|
||||
|
||||
Session session = this.repository.findById(toSave.getId());
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.findById(toSave.getId());
|
||||
|
||||
assertThat(session).isNotNull();
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
assertThat(session.isExpired()).isFalse();
|
||||
assertThat(session.getLastAccessedTime()).isEqualTo(lastAccessedTime);
|
||||
}
|
||||
@@ -229,6 +237,10 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
findByPrincipalName.values().forEach(session -> {
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -251,6 +263,10 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
findByPrincipalName.values().forEach(session -> {
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -293,6 +309,10 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
findByPrincipalName.values().forEach(session -> {
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -340,6 +360,10 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
findByPrincipalName.values().forEach(session -> {
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -399,6 +423,10 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
findByPrincipalName.values().forEach(session -> {
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -420,6 +448,10 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
findByPrincipalName.values().forEach(session -> {
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -459,6 +491,10 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
findByPrincipalName.values().forEach(session -> {
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -503,6 +539,10 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
assertThat(findByPrincipalName).hasSize(1);
|
||||
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
|
||||
findByPrincipalName.values().forEach(session -> {
|
||||
assertThat(session.isChanged()).isFalse();
|
||||
assertThat(session.getDelta()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -585,6 +625,8 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession findByChangeSessionId = this.repository.findById(changeSessionId);
|
||||
|
||||
assertThat(findByChangeSessionId.isChanged()).isFalse();
|
||||
assertThat(findByChangeSessionId.getDelta()).isEmpty();
|
||||
assertThat(findByChangeSessionId.<String>getAttribute(attrName)).isEqualTo(attrValue);
|
||||
}
|
||||
|
||||
@@ -627,6 +669,8 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
JdbcOperationsSessionRepository.JdbcSession findByChangeSessionId = this.repository.findById(changeSessionId);
|
||||
|
||||
assertThat(findByChangeSessionId.isChanged()).isFalse();
|
||||
assertThat(findByChangeSessionId.getDelta()).isEmpty();
|
||||
assertThat(findByChangeSessionId.<String>getAttribute(attrName)).isEqualTo(attrValue);
|
||||
}
|
||||
|
||||
@@ -645,6 +689,60 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
|
||||
assertThat(this.repository.findById(originalId)).isNull();
|
||||
}
|
||||
|
||||
@Test // gh-1070
|
||||
public void saveUpdatedAddAndModifyAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
session.setAttribute("testName", "testValue1");
|
||||
session.setAttribute("testName", "testValue2");
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
|
||||
assertThat(session.<String>getAttribute("testName")).isEqualTo("testValue2");
|
||||
}
|
||||
|
||||
@Test // gh-1070
|
||||
public void saveUpdatedAddAndRemoveAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
session.setAttribute("testName", "testValue");
|
||||
session.removeAttribute("testName");
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
|
||||
assertThat(session.<String>getAttribute("testName")).isNull();
|
||||
}
|
||||
|
||||
@Test // gh-1070
|
||||
public void saveUpdatedModifyAndRemoveAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
session.setAttribute("testName", "testValue1");
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
session.setAttribute("testName", "testValue2");
|
||||
session.removeAttribute("testName");
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
|
||||
assertThat(session.<String>getAttribute("testName")).isNull();
|
||||
}
|
||||
|
||||
@Test // gh-1070
|
||||
public void saveUpdatedRemoveAndAddAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
|
||||
session.setAttribute("testName", "testValue1");
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
session.removeAttribute("testName");
|
||||
session.setAttribute("testName", "testValue2");
|
||||
this.repository.save(session);
|
||||
session = this.repository.findById(session.getId());
|
||||
|
||||
assertThat(session.<String>getAttribute("testName")).isEqualTo("testValue2");
|
||||
}
|
||||
|
||||
private String getSecurityName() {
|
||||
return this.context.getAuthentication().getName();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ import java.sql.SQLException;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mariadb.jdbc.MariaDbDataSource;
|
||||
import org.testcontainers.containers.MariaDBContainer;
|
||||
@@ -43,23 +44,29 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
public class MariaDB10JdbcOperationsSessionRepositoryITests
|
||||
public class MariaDb10JdbcOperationsSessionRepositoryITests
|
||||
extends AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "mariadb:10.2.13";
|
||||
private static MariaDBContainer container = new MariaDb10Container();
|
||||
|
||||
@ClassRule
|
||||
public static MariaDBContainer mariaDBContainer = new MariaDBContainer(DOCKER_IMAGE);
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
container.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() {
|
||||
container.stop();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseConfig {
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() throws SQLException {
|
||||
MariaDbDataSource dataSource = new MariaDbDataSource(
|
||||
mariaDBContainer.getJdbcUrl());
|
||||
dataSource.setUserName(mariaDBContainer.getUsername());
|
||||
dataSource.setPassword(mariaDBContainer.getPassword());
|
||||
MariaDbDataSource dataSource = new MariaDbDataSource(container.getJdbcUrl());
|
||||
dataSource.setUserName(container.getUsername());
|
||||
dataSource.setPassword(container.getPassword());
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@@ -76,4 +83,19 @@ public class MariaDB10JdbcOperationsSessionRepositoryITests
|
||||
|
||||
}
|
||||
|
||||
private static class MariaDb10Container extends MariaDBContainer<MariaDb10Container> {
|
||||
|
||||
MariaDb10Container() {
|
||||
super("mariadb:10.3.7");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
setCommand("mysqld", "--character-set-server=utf8mb4",
|
||||
"--collation-server=utf8mb4_unicode_ci");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,8 @@ import java.sql.SQLException;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mariadb.jdbc.MariaDbDataSource;
|
||||
import org.testcontainers.containers.MariaDBContainer;
|
||||
@@ -43,23 +44,29 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
public class MariaDB5JdbcOperationsSessionRepositoryITests
|
||||
public class MariaDb5JdbcOperationsSessionRepositoryITests
|
||||
extends AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "mariadb:5.5.59";
|
||||
private static MariaDBContainer container = new MariaDb5Container();
|
||||
|
||||
@ClassRule
|
||||
public static MariaDBContainer mariaDBContainer = new MariaDBContainer(DOCKER_IMAGE);
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
container.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() {
|
||||
container.stop();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseConfig {
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() throws SQLException {
|
||||
MariaDbDataSource dataSource = new MariaDbDataSource(
|
||||
mariaDBContainer.getJdbcUrl());
|
||||
dataSource.setUserName(mariaDBContainer.getUsername());
|
||||
dataSource.setPassword(mariaDBContainer.getPassword());
|
||||
MariaDbDataSource dataSource = new MariaDbDataSource(container.getJdbcUrl());
|
||||
dataSource.setUserName(container.getUsername());
|
||||
dataSource.setPassword(container.getPassword());
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@@ -76,4 +83,20 @@ public class MariaDB5JdbcOperationsSessionRepositoryITests
|
||||
|
||||
}
|
||||
|
||||
private static class MariaDb5Container extends MariaDBContainer<MariaDb5Container> {
|
||||
|
||||
MariaDb5Container() {
|
||||
super("mariadb:5.5.60");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
setCommand("mysqld", "--character-set-server=utf8mb4",
|
||||
"--collation-server=utf8mb4_unicode_ci", "--innodb_large_prefix",
|
||||
"--innodb_file_format=barracuda", "--innodb-file-per-table");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,8 +18,10 @@ package org.springframework.session.jdbc;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
|
||||
import org.junit.ClassRule;
|
||||
import com.mysql.cj.jdbc.Driver;
|
||||
import com.mysql.cj.jdbc.MysqlDataSource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.testcontainers.containers.MySQLContainer;
|
||||
|
||||
@@ -40,13 +42,20 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
public class MySQL5JdbcOperationsSessionRepositoryITests
|
||||
public class MySql5JdbcOperationsSessionRepositoryITests
|
||||
extends AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "mysql:5.7.21";
|
||||
private static MySQLContainer container = new MySql5Container();
|
||||
|
||||
@ClassRule
|
||||
public static MySQLContainer mySQLContainer = new MySQLContainer(DOCKER_IMAGE);
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
container.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() {
|
||||
container.stop();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseConfig {
|
||||
@@ -54,9 +63,9 @@ public class MySQL5JdbcOperationsSessionRepositoryITests
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
MysqlDataSource dataSource = new MysqlDataSource();
|
||||
dataSource.setUrl(mySQLContainer.getJdbcUrl());
|
||||
dataSource.setUser(mySQLContainer.getUsername());
|
||||
dataSource.setPassword(mySQLContainer.getPassword());
|
||||
dataSource.setUrl(container.getJdbcUrl());
|
||||
dataSource.setUser(container.getUsername());
|
||||
dataSource.setPassword(container.getPassword());
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@@ -73,4 +82,24 @@ public class MySQL5JdbcOperationsSessionRepositoryITests
|
||||
|
||||
}
|
||||
|
||||
private static class MySql5Container extends MySQLContainer<MySql5Container> {
|
||||
|
||||
MySql5Container() {
|
||||
super("mysql:5.7.22");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
setCommand("mysqld", "--character-set-server=utf8mb4",
|
||||
"--collation-server=utf8mb4_unicode_ci");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDriverClassName() {
|
||||
return Driver.class.getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.session.jdbc;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import com.mysql.cj.jdbc.Driver;
|
||||
import com.mysql.cj.jdbc.MysqlDataSource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.testcontainers.containers.MySQLContainer;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
|
||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link JdbcOperationsSessionRepository} using MySQL 8.x database.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
public class MySql8JdbcOperationsSessionRepositoryITests
|
||||
extends AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
private static MySQLContainer container = new MySql8Container();
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
container.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() {
|
||||
container.stop();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseConfig {
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
MysqlDataSource dataSource = new MysqlDataSource();
|
||||
dataSource.setUrl(container.getJdbcUrl());
|
||||
dataSource.setUser(container.getUsername());
|
||||
dataSource.setPassword(container.getPassword());
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataSourceInitializer initializer(DataSource dataSource,
|
||||
ResourceLoader resourceLoader) {
|
||||
DataSourceInitializer initializer = new DataSourceInitializer();
|
||||
initializer.setDataSource(dataSource);
|
||||
initializer.setDatabasePopulator(
|
||||
new ResourceDatabasePopulator(resourceLoader.getResource(
|
||||
"classpath:org/springframework/session/jdbc/schema-mysql.sql")));
|
||||
return initializer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class MySql8Container extends MySQLContainer<MySql8Container> {
|
||||
|
||||
MySql8Container() {
|
||||
super("mysql:8.0.11");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
setCommand("mysqld", "--default-authentication-plugin=mysql_native_password");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDriverClassName() {
|
||||
return Driver.class.getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,8 @@ package org.springframework.session.jdbc;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.postgresql.ds.PGSimpleDataSource;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
@@ -41,14 +42,20 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
public class PostgreSQL10JdbcOperationsSessionRepositoryITests
|
||||
public class PostgreSql10JdbcOperationsSessionRepositoryITests
|
||||
extends AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "postgres:10.2";
|
||||
private static PostgreSQLContainer container = new PostgreSql10Container();
|
||||
|
||||
@ClassRule
|
||||
public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer(
|
||||
DOCKER_IMAGE);
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
container.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() {
|
||||
container.stop();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseConfig {
|
||||
@@ -56,9 +63,9 @@ public class PostgreSQL10JdbcOperationsSessionRepositoryITests
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
PGSimpleDataSource dataSource = new PGSimpleDataSource();
|
||||
dataSource.setUrl(postgreSQLContainer.getJdbcUrl());
|
||||
dataSource.setUser(postgreSQLContainer.getUsername());
|
||||
dataSource.setPassword(postgreSQLContainer.getPassword());
|
||||
dataSource.setUrl(container.getJdbcUrl());
|
||||
dataSource.setUser(container.getUsername());
|
||||
dataSource.setPassword(container.getPassword());
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@@ -75,4 +82,13 @@ public class PostgreSQL10JdbcOperationsSessionRepositoryITests
|
||||
|
||||
}
|
||||
|
||||
private static class PostgreSql10Container
|
||||
extends PostgreSQLContainer<PostgreSql10Container> {
|
||||
|
||||
PostgreSql10Container() {
|
||||
super("postgres:10.4");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,8 @@ package org.springframework.session.jdbc;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.postgresql.ds.PGSimpleDataSource;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
@@ -41,14 +42,20 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
public class PostgreSQL9JdbcOperationsSessionRepositoryITests
|
||||
public class PostgreSql9JdbcOperationsSessionRepositoryITests
|
||||
extends AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "postgres:9.6.7";
|
||||
private static PostgreSQLContainer container = new PostgreSql9Container();
|
||||
|
||||
@ClassRule
|
||||
public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer(
|
||||
DOCKER_IMAGE);
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
container.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() {
|
||||
container.stop();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseConfig {
|
||||
@@ -56,9 +63,9 @@ public class PostgreSQL9JdbcOperationsSessionRepositoryITests
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
PGSimpleDataSource dataSource = new PGSimpleDataSource();
|
||||
dataSource.setUrl(postgreSQLContainer.getJdbcUrl());
|
||||
dataSource.setUser(postgreSQLContainer.getUsername());
|
||||
dataSource.setPassword(postgreSQLContainer.getPassword());
|
||||
dataSource.setUrl(container.getJdbcUrl());
|
||||
dataSource.setUser(container.getUsername());
|
||||
dataSource.setPassword(container.getPassword());
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@@ -75,4 +82,13 @@ public class PostgreSQL9JdbcOperationsSessionRepositoryITests
|
||||
|
||||
}
|
||||
|
||||
private static class PostgreSql9Container
|
||||
extends PostgreSQLContainer<PostgreSql9Container> {
|
||||
|
||||
PostgreSql9Container() {
|
||||
super("postgres:9.6.9");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,7 +19,8 @@ package org.springframework.session.jdbc;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.testcontainers.containers.MSSQLServerContainer;
|
||||
@@ -43,13 +44,20 @@ import org.springframework.test.context.web.WebAppConfiguration;
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
public class SQLServerJdbcOperationsSessionRepositoryITests
|
||||
public class SqlServerJdbcOperationsSessionRepositoryITests
|
||||
extends AbstractJdbcOperationsSessionRepositoryITests {
|
||||
|
||||
private static final String DOCKER_IMAGE = "microsoft/mssql-server-linux:2017-CU3";
|
||||
private static MSSQLServerContainer container = new SqlServer2007Container();
|
||||
|
||||
@ClassRule
|
||||
public static MSSQLServerContainer container = new MSSQLServerContainer(DOCKER_IMAGE);
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
container.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() {
|
||||
container.stop();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config extends BaseConfig {
|
||||
@@ -76,4 +84,18 @@ public class SQLServerJdbcOperationsSessionRepositoryITests
|
||||
|
||||
}
|
||||
|
||||
private static class SqlServer2007Container
|
||||
extends MSSQLServerContainer<SqlServer2007Container> {
|
||||
|
||||
SqlServer2007Container() {
|
||||
super("microsoft/mssql-server-linux:2017-CU7");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getStartupTimeoutSeconds() {
|
||||
return 240;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -382,24 +383,7 @@ public class JdbcOperationsSessionRepository implements
|
||||
});
|
||||
if (!session.getAttributeNames().isEmpty()) {
|
||||
final List<String> attributeNames = new ArrayList<>(session.getAttributeNames());
|
||||
JdbcOperationsSessionRepository.this.jdbcOperations.batchUpdate(
|
||||
JdbcOperationsSessionRepository.this.createSessionAttributeQuery,
|
||||
new BatchPreparedStatementSetter() {
|
||||
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
String attributeName = attributeNames.get(i);
|
||||
ps.setString(1, session.primaryKey);
|
||||
ps.setString(2, attributeName);
|
||||
serialize(ps, 3, session.getAttribute(attributeName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return attributeNames.size();
|
||||
}
|
||||
|
||||
});
|
||||
insertSessionAttributes(session, attributeNames);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,37 +406,21 @@ public class JdbcOperationsSessionRepository implements
|
||||
ps.setString(6, session.primaryKey);
|
||||
});
|
||||
}
|
||||
Map<String, Object> delta = session.getDelta();
|
||||
if (!delta.isEmpty()) {
|
||||
for (final Map.Entry<String, Object> entry : delta.entrySet()) {
|
||||
if (entry.getValue() == null) {
|
||||
JdbcOperationsSessionRepository.this.jdbcOperations.update(
|
||||
JdbcOperationsSessionRepository.this.deleteSessionAttributeQuery,
|
||||
ps -> {
|
||||
ps.setString(1, session.primaryKey);
|
||||
ps.setString(2, entry.getKey());
|
||||
});
|
||||
}
|
||||
else {
|
||||
int updatedCount = JdbcOperationsSessionRepository.this.jdbcOperations.update(
|
||||
JdbcOperationsSessionRepository.this.updateSessionAttributeQuery,
|
||||
ps -> {
|
||||
serialize(ps, 1, entry.getValue());
|
||||
ps.setString(2, session.primaryKey);
|
||||
ps.setString(3, entry.getKey());
|
||||
});
|
||||
if (updatedCount == 0) {
|
||||
JdbcOperationsSessionRepository.this.jdbcOperations.update(
|
||||
JdbcOperationsSessionRepository.this.createSessionAttributeQuery,
|
||||
ps -> {
|
||||
ps.setString(1, session.primaryKey);
|
||||
ps.setString(2, entry.getKey());
|
||||
serialize(ps, 3, entry.getValue());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
List<String> addedAttributeNames = session.delta.entrySet().stream()
|
||||
.filter(entry -> entry.getValue() == DeltaValue.ADDED)
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
insertSessionAttributes(session, addedAttributeNames);
|
||||
List<String> updatedAttributeNames = session.delta.entrySet().stream()
|
||||
.filter(entry -> entry.getValue() == DeltaValue.UPDATED)
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
updateSessionAttributes(session, updatedAttributeNames);
|
||||
List<String> removedAttributeNames = session.delta.entrySet().stream()
|
||||
.filter(entry -> entry.getValue() == DeltaValue.REMOVED)
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
deleteSessionAttributes(session, removedAttributeNames);
|
||||
}
|
||||
|
||||
});
|
||||
@@ -521,6 +489,100 @@ public class JdbcOperationsSessionRepository implements
|
||||
return sessionMap;
|
||||
}
|
||||
|
||||
private void insertSessionAttributes(JdbcSession session, List<String> attributeNames) {
|
||||
if (attributeNames == null || attributeNames.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (attributeNames.size() > 1) {
|
||||
this.jdbcOperations.batchUpdate(this.createSessionAttributeQuery, new BatchPreparedStatementSetter() {
|
||||
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
String attributeName = attributeNames.get(i);
|
||||
ps.setString(1, session.primaryKey);
|
||||
ps.setString(2, attributeName);
|
||||
serialize(ps, 3, session.getAttribute(attributeName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return attributeNames.size();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.jdbcOperations.update(this.createSessionAttributeQuery, ps -> {
|
||||
String attributeName = attributeNames.get(0);
|
||||
ps.setString(1, session.primaryKey);
|
||||
ps.setString(2, attributeName);
|
||||
serialize(ps, 3, session.getAttribute(attributeName));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSessionAttributes(JdbcSession session, List<String> attributeNames) {
|
||||
if (attributeNames == null || attributeNames.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (attributeNames.size() > 1) {
|
||||
this.jdbcOperations.batchUpdate(this.updateSessionAttributeQuery, new BatchPreparedStatementSetter() {
|
||||
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
String attributeName = attributeNames.get(i);
|
||||
serialize(ps, 1, session.getAttribute(attributeName));
|
||||
ps.setString(2, session.primaryKey);
|
||||
ps.setString(3, attributeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return attributeNames.size();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.jdbcOperations.update(this.updateSessionAttributeQuery, ps -> {
|
||||
String attributeName = attributeNames.get(0);
|
||||
serialize(ps, 1, session.getAttribute(attributeName));
|
||||
ps.setString(2, session.primaryKey);
|
||||
ps.setString(3, attributeName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteSessionAttributes(JdbcSession session, List<String> attributeNames) {
|
||||
if (attributeNames == null || attributeNames.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (attributeNames.size() > 1) {
|
||||
this.jdbcOperations.batchUpdate(this.deleteSessionAttributeQuery, new BatchPreparedStatementSetter() {
|
||||
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
String attributeName = attributeNames.get(i);
|
||||
ps.setString(1, session.primaryKey);
|
||||
ps.setString(2, attributeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return attributeNames.size();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.jdbcOperations.update(this.deleteSessionAttributeQuery, ps -> {
|
||||
String attributeName = attributeNames.get(0);
|
||||
ps.setString(1, session.primaryKey);
|
||||
ps.setString(2, attributeName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanUpExpiredSessions() {
|
||||
Integer deletedCount = this.transactionOperations.execute(transactionStatus ->
|
||||
JdbcOperationsSessionRepository.this.jdbcOperations.update(
|
||||
@@ -585,6 +647,12 @@ public class JdbcOperationsSessionRepository implements
|
||||
TypeDescriptor.valueOf(Object.class));
|
||||
}
|
||||
|
||||
private enum DeltaValue {
|
||||
|
||||
ADDED, UPDATED, REMOVED
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link Session} to use for {@link JdbcOperationsSessionRepository}.
|
||||
*
|
||||
@@ -600,7 +668,7 @@ public class JdbcOperationsSessionRepository implements
|
||||
|
||||
private boolean changed;
|
||||
|
||||
private Map<String, Object> delta = new HashMap<>();
|
||||
private Map<String, DeltaValue> delta = new HashMap<>();
|
||||
|
||||
JdbcSession() {
|
||||
this.delegate = new MapSession();
|
||||
@@ -623,7 +691,7 @@ public class JdbcOperationsSessionRepository implements
|
||||
return this.changed;
|
||||
}
|
||||
|
||||
Map<String, Object> getDelta() {
|
||||
Map<String, DeltaValue> getDelta() {
|
||||
return this.delta;
|
||||
}
|
||||
|
||||
@@ -664,8 +732,32 @@ public class JdbcOperationsSessionRepository implements
|
||||
|
||||
@Override
|
||||
public void setAttribute(String attributeName, Object attributeValue) {
|
||||
boolean attributeExists = (this.delegate.getAttribute(attributeName) != null);
|
||||
boolean attributeRemoved = (attributeValue == null);
|
||||
if (!attributeExists && attributeRemoved) {
|
||||
return;
|
||||
}
|
||||
if (attributeExists) {
|
||||
if (attributeRemoved) {
|
||||
this.delta.merge(attributeName, DeltaValue.REMOVED,
|
||||
(oldDeltaValue, deltaValue) -> oldDeltaValue == DeltaValue.ADDED
|
||||
? null
|
||||
: deltaValue);
|
||||
}
|
||||
else {
|
||||
this.delta.merge(attributeName, DeltaValue.UPDATED,
|
||||
(oldDeltaValue, deltaValue) -> oldDeltaValue == DeltaValue.ADDED
|
||||
? oldDeltaValue
|
||||
: deltaValue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.delta.merge(attributeName, DeltaValue.ADDED,
|
||||
(oldDeltaValue, deltaValue) -> oldDeltaValue == DeltaValue.ADDED
|
||||
? oldDeltaValue
|
||||
: DeltaValue.UPDATED);
|
||||
}
|
||||
this.delegate.setAttribute(attributeName, attributeValue);
|
||||
this.delta.put(attributeName, attributeValue);
|
||||
if (PRINCIPAL_NAME_INDEX_NAME.equals(attributeName) ||
|
||||
SPRING_SECURITY_CONTEXT.equals(attributeName)) {
|
||||
this.changed = true;
|
||||
@@ -674,8 +766,7 @@ public class JdbcOperationsSessionRepository implements
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String attributeName) {
|
||||
this.delegate.removeAttribute(attributeName);
|
||||
this.delta.put(attributeName, null);
|
||||
setAttribute(attributeName, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -758,7 +849,7 @@ public class JdbcOperationsSessionRepository implements
|
||||
}
|
||||
String attributeName = rs.getString("ATTRIBUTE_NAME");
|
||||
if (attributeName != null) {
|
||||
session.setAttribute(attributeName, deserialize(rs, "ATTRIBUTE_BYTES"));
|
||||
session.delegate.setAttribute(attributeName, deserialize(rs, "ATTRIBUTE_BYTES"));
|
||||
}
|
||||
sessions.add(session);
|
||||
}
|
||||
|
||||
@@ -20,5 +20,3 @@ CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
|
||||
|
||||
@@ -20,5 +20,3 @@ CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
|
||||
|
||||
@@ -20,5 +20,3 @@ CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
|
||||
|
||||
@@ -20,5 +20,3 @@ CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
|
||||
|
||||
@@ -7,7 +7,7 @@ CREATE TABLE SPRING_SESSION (
|
||||
EXPIRY_TIME BIGINT NOT NULL,
|
||||
PRINCIPAL_NAME VARCHAR(100),
|
||||
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
|
||||
) ENGINE=InnoDB;
|
||||
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
|
||||
|
||||
CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
|
||||
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME);
|
||||
@@ -19,6 +19,4 @@ CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
ATTRIBUTE_BYTES BLOB NOT NULL,
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
|
||||
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
|
||||
|
||||
@@ -20,5 +20,3 @@ CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
|
||||
|
||||
@@ -20,5 +20,3 @@ CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
|
||||
|
||||
@@ -20,5 +20,3 @@ CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
|
||||
|
||||
@@ -20,5 +20,3 @@ CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
|
||||
|
||||
@@ -20,5 +20,3 @@ CREATE TABLE SPRING_SESSION_ATTRIBUTES (
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
|
||||
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
|
||||
) LOCK DATAROWS;
|
||||
|
||||
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,13 +24,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
@@ -46,241 +41,213 @@ import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.AdditionalMatchers.and;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.contains;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.ArgumentMatchers.startsWith;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
/**
|
||||
* Tests for {@link JdbcOperationsSessionRepository}.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @author Craig Andrews
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
private JdbcOperations jdbcOperations = mock(JdbcOperations.class);
|
||||
|
||||
@Mock
|
||||
private JdbcOperations jdbcOperations;
|
||||
|
||||
@Mock
|
||||
private PlatformTransactionManager transactionManager;
|
||||
private PlatformTransactionManager transactionManager = mock(PlatformTransactionManager.class);
|
||||
|
||||
private JdbcOperationsSessionRepository repository;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.repository = new JdbcOperationsSessionRepository(
|
||||
this.jdbcOperations, this.transactionManager);
|
||||
this.repository = new JdbcOperationsSessionRepository(this.jdbcOperations, this.transactionManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorNullJdbcOperations() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("JdbcOperations must not be null");
|
||||
|
||||
new JdbcOperationsSessionRepository((JdbcOperations) null, this.transactionManager);
|
||||
assertThatThrownBy(
|
||||
() -> new JdbcOperationsSessionRepository(null, this.transactionManager))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("JdbcOperations must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorNullTransactionManager() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Property 'transactionManager' is required");
|
||||
|
||||
new JdbcOperationsSessionRepository(this.jdbcOperations, null);
|
||||
assertThatThrownBy(
|
||||
() -> new JdbcOperationsSessionRepository(this.jdbcOperations, null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Property 'transactionManager' is required");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setTableNameNull() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Table name must not be empty");
|
||||
|
||||
this.repository.setTableName(null);
|
||||
assertThatThrownBy(() -> this.repository.setTableName(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Table name must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setTableNameEmpty() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Table name must not be empty");
|
||||
|
||||
this.repository.setTableName(" ");
|
||||
assertThatThrownBy(() -> this.repository.setTableName(" "))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Table name must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setCreateSessionQueryNull() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setCreateSessionQuery(null);
|
||||
assertThatThrownBy(() -> this.repository.setCreateSessionQuery(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setCreateSessionQueryEmpty() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setCreateSessionQuery(" ");
|
||||
assertThatThrownBy(() -> this.repository.setCreateSessionQuery(" "))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setCreateSessionAttributeQueryNull() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setCreateSessionAttributeQuery(null);
|
||||
assertThatThrownBy(() -> this.repository.setCreateSessionAttributeQuery(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setCreateSessionAttributeQueryEmpty() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setCreateSessionAttributeQuery(" ");
|
||||
assertThatThrownBy(() -> this.repository.setCreateSessionAttributeQuery(" "))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setGetSessionQueryNull() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setGetSessionQuery(null);
|
||||
assertThatThrownBy(() -> this.repository.setGetSessionQuery(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setGetSessionQueryEmpty() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setGetSessionQuery(" ");
|
||||
assertThatThrownBy(() -> this.repository.setGetSessionQuery(" "))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setUpdateSessionQueryNull() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setUpdateSessionQuery(null);
|
||||
assertThatThrownBy(() -> this.repository.setUpdateSessionQuery(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setUpdateSessionQueryEmpty() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setUpdateSessionQuery(" ");
|
||||
assertThatThrownBy(() -> this.repository.setUpdateSessionQuery(" "))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setUpdateSessionAttributeQueryNull() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setUpdateSessionAttributeQuery(null);
|
||||
assertThatThrownBy(() -> this.repository.setUpdateSessionAttributeQuery(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setUpdateSessionAttributeQueryEmpty() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setUpdateSessionAttributeQuery(" ");
|
||||
assertThatThrownBy(() -> this.repository.setUpdateSessionAttributeQuery(" "))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDeleteSessionAttributeQueryNull() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setDeleteSessionAttributeQuery(null);
|
||||
assertThatThrownBy(() -> this.repository.setDeleteSessionAttributeQuery(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDeleteSessionAttributeQueryEmpty() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setDeleteSessionAttributeQuery(" ");
|
||||
assertThatThrownBy(() -> this.repository.setDeleteSessionAttributeQuery(" "))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDeleteSessionQueryNull() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setDeleteSessionQuery(null);
|
||||
assertThatThrownBy(() -> this.repository.setDeleteSessionQuery(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDeleteSessionQueryEmpty() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setDeleteSessionQuery(" ");
|
||||
assertThatThrownBy(() -> this.repository.setDeleteSessionQuery(" "))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setListSessionsByPrincipalNameQueryNull() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setListSessionsByPrincipalNameQuery(null);
|
||||
assertThatThrownBy(
|
||||
() -> this.repository.setListSessionsByPrincipalNameQuery(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setListSessionsByPrincipalNameQueryEmpty() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setListSessionsByPrincipalNameQuery(" ");
|
||||
assertThatThrownBy(() -> this.repository.setListSessionsByPrincipalNameQuery(" "))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDeleteSessionsByLastAccessTimeQueryNull() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setDeleteSessionsByExpiryTimeQuery(null);
|
||||
assertThatThrownBy(() -> this.repository.setDeleteSessionsByExpiryTimeQuery(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDeleteSessionsByLastAccessTimeQueryEmpty() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Query must not be empty");
|
||||
|
||||
this.repository.setDeleteSessionsByExpiryTimeQuery(" ");
|
||||
assertThatThrownBy(() -> this.repository.setDeleteSessionsByExpiryTimeQuery(" "))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Query must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setLobHandlerNull() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("LobHandler must not be null");
|
||||
|
||||
this.repository.setLobHandler(null);
|
||||
assertThatThrownBy(() -> this.repository.setLobHandler(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("LobHandler must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setConversionServiceNull() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("conversionService must not be null");
|
||||
|
||||
this.repository.setConversionService(null);
|
||||
assertThatThrownBy(() -> this.repository.setConversionService(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("conversionService must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSessionDefaultMaxInactiveInterval() throws Exception {
|
||||
public void createSessionDefaultMaxInactiveInterval() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository
|
||||
.createSession();
|
||||
|
||||
@@ -291,7 +258,7 @@ public class JdbcOperationsSessionRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSessionCustomMaxInactiveInterval() throws Exception {
|
||||
public void createSessionCustomMaxInactiveInterval() {
|
||||
int interval = 1;
|
||||
this.repository.setDefaultMaxInactiveInterval(interval);
|
||||
|
||||
@@ -314,11 +281,11 @@ public class JdbcOperationsSessionRepositoryTests {
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations, times(1)).update(startsWith("INSERT"),
|
||||
isA(PreparedStatementSetter.class));
|
||||
verifyNoMoreInteractions(this.jdbcOperations);
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveNewWithAttributes() {
|
||||
public void saveNewWithSingleAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository
|
||||
.createSession();
|
||||
session.setAttribute("testName", "testValue");
|
||||
@@ -327,15 +294,37 @@ public class JdbcOperationsSessionRepositoryTests {
|
||||
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations, times(1)).update(startsWith("INSERT"),
|
||||
verify(this.jdbcOperations, times(1)).update(
|
||||
startsWith("INSERT INTO SPRING_SESSION("),
|
||||
isA(PreparedStatementSetter.class));
|
||||
verify(this.jdbcOperations, times(1)).batchUpdate(
|
||||
and(startsWith("INSERT"), contains("ATTRIBUTE_BYTES")),
|
||||
isA(BatchPreparedStatementSetter.class));
|
||||
verify(this.jdbcOperations, times(1)).update(
|
||||
startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES("),
|
||||
isA(PreparedStatementSetter.class));
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveUpdatedAttributes() {
|
||||
public void saveNewWithMultipleAttributes() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository
|
||||
.createSession();
|
||||
session.setAttribute("testName1", "testValue1");
|
||||
session.setAttribute("testName2", "testValue2");
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations, times(1)).update(
|
||||
startsWith("INSERT INTO SPRING_SESSION("),
|
||||
isA(PreparedStatementSetter.class));
|
||||
verify(this.jdbcOperations, times(1)).batchUpdate(
|
||||
startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES("),
|
||||
isA(BatchPreparedStatementSetter.class));
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveUpdatedAddSingleAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
|
||||
new MapSession());
|
||||
session.setAttribute("testName", "testValue");
|
||||
@@ -345,8 +334,184 @@ public class JdbcOperationsSessionRepositoryTests {
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations, times(1)).update(
|
||||
and(startsWith("UPDATE"), contains("ATTRIBUTE_BYTES")),
|
||||
startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES("),
|
||||
isA(PreparedStatementSetter.class));
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveUpdatedAddMultipleAttributes() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
|
||||
new MapSession());
|
||||
session.setAttribute("testName1", "testValue1");
|
||||
session.setAttribute("testName2", "testValue2");
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations, times(1)).batchUpdate(
|
||||
startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES("),
|
||||
isA(BatchPreparedStatementSetter.class));
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveUpdatedModifySingleAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
|
||||
new MapSession());
|
||||
session.setAttribute("testName", "testValue");
|
||||
session.clearChangeFlags();
|
||||
session.setAttribute("testName", "testValue");
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations, times(1)).update(
|
||||
startsWith("UPDATE SPRING_SESSION_ATTRIBUTES SET"),
|
||||
isA(PreparedStatementSetter.class));
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveUpdatedModifyMultipleAttributes() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
|
||||
new MapSession());
|
||||
session.setAttribute("testName1", "testValue1");
|
||||
session.setAttribute("testName2", "testValue2");
|
||||
session.clearChangeFlags();
|
||||
session.setAttribute("testName1", "testValue1");
|
||||
session.setAttribute("testName2", "testValue2");
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations, times(1)).batchUpdate(
|
||||
startsWith("UPDATE SPRING_SESSION_ATTRIBUTES SET"),
|
||||
isA(BatchPreparedStatementSetter.class));
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveUpdatedRemoveSingleAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
|
||||
new MapSession());
|
||||
session.setAttribute("testName", "testValue");
|
||||
session.clearChangeFlags();
|
||||
session.removeAttribute("testName");
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations, times(1)).update(
|
||||
startsWith("DELETE FROM SPRING_SESSION_ATTRIBUTES WHERE"),
|
||||
isA(PreparedStatementSetter.class));
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveUpdatedRemoveNonExistingAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
|
||||
new MapSession());
|
||||
session.removeAttribute("testName");
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveUpdatedRemoveMultipleAttributes() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
|
||||
new MapSession());
|
||||
session.setAttribute("testName1", "testValue1");
|
||||
session.setAttribute("testName2", "testValue2");
|
||||
session.clearChangeFlags();
|
||||
session.removeAttribute("testName1");
|
||||
session.removeAttribute("testName2");
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations, times(1)).batchUpdate(
|
||||
startsWith("DELETE FROM SPRING_SESSION_ATTRIBUTES WHERE"),
|
||||
isA(BatchPreparedStatementSetter.class));
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test // gh-1070
|
||||
public void saveUpdatedAddAndModifyAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
|
||||
new MapSession());
|
||||
session.setAttribute("testName", "testValue1");
|
||||
session.setAttribute("testName", "testValue2");
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations).update(
|
||||
startsWith("INSERT INTO SPRING_SESSION_ATTRIBUTES("),
|
||||
isA(PreparedStatementSetter.class));
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test // gh-1070
|
||||
public void saveUpdatedAddAndRemoveAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
|
||||
new MapSession());
|
||||
session.setAttribute("testName", "testValue");
|
||||
session.removeAttribute("testName");
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test // gh-1070
|
||||
public void saveUpdatedModifyAndRemoveAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
|
||||
new MapSession());
|
||||
session.setAttribute("testName", "testValue1");
|
||||
session.clearChangeFlags();
|
||||
session.setAttribute("testName", "testValue2");
|
||||
session.removeAttribute("testName");
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations).update(
|
||||
startsWith("DELETE FROM SPRING_SESSION_ATTRIBUTES WHERE"),
|
||||
isA(PreparedStatementSetter.class));
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test // gh-1070
|
||||
public void saveUpdatedRemoveAndAddAttribute() {
|
||||
JdbcOperationsSessionRepository.JdbcSession session = this.repository.new JdbcSession("primaryKey",
|
||||
new MapSession());
|
||||
session.setAttribute("testName", "testValue1");
|
||||
session.clearChangeFlags();
|
||||
session.removeAttribute("testName");
|
||||
session.setAttribute("testName", "testValue2");
|
||||
|
||||
this.repository.save(session);
|
||||
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations).update(
|
||||
startsWith("UPDATE SPRING_SESSION_ATTRIBUTES SET"),
|
||||
isA(PreparedStatementSetter.class));
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -360,8 +525,9 @@ public class JdbcOperationsSessionRepositoryTests {
|
||||
assertThat(session.isNew()).isFalse();
|
||||
assertPropagationRequiresNew();
|
||||
verify(this.jdbcOperations, times(1)).update(
|
||||
and(startsWith("UPDATE"), contains("LAST_ACCESS_TIME")),
|
||||
startsWith("UPDATE SPRING_SESSION SET"),
|
||||
isA(PreparedStatementSetter.class));
|
||||
verifyZeroInteractions(this.jdbcOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,9 +19,7 @@ package org.springframework.session.jdbc.config.annotation.web.http;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@@ -39,6 +37,7 @@ import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
@@ -56,9 +55,6 @@ public class JdbcHttpSessionConfigurationTests {
|
||||
|
||||
private static final String CLEANUP_CRON_EXPRESSION = "0 0 * * * *";
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
||||
@After
|
||||
@@ -70,11 +66,9 @@ public class JdbcHttpSessionConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void noDataSourceConfiguration() {
|
||||
this.thrown.expect(BeanCreationException.class);
|
||||
this.thrown.expectMessage(
|
||||
"expected at least 1 bean which qualifies as autowire candidate");
|
||||
|
||||
registerAndRefresh(NoDataSourceConfiguration.class);
|
||||
assertThatThrownBy(() -> registerAndRefresh(NoDataSourceConfiguration.class))
|
||||
.isInstanceOf(BeanCreationException.class).hasMessageContaining(
|
||||
"expected at least 1 bean which qualifies as autowire candidate");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -230,11 +224,10 @@ public class JdbcHttpSessionConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void multipleDataSourceConfiguration() {
|
||||
this.thrown.expect(BeanCreationException.class);
|
||||
this.thrown.expectMessage("expected single matching bean but found 2");
|
||||
|
||||
registerAndRefresh(DataSourceConfiguration.class,
|
||||
MultipleDataSourceConfiguration.class);
|
||||
assertThatThrownBy(() -> registerAndRefresh(DataSourceConfiguration.class,
|
||||
MultipleDataSourceConfiguration.class))
|
||||
.isInstanceOf(BeanCreationException.class)
|
||||
.hasMessageContaining("expected single matching bean but found 2");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user