Add common flush mode support

Resolves: #1465
This commit is contained in:
Vedran Pavic
2019-06-21 15:49:59 +02:00
parent a6f6042831
commit 07b9433540
17 changed files with 309 additions and 53 deletions

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.session;
/**
* Supported modes of writing the session to session store.
*
* @author Rob Winch
* @author Vedran Pavic
* @since 2.2.0
*/
public enum FlushMode {
/**
* Only writes to session store when {@link SessionRepository#save(Session)} is
* invoked. In a web environment this is typically done as soon as the HTTP response
* is committed.
*/
ON_SAVE,
/**
* Writes to session store as soon as possible. For example
* {@link SessionRepository#createSession()} will write the session to session store.
* Another example is that setting an attribute using
* {@link Session#setAttribute(String, Object)} will also write to session store
* immediately.
*/
IMMEDIATE
}

View File

@@ -21,10 +21,10 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.session.FlushMode;
import org.springframework.session.Session; import org.springframework.session.Session;
import org.springframework.session.SessionRepository; import org.springframework.session.SessionRepository;
import org.springframework.session.data.redis.AbstractRedisITests; import org.springframework.session.data.redis.AbstractRedisITests;
import org.springframework.session.data.redis.RedisFlushMode;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -50,7 +50,7 @@ class RedisOperationsSessionRepositoryFlushImmediatelyITests<S extends Session>
} }
@Configuration @Configuration
@EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE) @EnableRedisHttpSession(flushMode = FlushMode.IMMEDIATE)
static class RedisHttpSessionConfig extends BaseConfig { static class RedisHttpSessionConfig extends BaseConfig {
} }

View File

@@ -16,6 +16,7 @@
package org.springframework.session.data.redis; package org.springframework.session.data.redis;
import org.springframework.session.FlushMode;
import org.springframework.session.SessionRepository; import org.springframework.session.SessionRepository;
/** /**
@@ -23,7 +24,9 @@ import org.springframework.session.SessionRepository;
* *
* @author Rob Winch * @author Rob Winch
* @since 1.1 * @since 1.1
* @deprecated since 2.2.0 in favor of {@link FlushMode}
*/ */
@Deprecated
public enum RedisFlushMode { public enum RedisFlushMode {
/** /**
@@ -31,7 +34,7 @@ public enum RedisFlushMode {
* {@link SessionRepository#save(org.springframework.session.Session)} is invoked. In * {@link SessionRepository#save(org.springframework.session.Session)} is invoked. In
* a web environment this is typically done as soon as the HTTP response is committed. * a web environment this is typically done as soon as the HTTP response is committed.
*/ */
ON_SAVE, ON_SAVE(FlushMode.ON_SAVE),
/** /**
* Writes to Redis as soon as possible. For example * Writes to Redis as soon as possible. For example
@@ -39,6 +42,16 @@ public enum RedisFlushMode {
* example is that setting an attribute on the session will also write to Redis * example is that setting an attribute on the session will also write to Redis
* immediately. * immediately.
*/ */
IMMEDIATE IMMEDIATE(FlushMode.IMMEDIATE);
private final FlushMode flushMode;
RedisFlushMode(FlushMode flushMode) {
this.flushMode = flushMode;
}
public FlushMode getFlushMode() {
return this.flushMode;
}
} }

View File

@@ -38,6 +38,7 @@ import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.session.DelegatingIndexResolver; import org.springframework.session.DelegatingIndexResolver;
import org.springframework.session.FindByIndexNameSessionRepository; import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.FlushMode;
import org.springframework.session.IndexResolver; import org.springframework.session.IndexResolver;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.PrincipalNameIndexResolver; import org.springframework.session.PrincipalNameIndexResolver;
@@ -300,7 +301,7 @@ public class RedisOperationsSessionRepository
private RedisSerializer<Object> defaultSerializer = new JdkSerializationRedisSerializer(); private RedisSerializer<Object> defaultSerializer = new JdkSerializationRedisSerializer();
private RedisFlushMode redisFlushMode = RedisFlushMode.ON_SAVE; private FlushMode flushMode = FlushMode.ON_SAVE;
/** /**
* Creates a new instance. For an example, refer to the class level javadoc. * Creates a new instance. For an example, refer to the class level javadoc.
@@ -352,10 +353,21 @@ public class RedisOperationsSessionRepository
/** /**
* Sets the redis flush mode. Default flush mode is {@link RedisFlushMode#ON_SAVE}. * Sets the redis flush mode. Default flush mode is {@link RedisFlushMode#ON_SAVE}.
* @param redisFlushMode the new redis flush mode * @param redisFlushMode the new redis flush mode
* @deprecated since 2.2.0 in favor of {@link #setFlushMode(FlushMode)}
*/ */
@Deprecated
public void setRedisFlushMode(RedisFlushMode redisFlushMode) { public void setRedisFlushMode(RedisFlushMode redisFlushMode) {
Assert.notNull(redisFlushMode, "redisFlushMode cannot be null"); Assert.notNull(redisFlushMode, "redisFlushMode cannot be null");
this.redisFlushMode = redisFlushMode; setFlushMode(redisFlushMode.getFlushMode());
}
/**
* Sets the redis flush mode. Default flush mode is {@link FlushMode#ON_SAVE}.
* @param flushMode the flush mode
*/
public void setFlushMode(FlushMode flushMode) {
Assert.notNull(flushMode, "flushMode cannot be null");
this.flushMode = flushMode;
} }
/** /**
@@ -770,7 +782,7 @@ public class RedisOperationsSessionRepository
} }
private void flushImmediateIfNecessary() { private void flushImmediateIfNecessary() {
if (RedisOperationsSessionRepository.this.redisFlushMode == RedisFlushMode.IMMEDIATE) { if (RedisOperationsSessionRepository.this.flushMode == FlushMode.IMMEDIATE) {
save(); save();
} }
} }

View File

@@ -24,6 +24,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisOperations;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.Session; import org.springframework.session.Session;
import org.springframework.session.SessionRepository; import org.springframework.session.SessionRepository;
@@ -49,7 +50,7 @@ public class SimpleRedisOperationsSessionRepository
private String keyNamespace = DEFAULT_KEY_NAMESPACE; private String keyNamespace = DEFAULT_KEY_NAMESPACE;
private RedisFlushMode flushMode = RedisFlushMode.ON_SAVE; private FlushMode flushMode = FlushMode.ON_SAVE;
/** /**
* Create a new {@link SimpleRedisOperationsSessionRepository} instance. * Create a new {@link SimpleRedisOperationsSessionRepository} instance.
@@ -83,7 +84,7 @@ public class SimpleRedisOperationsSessionRepository
* Set the flush mode. * Set the flush mode.
* @param flushMode the flush mode * @param flushMode the flush mode
*/ */
public void setFlushMode(RedisFlushMode flushMode) { public void setFlushMode(FlushMode flushMode) {
Assert.notNull(flushMode, "flushMode must not be null"); Assert.notNull(flushMode, "flushMode must not be null");
this.flushMode = flushMode; this.flushMode = flushMode;
} }
@@ -231,7 +232,7 @@ public class SimpleRedisOperationsSessionRepository
} }
private void flushIfRequired() { private void flushIfRequired() {
if (SimpleRedisOperationsSessionRepository.this.flushMode == RedisFlushMode.IMMEDIATE) { if (SimpleRedisOperationsSessionRepository.this.flushMode == FlushMode.IMMEDIATE) {
save(); save();
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2014-2017 the original author or authors. * Copyright 2014-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.Session; import org.springframework.session.Session;
import org.springframework.session.SessionRepository; import org.springframework.session.SessionRepository;
@@ -94,9 +95,23 @@ public @interface EnableRedisHttpSession {
* Session are immediately written to the Redis instance. * Session are immediately written to the Redis instance.
* @return the {@link RedisFlushMode} to use * @return the {@link RedisFlushMode} to use
* @since 1.1 * @since 1.1
* @deprecated since 2.2.0 in favor of {@link #flushMode()}
*/ */
@Deprecated
RedisFlushMode redisFlushMode() default RedisFlushMode.ON_SAVE; RedisFlushMode redisFlushMode() default RedisFlushMode.ON_SAVE;
/**
* Flush mode for the Redis sessions. The default is {@code ON_SAVE} which only
* updates the backing Redis when {@link SessionRepository#save(Session)} is invoked.
* In a web environment this happens just before the HTTP response is committed.
* <p>
* Setting the value to {@code IMMEDIATE} will ensure that the any updates to the
* Session are immediately written to the Redis instance.
* @return the {@link FlushMode} to use
* @since 2.2.0
*/
FlushMode flushMode() default FlushMode.ON_SAVE;
/** /**
* The cron expression for expired session cleanup job. By default runs every minute. * The cron expression for expired session cleanup job. By default runs every minute.
* @return the session cleanup cron expression * @return the session cleanup cron expression

View File

@@ -48,6 +48,7 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration; import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
import org.springframework.session.data.redis.RedisFlushMode; import org.springframework.session.data.redis.RedisFlushMode;
@@ -83,7 +84,7 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
private String redisNamespace = RedisOperationsSessionRepository.DEFAULT_NAMESPACE; private String redisNamespace = RedisOperationsSessionRepository.DEFAULT_NAMESPACE;
private RedisFlushMode redisFlushMode = RedisFlushMode.ON_SAVE; private FlushMode flushMode = FlushMode.ON_SAVE;
private String cleanupCron = DEFAULT_CLEANUP_CRON; private String cleanupCron = DEFAULT_CLEANUP_CRON;
@@ -115,7 +116,7 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
if (StringUtils.hasText(this.redisNamespace)) { if (StringUtils.hasText(this.redisNamespace)) {
sessionRepository.setRedisKeyNamespace(this.redisNamespace); sessionRepository.setRedisKeyNamespace(this.redisNamespace);
} }
sessionRepository.setRedisFlushMode(this.redisFlushMode); sessionRepository.setFlushMode(this.flushMode);
int database = resolveDatabase(); int database = resolveDatabase();
sessionRepository.setDatabase(database); sessionRepository.setDatabase(database);
return sessionRepository; return sessionRepository;
@@ -153,9 +154,15 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
this.redisNamespace = namespace; this.redisNamespace = namespace;
} }
@Deprecated
public void setRedisFlushMode(RedisFlushMode redisFlushMode) { public void setRedisFlushMode(RedisFlushMode redisFlushMode) {
Assert.notNull(redisFlushMode, "redisFlushMode cannot be null"); Assert.notNull(redisFlushMode, "redisFlushMode cannot be null");
this.redisFlushMode = redisFlushMode; setFlushMode(redisFlushMode.getFlushMode());
}
public void setFlushMode(FlushMode flushMode) {
Assert.notNull(flushMode, "flushMode cannot be null");
this.flushMode = flushMode;
} }
public void setCleanupCron(String cleanupCron) { public void setCleanupCron(String cleanupCron) {
@@ -217,6 +224,7 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
} }
@Override @Override
@SuppressWarnings("deprecation")
public void setImportMetadata(AnnotationMetadata importMetadata) { public void setImportMetadata(AnnotationMetadata importMetadata) {
Map<String, Object> attributeMap = importMetadata Map<String, Object> attributeMap = importMetadata
.getAnnotationAttributes(EnableRedisHttpSession.class.getName()); .getAnnotationAttributes(EnableRedisHttpSession.class.getName());
@@ -226,7 +234,12 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
if (StringUtils.hasText(redisNamespaceValue)) { if (StringUtils.hasText(redisNamespaceValue)) {
this.redisNamespace = this.embeddedValueResolver.resolveStringValue(redisNamespaceValue); this.redisNamespace = this.embeddedValueResolver.resolveStringValue(redisNamespaceValue);
} }
this.redisFlushMode = attributes.getEnum("redisFlushMode"); FlushMode flushMode = attributes.getEnum("flushMode");
RedisFlushMode redisFlushMode = attributes.getEnum("redisFlushMode");
if (flushMode == FlushMode.ON_SAVE && redisFlushMode != RedisFlushMode.ON_SAVE) {
flushMode = redisFlushMode.getFlushMode();
}
this.flushMode = flushMode;
String cleanupCron = attributes.getString("cleanupCron"); String cleanupCron = attributes.getString("cleanupCron");
if (StringUtils.hasText(cleanupCron)) { if (StringUtils.hasText(cleanupCron)) {
this.cleanupCron = cleanupCron; this.cleanupCron = cleanupCron;

View File

@@ -46,6 +46,7 @@ import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.session.FindByIndexNameSessionRepository; import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.Session; import org.springframework.session.Session;
import org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession; import org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession;
@@ -636,7 +637,7 @@ class RedisOperationsSessionRepositoryTests {
given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations); given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations);
given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations); given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations);
this.redisRepository.setRedisFlushMode(RedisFlushMode.IMMEDIATE); this.redisRepository.setFlushMode(FlushMode.IMMEDIATE);
RedisSession session = this.redisRepository.createSession(); RedisSession session = this.redisRepository.createSession();
Map<String, Object> delta = getDelta(); Map<String, Object> delta = getDelta();
@@ -655,7 +656,7 @@ class RedisOperationsSessionRepositoryTests {
given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations); given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations);
given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations); given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations);
this.redisRepository.setDefaultMaxInactiveInterval(60); this.redisRepository.setDefaultMaxInactiveInterval(60);
this.redisRepository.setRedisFlushMode(RedisFlushMode.IMMEDIATE); this.redisRepository.setFlushMode(FlushMode.IMMEDIATE);
this.redisRepository.createSession(); this.redisRepository.createSession();
Map<String, Object> delta = getDelta(); Map<String, Object> delta = getDelta();
assertThat(delta.size()).isEqualTo(3); assertThat(delta.size()).isEqualTo(3);
@@ -668,7 +669,7 @@ class RedisOperationsSessionRepositoryTests {
given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations); given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations);
given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations); given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations);
this.redisRepository.setRedisFlushMode(RedisFlushMode.IMMEDIATE); this.redisRepository.setFlushMode(FlushMode.IMMEDIATE);
RedisSession session = this.redisRepository.createSession(); RedisSession session = this.redisRepository.createSession();
String attrName = "someAttribute"; String attrName = "someAttribute";
session.setAttribute(attrName, "someValue"); session.setAttribute(attrName, "someValue");
@@ -685,7 +686,7 @@ class RedisOperationsSessionRepositoryTests {
given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations); given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations);
given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations); given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations);
this.redisRepository.setRedisFlushMode(RedisFlushMode.IMMEDIATE); this.redisRepository.setFlushMode(FlushMode.IMMEDIATE);
RedisSession session = this.redisRepository.createSession(); RedisSession session = this.redisRepository.createSession();
String attrName = "someAttribute"; String attrName = "someAttribute";
session.removeAttribute(attrName); session.removeAttribute(attrName);
@@ -702,7 +703,7 @@ class RedisOperationsSessionRepositoryTests {
given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations); given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations);
given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations); given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations);
this.redisRepository.setRedisFlushMode(RedisFlushMode.IMMEDIATE); this.redisRepository.setFlushMode(FlushMode.IMMEDIATE);
RedisSession session = this.redisRepository.createSession(); RedisSession session = this.redisRepository.createSession();
reset(this.boundHashOperations); reset(this.boundHashOperations);
@@ -718,7 +719,7 @@ class RedisOperationsSessionRepositoryTests {
given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations); given(this.redisOperations.boundSetOps(anyString())).willReturn(this.boundSetOperations);
given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations); given(this.redisOperations.boundValueOps(anyString())).willReturn(this.boundValueOperations);
this.redisRepository.setRedisFlushMode(RedisFlushMode.IMMEDIATE); this.redisRepository.setFlushMode(FlushMode.IMMEDIATE);
RedisSession session = this.redisRepository.createSession(); RedisSession session = this.redisRepository.createSession();
session.setLastAccessedTime(Instant.now()); session.setLastAccessedTime(Instant.now());
@@ -729,6 +730,12 @@ class RedisOperationsSessionRepositoryTests {
map(RedisSessionMapper.LAST_ACCESSED_TIME_KEY, session.getLastAccessedTime().toEpochMilli())); map(RedisSessionMapper.LAST_ACCESSED_TIME_KEY, session.getLastAccessedTime().toEpochMilli()));
} }
@Test
void setFlushModeNull() {
assertThatIllegalArgumentException().isThrownBy(() -> this.redisRepository.setFlushMode(null))
.withMessage("flushMode cannot be null");
}
@Test @Test
void setRedisFlushModeNull() { void setRedisFlushModeNull() {
assertThatIllegalArgumentException().isThrownBy(() -> this.redisRepository.setRedisFlushMode(null)) assertThatIllegalArgumentException().isThrownBy(() -> this.redisRepository.setRedisFlushMode(null))

View File

@@ -33,6 +33,7 @@ import org.mockito.MockitoAnnotations;
import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisOperations;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.data.redis.SimpleRedisOperationsSessionRepository.RedisSession; import org.springframework.session.data.redis.SimpleRedisOperationsSessionRepository.RedisSession;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
@@ -114,9 +115,8 @@ class SimpleRedisOperationsSessionRepositoryTests {
@Test @Test
void setFlushMode_ValidFlushMode_ShouldSetFlushMode() { void setFlushMode_ValidFlushMode_ShouldSetFlushMode() {
this.sessionRepository.setFlushMode(RedisFlushMode.IMMEDIATE); this.sessionRepository.setFlushMode(FlushMode.IMMEDIATE);
assertThat(ReflectionTestUtils.getField(this.sessionRepository, "flushMode")) assertThat(ReflectionTestUtils.getField(this.sessionRepository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
.isEqualTo(RedisFlushMode.IMMEDIATE);
} }
@Test @Test
@@ -145,7 +145,7 @@ class SimpleRedisOperationsSessionRepositoryTests {
@Test @Test
void createSession_ImmediateFlushMode_ShouldCreateSession() { void createSession_ImmediateFlushMode_ShouldCreateSession() {
this.sessionRepository.setFlushMode(RedisFlushMode.IMMEDIATE); this.sessionRepository.setFlushMode(FlushMode.IMMEDIATE);
RedisSession session = this.sessionRepository.createSession(); RedisSession session = this.sessionRepository.createSession();
String key = getSessionKey(session.getId()); String key = getSessionKey(session.getId());
verify(this.sessionRedisOperations).opsForHash(); verify(this.sessionRedisOperations).opsForHash();

View File

@@ -34,6 +34,8 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.mock.env.MockEnvironment; import org.springframework.mock.env.MockEnvironment;
import org.springframework.session.FlushMode;
import org.springframework.session.data.redis.RedisFlushMode;
import org.springframework.session.data.redis.RedisOperationsSessionRepository; import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.session.data.redis.config.annotation.SpringSessionRedisConnectionFactory; import org.springframework.session.data.redis.config.annotation.SpringSessionRedisConnectionFactory;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
@@ -86,6 +88,42 @@ class RedisHttpSessionConfigurationTests {
assertThat(ReflectionTestUtils.getField(configuration, "redisNamespace")).isEqualTo("customRedisNamespace"); assertThat(ReflectionTestUtils.getField(configuration, "redisNamespace")).isEqualTo("customRedisNamespace");
} }
@Test
void customFlushImmediately() {
registerAndRefresh(RedisConfig.class, CustomFlushImmediatelyConfiguration.class);
RedisOperationsSessionRepository sessionRepository = this.context
.getBean(RedisOperationsSessionRepository.class);
assertThat(sessionRepository).isNotNull();
assertThat(ReflectionTestUtils.getField(sessionRepository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
}
@Test
void customFlushImmediatelyLegacy() {
registerAndRefresh(RedisConfig.class, CustomFlushImmediatelyLegacyConfiguration.class);
RedisOperationsSessionRepository sessionRepository = this.context
.getBean(RedisOperationsSessionRepository.class);
assertThat(sessionRepository).isNotNull();
assertThat(ReflectionTestUtils.getField(sessionRepository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
}
@Test
void setCustomFlushImmediately() {
registerAndRefresh(RedisConfig.class, CustomFlushImmediatelySetConfiguration.class);
RedisOperationsSessionRepository sessionRepository = this.context
.getBean(RedisOperationsSessionRepository.class);
assertThat(sessionRepository).isNotNull();
assertThat(ReflectionTestUtils.getField(sessionRepository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
}
@Test
void setCustomFlushImmediatelyLegacy() {
registerAndRefresh(RedisConfig.class, CustomFlushImmediatelySetLegacyConfiguration.class);
RedisOperationsSessionRepository sessionRepository = this.context
.getBean(RedisOperationsSessionRepository.class);
assertThat(sessionRepository).isNotNull();
assertThat(ReflectionTestUtils.getField(sessionRepository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
}
@Test @Test
void customCleanupCronAnnotation() { void customCleanupCronAnnotation() {
registerAndRefresh(RedisConfig.class, CustomCleanupCronExpressionAnnotationConfiguration.class); registerAndRefresh(RedisConfig.class, CustomCleanupCronExpressionAnnotationConfiguration.class);
@@ -217,6 +255,36 @@ class RedisHttpSessionConfigurationTests {
} }
@Configuration
static class CustomFlushImmediatelySetConfiguration extends RedisHttpSessionConfiguration {
CustomFlushImmediatelySetConfiguration() {
setFlushMode(FlushMode.IMMEDIATE);
}
}
@Configuration
static class CustomFlushImmediatelySetLegacyConfiguration extends RedisHttpSessionConfiguration {
CustomFlushImmediatelySetLegacyConfiguration() {
setRedisFlushMode(RedisFlushMode.IMMEDIATE);
}
}
@Configuration
@EnableRedisHttpSession(flushMode = FlushMode.IMMEDIATE)
static class CustomFlushImmediatelyConfiguration {
}
@Configuration
@EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE)
static class CustomFlushImmediatelyLegacyConfiguration {
}
@EnableRedisHttpSession(cleanupCron = CLEANUP_CRON_EXPRESSION) @EnableRedisHttpSession(cleanupCron = CLEANUP_CRON_EXPRESSION)
static class CustomCleanupCronExpressionAnnotationConfiguration { static class CustomCleanupCronExpressionAnnotationConfiguration {

View File

@@ -757,8 +757,8 @@ You can use the following attributes to customize the configuration:
* *maxInactiveIntervalInSeconds*: The amount of time before the session expires, in seconds. * *maxInactiveIntervalInSeconds*: The amount of time before the session expires, in seconds.
* *redisNamespace*: Allows configuring an application specific namespace for the sessions. Redis keys and channel IDs start with the prefix of `<redisNamespace>:`. * *redisNamespace*: Allows configuring an application specific namespace for the sessions. Redis keys and channel IDs start with the prefix of `<redisNamespace>:`.
* *redisFlushMode*: Allows specifying when data is written to Redis. The default is only when `save` is invoked on `SessionRepository`. * *flushMode*: Allows specifying when data is written to Redis. The default is only when `save` is invoked on `SessionRepository`.
A value of `RedisFlushMode.IMMEDIATE` writes to Redis as soon as possible. A value of `FlushMode.IMMEDIATE` writes to Redis as soon as possible.
===== Custom `RedisSerializer` ===== Custom `RedisSerializer`
@@ -1008,8 +1008,8 @@ You can use the following attributes to customize the configuration:
* *maxInactiveIntervalInSeconds*: The amount of time before the session expires, in seconds * *maxInactiveIntervalInSeconds*: The amount of time before the session expires, in seconds
* *redisNamespace*: Allows configuring an application specific namespace for the sessions. Redis keys and channel IDs start with q prefix of `<redisNamespace>:`. * *redisNamespace*: Allows configuring an application specific namespace for the sessions. Redis keys and channel IDs start with q prefix of `<redisNamespace>:`.
* *redisFlushMode*: Allows specifying when data is written to Redis. The default is only when `save` is invoked on `ReactiveSessionRepository`. * *flushMode*: Allows specifying when data is written to Redis. The default is only when `save` is invoked on `ReactiveSessionRepository`.
A value of `RedisFlushMode.IMMEDIATE` writes to Redis as soon as possible. A value of `FlushMode.IMMEDIATE` writes to Redis as soon as possible.
[[api-reactiveredisoperationssessionrepository-writes]] [[api-reactiveredisoperationssessionrepository-writes]]
===== Optimized Writes ===== Optimized Writes

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2014-2016 the original author or authors. * Copyright 2014-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package org.springframework.session.hazelcast; package org.springframework.session.hazelcast;
import org.springframework.session.FlushMode;
import org.springframework.session.SessionRepository; import org.springframework.session.SessionRepository;
/** /**
@@ -23,7 +24,9 @@ import org.springframework.session.SessionRepository;
* *
* @author Aleksandar Stojsavljevic * @author Aleksandar Stojsavljevic
* @since 1.3.0 * @since 1.3.0
* @deprecated since 2.2.0 in favor of {@link FlushMode}
*/ */
@Deprecated
public enum HazelcastFlushMode { public enum HazelcastFlushMode {
/** /**
@@ -31,7 +34,7 @@ public enum HazelcastFlushMode {
* {@link SessionRepository#save(org.springframework.session.Session)} is invoked. In * {@link SessionRepository#save(org.springframework.session.Session)} is invoked. In
* a web environment this is typically done as soon as the HTTP response is committed. * a web environment this is typically done as soon as the HTTP response is committed.
*/ */
ON_SAVE, ON_SAVE(FlushMode.ON_SAVE),
/** /**
* Writes to Hazelcast as soon as possible. For example * Writes to Hazelcast as soon as possible. For example
@@ -39,6 +42,16 @@ public enum HazelcastFlushMode {
* Another example is that setting an attribute on the session will also write to * Another example is that setting an attribute on the session will also write to
* Hazelcast immediately. * Hazelcast immediately.
*/ */
IMMEDIATE IMMEDIATE(FlushMode.IMMEDIATE);
private final FlushMode flushMode;
HazelcastFlushMode(FlushMode flushMode) {
this.flushMode = flushMode;
}
public FlushMode getFlushMode() {
return this.flushMode;
}
} }

View File

@@ -42,6 +42,7 @@ import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.session.DelegatingIndexResolver; import org.springframework.session.DelegatingIndexResolver;
import org.springframework.session.FindByIndexNameSessionRepository; import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.FlushMode;
import org.springframework.session.IndexResolver; import org.springframework.session.IndexResolver;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.PrincipalNameIndexResolver; import org.springframework.session.PrincipalNameIndexResolver;
@@ -154,7 +155,7 @@ public class HazelcastSessionRepository
private String sessionMapName = DEFAULT_SESSION_MAP_NAME; private String sessionMapName = DEFAULT_SESSION_MAP_NAME;
private HazelcastFlushMode hazelcastFlushMode = HazelcastFlushMode.ON_SAVE; private FlushMode flushMode = FlushMode.ON_SAVE;
private IMap<String, MapSession> sessions; private IMap<String, MapSession> sessions;
@@ -212,10 +213,20 @@ public class HazelcastSessionRepository
* Sets the Hazelcast flush mode. Default flush mode is * Sets the Hazelcast flush mode. Default flush mode is
* {@link HazelcastFlushMode#ON_SAVE}. * {@link HazelcastFlushMode#ON_SAVE}.
* @param hazelcastFlushMode the new Hazelcast flush mode * @param hazelcastFlushMode the new Hazelcast flush mode
* @deprecated since 2.2.0 in favor of {@link #setFlushMode(FlushMode)}
*/ */
public void setHazelcastFlushMode(HazelcastFlushMode hazelcastFlushMode) { public void setHazelcastFlushMode(HazelcastFlushMode hazelcastFlushMode) {
Assert.notNull(hazelcastFlushMode, "HazelcastFlushMode cannot be null"); Assert.notNull(hazelcastFlushMode, "HazelcastFlushMode cannot be null");
this.hazelcastFlushMode = hazelcastFlushMode; setFlushMode(hazelcastFlushMode.getFlushMode());
}
/**
* Sets the Hazelcast flush mode. Default flush mode is {@link FlushMode#ON_SAVE}.
* @param flushMode the new Hazelcast flush mode
*/
public void setFlushMode(FlushMode flushMode) {
Assert.notNull(flushMode, "flushMode cannot be null");
this.flushMode = flushMode;
} }
@Override @Override
@@ -456,7 +467,7 @@ public class HazelcastSessionRepository
} }
private void flushImmediateIfNecessary() { private void flushImmediateIfNecessary() {
if (HazelcastSessionRepository.this.hazelcastFlushMode == HazelcastFlushMode.IMMEDIATE) { if (HazelcastSessionRepository.this.flushMode == FlushMode.IMMEDIATE) {
HazelcastSessionRepository.this.save(this); HazelcastSessionRepository.this.save(this);
} }
} }

View File

@@ -26,6 +26,7 @@ import com.hazelcast.core.HazelcastInstance;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.Session; import org.springframework.session.Session;
import org.springframework.session.SessionRepository; import org.springframework.session.SessionRepository;
@@ -94,7 +95,22 @@ public @interface EnableHazelcastHttpSession {
* Session are immediately written to the Hazelcast instance. * Session are immediately written to the Hazelcast instance.
* @return the {@link HazelcastFlushMode} to use * @return the {@link HazelcastFlushMode} to use
* @since 1.3.0 * @since 1.3.0
* @deprecated since 2.2.0 in favor of {@link #flushMode()}
*/ */
@Deprecated
HazelcastFlushMode hazelcastFlushMode() default HazelcastFlushMode.ON_SAVE; HazelcastFlushMode hazelcastFlushMode() default HazelcastFlushMode.ON_SAVE;
/**
* Flush mode for the Hazelcast sessions. The default is {@code ON_SAVE} which only
* updates the backing Hazelcast when {@link SessionRepository#save(Session)} is
* invoked. In a web environment this happens just before the HTTP response is
* committed.
* <p>
* Setting the value to {@code IMMEDIATE} will ensure that the any updates to the
* Session are immediately written to the Hazelcast instance.
* @return the {@link FlushMode} to use
* @since 2.2.0
*/
FlushMode flushMode() default FlushMode.ON_SAVE;
} }

View File

@@ -28,6 +28,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware; import org.springframework.context.annotation.ImportAware;
import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.AnnotationMetadata;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration; import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
import org.springframework.session.hazelcast.HazelcastFlushMode; import org.springframework.session.hazelcast.HazelcastFlushMode;
@@ -53,7 +54,7 @@ public class HazelcastHttpSessionConfiguration extends SpringHttpSessionConfigur
private String sessionMapName = HazelcastSessionRepository.DEFAULT_SESSION_MAP_NAME; private String sessionMapName = HazelcastSessionRepository.DEFAULT_SESSION_MAP_NAME;
private HazelcastFlushMode hazelcastFlushMode = HazelcastFlushMode.ON_SAVE; private FlushMode flushMode = FlushMode.ON_SAVE;
private HazelcastInstance hazelcastInstance; private HazelcastInstance hazelcastInstance;
@@ -67,7 +68,7 @@ public class HazelcastHttpSessionConfiguration extends SpringHttpSessionConfigur
sessionRepository.setSessionMapName(this.sessionMapName); sessionRepository.setSessionMapName(this.sessionMapName);
} }
sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds); sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
sessionRepository.setHazelcastFlushMode(this.hazelcastFlushMode); sessionRepository.setFlushMode(this.flushMode);
return sessionRepository; return sessionRepository;
} }
@@ -79,8 +80,13 @@ public class HazelcastHttpSessionConfiguration extends SpringHttpSessionConfigur
this.sessionMapName = sessionMapName; this.sessionMapName = sessionMapName;
} }
@Deprecated
public void setHazelcastFlushMode(HazelcastFlushMode hazelcastFlushMode) { public void setHazelcastFlushMode(HazelcastFlushMode hazelcastFlushMode) {
this.hazelcastFlushMode = hazelcastFlushMode; setFlushMode(hazelcastFlushMode.getFlushMode());
}
public void setFlushMode(FlushMode flushMode) {
this.flushMode = flushMode;
} }
@Autowired @Autowired
@@ -100,6 +106,7 @@ public class HazelcastHttpSessionConfiguration extends SpringHttpSessionConfigur
} }
@Override @Override
@SuppressWarnings("deprecation")
public void setImportMetadata(AnnotationMetadata importMetadata) { public void setImportMetadata(AnnotationMetadata importMetadata) {
Map<String, Object> attributeMap = importMetadata Map<String, Object> attributeMap = importMetadata
.getAnnotationAttributes(EnableHazelcastHttpSession.class.getName()); .getAnnotationAttributes(EnableHazelcastHttpSession.class.getName());
@@ -109,7 +116,12 @@ public class HazelcastHttpSessionConfiguration extends SpringHttpSessionConfigur
if (StringUtils.hasText(sessionMapNameValue)) { if (StringUtils.hasText(sessionMapNameValue)) {
this.sessionMapName = sessionMapNameValue; this.sessionMapName = sessionMapNameValue;
} }
this.hazelcastFlushMode = attributes.getEnum("hazelcastFlushMode"); FlushMode flushMode = attributes.getEnum("flushMode");
HazelcastFlushMode hazelcastFlushMode = attributes.getEnum("hazelcastFlushMode");
if (flushMode == FlushMode.ON_SAVE && hazelcastFlushMode != HazelcastFlushMode.ON_SAVE) {
flushMode = hazelcastFlushMode.getFlushMode();
}
this.flushMode = flushMode;
} }
} }

View File

@@ -35,6 +35,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.session.FindByIndexNameSessionRepository; import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession; import org.springframework.session.MapSession;
import org.springframework.session.hazelcast.HazelcastSessionRepository.HazelcastSession; import org.springframework.session.hazelcast.HazelcastSessionRepository.HazelcastSession;
@@ -122,7 +123,7 @@ class HazelcastSessionRepositoryTests {
void saveNewFlushModeImmediate() { void saveNewFlushModeImmediate() {
verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean()); verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean());
this.repository.setHazelcastFlushMode(HazelcastFlushMode.IMMEDIATE); this.repository.setFlushMode(FlushMode.IMMEDIATE);
HazelcastSession session = this.repository.createSession(); HazelcastSession session = this.repository.createSession();
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class), verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),
@@ -148,7 +149,7 @@ class HazelcastSessionRepositoryTests {
void saveUpdatedAttributeFlushModeImmediate() { void saveUpdatedAttributeFlushModeImmediate() {
verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean()); verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean());
this.repository.setHazelcastFlushMode(HazelcastFlushMode.IMMEDIATE); this.repository.setFlushMode(FlushMode.IMMEDIATE);
HazelcastSession session = this.repository.createSession(); HazelcastSession session = this.repository.createSession();
session.setAttribute("testName", "testValue"); session.setAttribute("testName", "testValue");
@@ -178,7 +179,7 @@ class HazelcastSessionRepositoryTests {
void removeAttributeFlushModeImmediate() { void removeAttributeFlushModeImmediate() {
verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean()); verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean());
this.repository.setHazelcastFlushMode(HazelcastFlushMode.IMMEDIATE); this.repository.setFlushMode(FlushMode.IMMEDIATE);
HazelcastSession session = this.repository.createSession(); HazelcastSession session = this.repository.createSession();
session.removeAttribute("testName"); session.removeAttribute("testName");
@@ -208,7 +209,7 @@ class HazelcastSessionRepositoryTests {
void saveUpdatedLastAccessedTimeFlushModeImmediate() { void saveUpdatedLastAccessedTimeFlushModeImmediate() {
verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean()); verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean());
this.repository.setHazelcastFlushMode(HazelcastFlushMode.IMMEDIATE); this.repository.setFlushMode(FlushMode.IMMEDIATE);
HazelcastSession session = this.repository.createSession(); HazelcastSession session = this.repository.createSession();
session.setLastAccessedTime(Instant.now()); session.setLastAccessedTime(Instant.now());
@@ -238,7 +239,7 @@ class HazelcastSessionRepositoryTests {
void saveUpdatedMaxInactiveIntervalInSecondsFlushModeImmediate() { void saveUpdatedMaxInactiveIntervalInSecondsFlushModeImmediate() {
verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean()); verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean());
this.repository.setHazelcastFlushMode(HazelcastFlushMode.IMMEDIATE); this.repository.setFlushMode(FlushMode.IMMEDIATE);
HazelcastSession session = this.repository.createSession(); HazelcastSession session = this.repository.createSession();
String sessionId = session.getId(); String sessionId = session.getId();
@@ -269,7 +270,7 @@ class HazelcastSessionRepositoryTests {
void saveUnchangedFlushModeImmediate() { void saveUnchangedFlushModeImmediate() {
verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean()); verify(this.sessions, times(1)).addEntryListener(any(MapListener.class), anyBoolean());
this.repository.setHazelcastFlushMode(HazelcastFlushMode.IMMEDIATE); this.repository.setFlushMode(FlushMode.IMMEDIATE);
HazelcastSession session = this.repository.createSession(); HazelcastSession session = this.repository.createSession();
verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class), verify(this.sessions, times(1)).set(eq(session.getId()), eq(session.getDelegate()), isA(Long.class),

View File

@@ -26,6 +26,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.session.FlushMode;
import org.springframework.session.hazelcast.HazelcastFlushMode; import org.springframework.session.hazelcast.HazelcastFlushMode;
import org.springframework.session.hazelcast.HazelcastSessionRepository; import org.springframework.session.hazelcast.HazelcastSessionRepository;
import org.springframework.session.hazelcast.config.annotation.SpringSessionHazelcastInstance; import org.springframework.session.hazelcast.config.annotation.SpringSessionHazelcastInstance;
@@ -49,8 +50,6 @@ class HazelcastHttpSessionConfigurationTests {
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600; private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600;
private static final HazelcastFlushMode HAZELCAST_FLUSH_MODE = HazelcastFlushMode.IMMEDIATE;
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@AfterEach @AfterEach
@@ -120,8 +119,16 @@ class HazelcastHttpSessionConfigurationTests {
HazelcastSessionRepository repository = this.context.getBean(HazelcastSessionRepository.class); HazelcastSessionRepository repository = this.context.getBean(HazelcastSessionRepository.class);
assertThat(repository).isNotNull(); assertThat(repository).isNotNull();
assertThat(ReflectionTestUtils.getField(repository, "hazelcastFlushMode")) assertThat(ReflectionTestUtils.getField(repository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
.isEqualTo(HazelcastFlushMode.IMMEDIATE); }
@Test
void customFlushImmediatelyLegacy() {
registerAndRefresh(CustomFlushImmediatelyLegacyConfiguration.class);
HazelcastSessionRepository repository = this.context.getBean(HazelcastSessionRepository.class);
assertThat(repository).isNotNull();
assertThat(ReflectionTestUtils.getField(repository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
} }
@Test @Test
@@ -130,8 +137,16 @@ class HazelcastHttpSessionConfigurationTests {
HazelcastSessionRepository repository = this.context.getBean(HazelcastSessionRepository.class); HazelcastSessionRepository repository = this.context.getBean(HazelcastSessionRepository.class);
assertThat(repository).isNotNull(); assertThat(repository).isNotNull();
assertThat(ReflectionTestUtils.getField(repository, "hazelcastFlushMode")) assertThat(ReflectionTestUtils.getField(repository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
.isEqualTo(HazelcastFlushMode.IMMEDIATE); }
@Test
void setCustomFlushImmediatelyLegacy() {
registerAndRefresh(BaseConfiguration.class, CustomFlushImmediatelySetLegacyConfiguration.class);
HazelcastSessionRepository repository = this.context.getBean(HazelcastSessionRepository.class);
assertThat(repository).isNotNull();
assertThat(ReflectionTestUtils.getField(repository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
} }
@Test @Test
@@ -256,17 +271,32 @@ class HazelcastHttpSessionConfigurationTests {
static class CustomFlushImmediatelySetConfiguration extends HazelcastHttpSessionConfiguration { static class CustomFlushImmediatelySetConfiguration extends HazelcastHttpSessionConfiguration {
CustomFlushImmediatelySetConfiguration() { CustomFlushImmediatelySetConfiguration() {
setHazelcastFlushMode(HAZELCAST_FLUSH_MODE); setFlushMode(FlushMode.IMMEDIATE);
} }
} }
@Configuration @Configuration
@EnableHazelcastHttpSession(hazelcastFlushMode = HazelcastFlushMode.IMMEDIATE) static class CustomFlushImmediatelySetLegacyConfiguration extends HazelcastHttpSessionConfiguration {
CustomFlushImmediatelySetLegacyConfiguration() {
setHazelcastFlushMode(HazelcastFlushMode.IMMEDIATE);
}
}
@Configuration
@EnableHazelcastHttpSession(flushMode = FlushMode.IMMEDIATE)
static class CustomFlushImmediatelyConfiguration extends BaseConfiguration { static class CustomFlushImmediatelyConfiguration extends BaseConfiguration {
} }
@Configuration
@EnableHazelcastHttpSession(hazelcastFlushMode = HazelcastFlushMode.IMMEDIATE)
static class CustomFlushImmediatelyLegacyConfiguration extends BaseConfiguration {
}
@Configuration @Configuration
@EnableHazelcastHttpSession @EnableHazelcastHttpSession
static class QualifiedHazelcastInstanceConfiguration extends BaseConfiguration { static class QualifiedHazelcastInstanceConfiguration extends BaseConfiguration {