Use java.time in all session repositories and configurations

This commit reworks all session repository implementations and their respective configurations to use java.time for managing maxInactiveInterval and other temporal values.
This commit is contained in:
Vedran Pavic
2022-09-26 10:19:37 +02:00
committed by Rob Winch
parent da8e5fbbac
commit 6d74cf5f35
37 changed files with 281 additions and 285 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2021 the original author or authors.
* Copyright 2014-2022 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.
@@ -55,11 +55,7 @@ public class ReactiveRedisSessionRepository
*/
private String namespace = DEFAULT_NAMESPACE + ":";
/**
* If non-null, this value is used to override the default value for
* {@link RedisSession#setMaxInactiveInterval(Duration)}.
*/
private Integer defaultMaxInactiveInterval;
private Duration defaultMaxInactiveInterval = Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE;
@@ -79,13 +75,13 @@ public class ReactiveRedisSessionRepository
}
/**
* Sets the maximum inactive interval in seconds between requests before newly created
* Set the maximum inactive interval in seconds between requests before newly created
* sessions will be invalidated. A negative time indicates that the session will never
* timeout. The default is 1800 (30 minutes).
* @param defaultMaxInactiveInterval the number of seconds that the {@link Session}
* should be kept alive between client requests.
* time out. The default is 30 minutes.
* @param defaultMaxInactiveInterval the default maxInactiveInterval
*/
public void setDefaultMaxInactiveInterval(int defaultMaxInactiveInterval) {
public void setDefaultMaxInactiveInterval(Duration defaultMaxInactiveInterval) {
Assert.notNull(defaultMaxInactiveInterval, "defaultMaxInactiveInterval must not be null");
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
}
@@ -110,9 +106,7 @@ public class ReactiveRedisSessionRepository
public Mono<RedisSession> createSession() {
return Mono.defer(() -> {
MapSession cached = new MapSession();
if (this.defaultMaxInactiveInterval != null) {
cached.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
}
cached.setMaxInactiveInterval(this.defaultMaxInactiveInterval);
RedisSession session = new RedisSession(cached, true);
return Mono.just(session);
});

View File

@@ -307,11 +307,7 @@ public class RedisIndexedSessionRepository
private ApplicationEventPublisher eventPublisher = (event) -> {
};
/**
* If non-null, this value is used to override the default value for
* {@link RedisSession#setMaxInactiveInterval(Duration)}.
*/
private Integer defaultMaxInactiveInterval;
private Duration defaultMaxInactiveInterval = Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
private IndexResolver<Session> indexResolver = new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>());
@@ -373,13 +369,13 @@ public class RedisIndexedSessionRepository
}
/**
* Sets the maximum inactive interval in seconds between requests before newly created
* Set the maximum inactive interval in seconds between requests before newly created
* sessions will be invalidated. A negative time indicates that the session will never
* timeout. The default is 1800 (30 minutes).
* @param defaultMaxInactiveInterval the number of seconds that the {@link Session}
* should be kept alive between client requests.
* time out. The default is 30 minutes.
* @param defaultMaxInactiveInterval the default maxInactiveInterval
*/
public void setDefaultMaxInactiveInterval(int defaultMaxInactiveInterval) {
public void setDefaultMaxInactiveInterval(Duration defaultMaxInactiveInterval) {
Assert.notNull(defaultMaxInactiveInterval, "defaultMaxInactiveInterval must not be null");
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
}
@@ -560,9 +556,7 @@ public class RedisIndexedSessionRepository
@Override
public RedisSession createSession() {
MapSession cached = new MapSession();
if (this.defaultMaxInactiveInterval != null) {
cached.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
}
cached.setMaxInactiveInterval(this.defaultMaxInactiveInterval);
RedisSession session = new RedisSession(cached, true);
session.flushImmediateIfNecessary();
return session;

View File

@@ -18,7 +18,6 @@ package org.springframework.session.data.redis;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -68,7 +67,9 @@ public class RedisSessionRepository implements SessionRepository<RedisSessionRep
}
/**
* Set the default maxInactiveInterval.
* Set the maximum inactive interval in seconds between requests before newly created
* sessions will be invalidated. A negative time indicates that the session will never
* time out. The default is 30 minutes.
* @param defaultMaxInactiveInterval the default maxInactiveInterval
*/
public void setDefaultMaxInactiveInterval(Duration defaultMaxInactiveInterval) {
@@ -296,8 +297,8 @@ public class RedisSessionRepository implements SessionRepository<RedisSessionRep
String key = getSessionKey(getId());
RedisSessionRepository.this.sessionRedisOperations.opsForHash().putAll(key, new HashMap<>(this.delta));
RedisSessionRepository.this.sessionRedisOperations.expireAt(key,
Date.from(Instant.ofEpochMilli(getLastAccessedTime().toEpochMilli())
.plusSeconds(getMaxInactiveInterval().getSeconds())));
Instant.ofEpochMilli(getLastAccessedTime().toEpochMilli())
.plusSeconds(getMaxInactiveInterval().getSeconds()));
this.delta.clear();
}

View File

@@ -16,6 +16,7 @@
package org.springframework.session.data.redis.config.annotation.web.http;
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;
@@ -53,7 +54,7 @@ import org.springframework.util.Assert;
public abstract class AbstractRedisHttpSessionConfiguration<T extends SessionRepository<? extends Session>>
extends SpringHttpSessionConfiguration implements BeanClassLoaderAware {
private Integer maxInactiveIntervalInSeconds = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
private Duration maxInactiveInterval = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL;
private String redisNamespace = RedisSessionRepository.DEFAULT_KEY_NAMESPACE;
@@ -71,12 +72,17 @@ public abstract class AbstractRedisHttpSessionConfiguration<T extends SessionRep
public abstract T sessionRepository();
public void setMaxInactiveIntervalInSeconds(int maxInactiveIntervalInSeconds) {
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
public void setMaxInactiveInterval(Duration maxInactiveInterval) {
this.maxInactiveInterval = maxInactiveInterval;
}
protected Integer getMaxInactiveIntervalInSeconds() {
return this.maxInactiveIntervalInSeconds;
@Deprecated
public void setMaxInactiveIntervalInSeconds(int maxInactiveIntervalInSeconds) {
setMaxInactiveInterval(Duration.ofSeconds(maxInactiveIntervalInSeconds));
}
protected Duration getMaxInactiveInterval() {
return this.maxInactiveInterval;
}
public void setRedisNamespace(String namespace) {

View File

@@ -54,7 +54,7 @@ public class RedisHttpSessionConfiguration extends AbstractRedisHttpSessionConfi
public RedisSessionRepository sessionRepository() {
RedisTemplate<String, Object> redisTemplate = createRedisTemplate();
RedisSessionRepository sessionRepository = new RedisSessionRepository(redisTemplate);
sessionRepository.setDefaultMaxInactiveInterval(Duration.ofSeconds(getMaxInactiveIntervalInSeconds()));
sessionRepository.setDefaultMaxInactiveInterval(getMaxInactiveInterval());
if (StringUtils.hasText(getRedisNamespace())) {
sessionRepository.setRedisKeyNamespace(getRedisNamespace());
}
@@ -78,7 +78,7 @@ public class RedisHttpSessionConfiguration extends AbstractRedisHttpSessionConfi
if (attributes == null) {
return;
}
setMaxInactiveIntervalInSeconds(attributes.getNumber("maxInactiveIntervalInSeconds"));
setMaxInactiveInterval(Duration.ofSeconds(attributes.<Integer>getNumber("maxInactiveIntervalInSeconds")));
String redisNamespaceValue = attributes.getString("redisNamespace");
if (StringUtils.hasText(redisNamespaceValue)) {
setRedisNamespace(this.embeddedValueResolver.resolveStringValue(redisNamespaceValue));

View File

@@ -16,6 +16,7 @@
package org.springframework.session.data.redis.config.annotation.web.http;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
@@ -91,7 +92,7 @@ public class RedisIndexedHttpSessionConfiguration
if (getDefaultRedisSerializer() != null) {
sessionRepository.setDefaultSerializer(getDefaultRedisSerializer());
}
sessionRepository.setDefaultMaxInactiveInterval(getMaxInactiveIntervalInSeconds());
sessionRepository.setDefaultMaxInactiveInterval(getMaxInactiveInterval());
if (StringUtils.hasText(getRedisNamespace())) {
sessionRepository.setRedisKeyNamespace(getRedisNamespace());
}
@@ -178,7 +179,7 @@ public class RedisIndexedHttpSessionConfiguration
if (attributes == null) {
return;
}
setMaxInactiveIntervalInSeconds(attributes.getNumber("maxInactiveIntervalInSeconds"));
setMaxInactiveInterval(Duration.ofSeconds(attributes.<Integer>getNumber("maxInactiveIntervalInSeconds")));
String redisNamespaceValue = attributes.getString("redisNamespace");
if (StringUtils.hasText(redisNamespaceValue)) {
setRedisNamespace(this.embeddedValueResolver.resolveStringValue(redisNamespaceValue));

View File

@@ -16,6 +16,7 @@
package org.springframework.session.data.redis.config.annotation.web.server;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -59,7 +60,7 @@ import org.springframework.web.server.session.WebSessionManager;
public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware {
private Integer maxInactiveIntervalInSeconds = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
private Duration maxInactiveInterval = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL;
private String redisNamespace = ReactiveRedisSessionRepository.DEFAULT_NAMESPACE;
@@ -79,7 +80,7 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
public ReactiveRedisSessionRepository sessionRepository() {
ReactiveRedisTemplate<String, Object> reactiveRedisTemplate = createReactiveRedisTemplate();
ReactiveRedisSessionRepository sessionRepository = new ReactiveRedisSessionRepository(reactiveRedisTemplate);
sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveInterval);
if (StringUtils.hasText(this.redisNamespace)) {
sessionRepository.setRedisKeyNamespace(this.redisNamespace);
}
@@ -89,8 +90,13 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
return sessionRepository;
}
public void setMaxInactiveInterval(Duration maxInactiveInterval) {
this.maxInactiveInterval = maxInactiveInterval;
}
@Deprecated
public void setMaxInactiveIntervalInSeconds(int maxInactiveIntervalInSeconds) {
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
setMaxInactiveInterval(Duration.ofSeconds(maxInactiveIntervalInSeconds));
}
public void setRedisNamespace(String namespace) {
@@ -143,7 +149,7 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
if (attributes == null) {
return;
}
this.maxInactiveIntervalInSeconds = attributes.getNumber("maxInactiveIntervalInSeconds");
this.maxInactiveInterval = Duration.ofSeconds(attributes.<Integer>getNumber("maxInactiveIntervalInSeconds"));
String redisNamespaceValue = attributes.getString("redisNamespace");
if (StringUtils.hasText(redisNamespaceValue)) {
this.redisNamespace = this.embeddedValueResolver.resolveStringValue(redisNamespaceValue);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2021 the original author or authors.
* Copyright 2014-2022 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.
@@ -103,9 +103,10 @@ class ReactiveRedisSessionRepositoryTests {
@Test
void customMaxInactiveInterval() {
this.repository.setDefaultMaxInactiveInterval(600);
Duration interval = Duration.ofMinutes(10);
this.repository.setDefaultMaxInactiveInterval(interval);
assertThat(ReflectionTestUtils.getField(this.repository, "defaultMaxInactiveInterval")).isEqualTo(600);
assertThat(this.repository).extracting("defaultMaxInactiveInterval").isEqualTo(interval);
}
@Test
@@ -118,11 +119,11 @@ class ReactiveRedisSessionRepositoryTests {
@Test
void createSessionCustomMaxInactiveInterval() {
this.repository.setDefaultMaxInactiveInterval(600);
Duration interval = Duration.ofMinutes(10);
this.repository.setDefaultMaxInactiveInterval(interval);
StepVerifier.create(this.repository.createSession())
.consumeNextWith(
(session) -> assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(600)))
.consumeNextWith((session) -> assertThat(session.getMaxInactiveInterval()).isEqualTo(interval))
.verifyComplete();
}

View File

@@ -158,10 +158,10 @@ class RedisIndexedSessionRepositoryTests {
@Test
void createSessionCustomMaxInactiveInterval() {
int interval = 1;
Duration interval = Duration.ofSeconds(1);
this.redisRepository.setDefaultMaxInactiveInterval(interval);
Session session = this.redisRepository.createSession();
assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(interval));
assertThat(session.getMaxInactiveInterval()).isEqualTo(interval);
}
@Test
@@ -663,7 +663,7 @@ class RedisIndexedSessionRepositoryTests {
given(this.redisOperations.<String, Object>boundHashOps(anyString())).willReturn(this.boundHashOperations);
given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations);
given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations);
this.redisRepository.setDefaultMaxInactiveInterval(60);
this.redisRepository.setDefaultMaxInactiveInterval(Duration.ofSeconds(60));
this.redisRepository.setFlushMode(FlushMode.IMMEDIATE);
this.redisRepository.createSession();
Map<String, Object> delta = getDelta();

View File

@@ -20,7 +20,6 @@ import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -378,9 +377,9 @@ class RedisSessionRepositoryTests {
return "spring:session:sessions:" + sessionId;
}
private static Date getExpiry(RedisSession session) {
return Date.from(Instant.ofEpochMilli(session.getLastAccessedTime().toEpochMilli())
.plusSeconds(session.getMaxInactiveInterval().getSeconds()));
private static Instant getExpiry(RedisSession session) {
return Instant.ofEpochMilli(session.getLastAccessedTime().toEpochMilli())
.plusSeconds(session.getMaxInactiveInterval().getSeconds());
}
private static Map mapOf(Object... objects) {

View File

@@ -16,6 +16,7 @@
package org.springframework.session.data.redis.config.annotation.web.http;
import java.time.Duration;
import java.util.Map;
import java.util.Properties;
@@ -228,15 +229,15 @@ class RedisIndexedHttpSessionConfigurationTests {
void sessionRepositoryCustomizer() {
registerAndRefresh(RedisConfig.class, SessionRepositoryCustomizerConfiguration.class);
RedisIndexedSessionRepository sessionRepository = this.context.getBean(RedisIndexedSessionRepository.class);
assertThat(sessionRepository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
MAX_INACTIVE_INTERVAL_IN_SECONDS);
assertThat(sessionRepository).extracting("defaultMaxInactiveInterval")
.isEqualTo(Duration.ofSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS));
}
@Test
void importConfigAndCustomize() {
registerAndRefresh(RedisConfig.class, ImportConfigAndCustomizeConfiguration.class);
RedisIndexedSessionRepository sessionRepository = this.context.getBean(RedisIndexedSessionRepository.class);
assertThat(sessionRepository).extracting("defaultMaxInactiveInterval").isEqualTo(0);
assertThat(sessionRepository).extracting("defaultMaxInactiveInterval").isEqualTo(Duration.ZERO);
}
private void registerAndRefresh(Class<?>... annotatedClasses) {
@@ -420,14 +421,14 @@ class RedisIndexedHttpSessionConfigurationTests {
@Bean
@Order(0)
SessionRepositoryCustomizer<RedisIndexedSessionRepository> sessionRepositoryCustomizerOne() {
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0);
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(Duration.ZERO);
}
@Bean
@Order(1)
SessionRepositoryCustomizer<RedisIndexedSessionRepository> sessionRepositoryCustomizerTwo() {
return (sessionRepository) -> sessionRepository
.setDefaultMaxInactiveInterval(MAX_INACTIVE_INTERVAL_IN_SECONDS);
.setDefaultMaxInactiveInterval(Duration.ofSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS));
}
}
@@ -438,7 +439,7 @@ class RedisIndexedHttpSessionConfigurationTests {
@Bean
SessionRepositoryCustomizer<RedisIndexedSessionRepository> sessionRepositoryCustomizer() {
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0);
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(Duration.ZERO);
}
}

View File

@@ -16,6 +16,7 @@
package org.springframework.session.data.redis.config.annotation.web.http.gh109;
import java.time.Duration;
import java.util.Properties;
import org.junit.jupiter.api.Test;
@@ -60,7 +61,7 @@ class Gh109Tests {
@Configuration
static class Config extends RedisHttpSessionConfiguration {
int sessionTimeout = 100;
Duration sessionTimeout = Duration.ofSeconds(100);
/**
* override sessionRepository construction to set the custom session-timeout

View File

@@ -16,6 +16,8 @@
package org.springframework.session.data.redis.config.annotation.web.server;
import java.time.Duration;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -103,9 +105,8 @@ class RedisWebSessionConfigurationTests {
registerAndRefresh(RedisConfig.class, CustomMaxInactiveIntervalConfig.class);
ReactiveRedisSessionRepository repository = this.context.getBean(ReactiveRedisSessionRepository.class);
assertThat(repository).isNotNull();
assertThat(ReflectionTestUtils.getField(repository, "defaultMaxInactiveInterval"))
.isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
assertThat(repository).extracting("defaultMaxInactiveInterval")
.isEqualTo(Duration.ofSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS));
}
@Test
@@ -222,15 +223,15 @@ class RedisWebSessionConfigurationTests {
void sessionRepositoryCustomizer() {
registerAndRefresh(RedisConfig.class, SessionRepositoryCustomizerConfiguration.class);
ReactiveRedisSessionRepository sessionRepository = this.context.getBean(ReactiveRedisSessionRepository.class);
assertThat(sessionRepository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
MAX_INACTIVE_INTERVAL_IN_SECONDS);
assertThat(sessionRepository).extracting("defaultMaxInactiveInterval")
.isEqualTo(Duration.ofSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS));
}
@Test
void importConfigAndCustomize() {
registerAndRefresh(RedisConfig.class, ImportConfigAndCustomizeConfiguration.class);
ReactiveRedisSessionRepository sessionRepository = this.context.getBean(ReactiveRedisSessionRepository.class);
assertThat(sessionRepository).extracting("defaultMaxInactiveInterval").isEqualTo(0);
assertThat(sessionRepository).extracting("defaultMaxInactiveInterval").isEqualTo(Duration.ZERO);
}
private void registerAndRefresh(Class<?>... annotatedClasses) {
@@ -377,14 +378,14 @@ class RedisWebSessionConfigurationTests {
@Bean
@Order(0)
ReactiveSessionRepositoryCustomizer<ReactiveRedisSessionRepository> sessionRepositoryCustomizerOne() {
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0);
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(Duration.ZERO);
}
@Bean
@Order(1)
ReactiveSessionRepositoryCustomizer<ReactiveRedisSessionRepository> sessionRepositoryCustomizerTwo() {
return (sessionRepository) -> sessionRepository
.setDefaultMaxInactiveInterval(MAX_INACTIVE_INTERVAL_IN_SECONDS);
.setDefaultMaxInactiveInterval(Duration.ofSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS));
}
}
@@ -395,7 +396,7 @@ class RedisWebSessionConfigurationTests {
@Bean
ReactiveSessionRepositoryCustomizer<ReactiveRedisSessionRepository> sessionRepositoryCustomizer() {
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0);
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(Duration.ZERO);
}
}