diff --git a/spring-session-data-redis/src/integration-test/java/org/springframework/session/data/redis/RedisIndexedSessionRepositoryITests.java b/spring-session-data-redis/src/integration-test/java/org/springframework/session/data/redis/RedisIndexedSessionRepositoryITests.java index a649148f..4fcf13d9 100644 --- a/spring-session-data-redis/src/integration-test/java/org/springframework/session/data/redis/RedisIndexedSessionRepositoryITests.java +++ b/spring-session-data-redis/src/integration-test/java/org/springframework/session/data/redis/RedisIndexedSessionRepositoryITests.java @@ -18,6 +18,7 @@ package org.springframework.session.data.redis; import java.nio.charset.StandardCharsets; import java.util.Map; +import java.util.Set; import java.util.UUID; import org.junit.jupiter.api.BeforeEach; @@ -134,6 +135,22 @@ class RedisIndexedSessionRepositoryITests extends AbstractRedisITests { .isEqualTo(expectedAttributeValue); } + @Test + void removeAttributeRemovedAttributeKey() { + RedisSession toSave = this.repository.createSession(); + toSave.setAttribute("a", "b"); + this.repository.save(toSave); + + toSave.removeAttribute("a"); + this.repository.save(toSave); + + String id = toSave.getId(); + String key = "RedisIndexedSessionRepositoryITests:sessions:" + id; + + Set> entries = this.redis.boundHashOps(key).entries().entrySet(); + assertThat(entries).extracting(Map.Entry::getKey).doesNotContain("sessionAttr:a"); + } + @Test void putAllOnSingleAttrDoesNotRemoveOld() { RedisSession toSave = this.repository.createSession(); diff --git a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisIndexedSessionRepository.java b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisIndexedSessionRepository.java index 126316d0..c30790e3 100644 --- a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisIndexedSessionRepository.java +++ b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisIndexedSessionRepository.java @@ -792,7 +792,8 @@ public class RedisIndexedSessionRepository return; } String sessionId = getId(); - getSessionBoundHashOperations(sessionId).putAll(this.delta); + BoundHashOperations boundHashOperations = getSessionBoundHashOperations(sessionId); + boundHashOperations.putAll(this.delta); String principalSessionKey = getSessionAttrNameKey( FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME); String securityPrincipalSessionKey = getSessionAttrNameKey(SPRING_SECURITY_CONTEXT); @@ -811,6 +812,11 @@ public class RedisIndexedSessionRepository .add(sessionId); } } + for (final Map.Entry attribute : this.delta.entrySet()) { + if (attribute.getValue() == null) { + boundHashOperations.delete(attribute.getKey()); + } + } this.delta = new HashMap<>(this.delta.size());