diff --git a/spring-session-core/src/main/java/org/springframework/session/MapSession.java b/spring-session-core/src/main/java/org/springframework/session/MapSession.java index ddbeecbc..bcfee250 100644 --- a/spring-session-core/src/main/java/org/springframework/session/MapSession.java +++ b/spring-session-core/src/main/java/org/springframework/session/MapSession.java @@ -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,6 +20,7 @@ import java.io.Serializable; import java.time.Duration; import java.time.Instant; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -177,7 +178,7 @@ public final class MapSession implements Session, Serializable { @Override public Set getAttributeNames() { - return this.sessionAttrs.keySet(); + return new HashSet<>(this.sessionAttrs.keySet()); } @Override diff --git a/spring-session-core/src/test/java/org/springframework/session/MapSessionRepositoryTests.java b/spring-session-core/src/test/java/org/springframework/session/MapSessionRepositoryTests.java index a7be916a..8faa8a27 100644 --- a/spring-session-core/src/test/java/org/springframework/session/MapSessionRepositoryTests.java +++ b/spring-session-core/src/test/java/org/springframework/session/MapSessionRepositoryTests.java @@ -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. @@ -100,4 +100,17 @@ public class MapSessionRepositoryTests { assertThat(this.repository.findById(createSession.getId())).isNotNull(); } + @Test // gh-1120 + public void getAttributeNamesAndRemove() { + MapSession session = this.repository.createSession(); + session.setAttribute("attribute1", "value1"); + session.setAttribute("attribute2", "value2"); + + for (String attributeName : session.getAttributeNames()) { + session.removeAttribute(attributeName); + } + + assertThat(session.getAttributeNames()).isEmpty(); + } + } diff --git a/spring-session-core/src/test/java/org/springframework/session/MapSessionTests.java b/spring-session-core/src/test/java/org/springframework/session/MapSessionTests.java index b7b0e7e9..d46bb0f7 100644 --- a/spring-session-core/src/test/java/org/springframework/session/MapSessionTests.java +++ b/spring-session-core/src/test/java/org/springframework/session/MapSessionTests.java @@ -133,6 +133,18 @@ public class MapSessionTests { assertThat(this.session.isExpired(now)).isTrue(); } + @Test // gh-1120 + public void getAttributeNamesAndRemove() { + this.session.setAttribute("attribute1", "value1"); + this.session.setAttribute("attribute2", "value2"); + + for (String attributeName : this.session.getAttributeNames()) { + this.session.removeAttribute(attributeName); + } + + assertThat(this.session.getAttributeNames()).isEmpty(); + } + static class CustomSession implements Session { @Override diff --git a/spring-session-core/src/test/java/org/springframework/session/ReactiveMapSessionRepositoryTests.java b/spring-session-core/src/test/java/org/springframework/session/ReactiveMapSessionRepositoryTests.java index 633c4504..9c7bac19 100644 --- a/spring-session-core/src/test/java/org/springframework/session/ReactiveMapSessionRepositoryTests.java +++ b/spring-session-core/src/test/java/org/springframework/session/ReactiveMapSessionRepositoryTests.java @@ -144,4 +144,17 @@ public class ReactiveMapSessionRepositoryTests { assertThat(this.repository.findById(createSession.getId()).block()).isNotNull(); } + @Test // gh-1120 + public void getAttributeNamesAndRemove() { + MapSession session = this.repository.createSession().block(); + session.setAttribute("attribute1", "value1"); + session.setAttribute("attribute2", "value2"); + + for (String attributeName : session.getAttributeNames()) { + session.removeAttribute(attributeName); + } + + assertThat(session.getAttributeNames()).isEmpty(); + } + } diff --git a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/ReactiveRedisOperationsSessionRepositoryTests.java b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/ReactiveRedisOperationsSessionRepositoryTests.java index 11a1702f..4480182b 100644 --- a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/ReactiveRedisOperationsSessionRepositoryTests.java +++ b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/ReactiveRedisOperationsSessionRepositoryTests.java @@ -367,6 +367,19 @@ public class ReactiveRedisOperationsSessionRepositoryTests { verifyZeroInteractions(this.hashOperations); } + @Test // gh-1120 + public void getAttributeNamesAndRemove() { + RedisSession session = this.repository.new RedisSession(this.cached); + session.setAttribute("attribute1", "value1"); + session.setAttribute("attribute2", "value2"); + + for (String attributeName : session.getAttributeNames()) { + session.removeAttribute(attributeName); + } + + assertThat(session.getAttributeNames()).isEmpty(); + } + private Map map(Object... objects) { Map result = new HashMap<>(); if (objects == null) { diff --git a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryTests.java b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryTests.java index 039ea37e..3730d497 100644 --- a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryTests.java +++ b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryTests.java @@ -868,6 +868,19 @@ public class RedisOperationsSessionRepositoryTests { .hasMessage("namespace cannot be null or empty"); } + @Test // gh-1120 + public void getAttributeNamesAndRemove() { + RedisSession session = this.redisRepository.new RedisSession(this.cached); + session.setAttribute("attribute1", "value1"); + session.setAttribute("attribute2", "value2"); + + for (String attributeName : session.getAttributeNames()) { + session.removeAttribute(attributeName); + } + + assertThat(session.getAttributeNames()).isEmpty(); + } + private String getKey(String id) { return "spring:session:sessions:" + id; } diff --git a/spring-session-hazelcast/src/test/java/org/springframework/session/hazelcast/HazelcastSessionRepositoryTests.java b/spring-session-hazelcast/src/test/java/org/springframework/session/hazelcast/HazelcastSessionRepositoryTests.java index f0ba72f8..9798047e 100644 --- a/spring-session-hazelcast/src/test/java/org/springframework/session/hazelcast/HazelcastSessionRepositoryTests.java +++ b/spring-session-hazelcast/src/test/java/org/springframework/session/hazelcast/HazelcastSessionRepositoryTests.java @@ -418,4 +418,17 @@ public class HazelcastSessionRepositoryTests { verifyZeroInteractions(this.sessions); } + @Test // gh-1120 + public void getAttributeNamesAndRemove() { + HazelcastSession session = this.repository.createSession(); + session.setAttribute("attribute1", "value1"); + session.setAttribute("attribute2", "value2"); + + for (String attributeName : session.getAttributeNames()) { + session.removeAttribute(attributeName); + } + + assertThat(session.getAttributeNames()).isEmpty(); + } + } diff --git a/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/JdbcOperationsSessionRepositoryTests.java b/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/JdbcOperationsSessionRepositoryTests.java index 557879fe..9a41c4ef 100644 --- a/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/JdbcOperationsSessionRepositoryTests.java +++ b/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/JdbcOperationsSessionRepositoryTests.java @@ -675,6 +675,19 @@ public class JdbcOperationsSessionRepositoryTests { verify(this.jdbcOperations, times(1)).update(startsWith("DELETE"), anyLong()); } + @Test // gh-1120 + public void getAttributeNamesAndRemove() { + JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession(); + session.setAttribute("attribute1", "value1"); + session.setAttribute("attribute2", "value2"); + + for (String attributeName : session.getAttributeNames()) { + session.removeAttribute(attributeName); + } + + assertThat(session.getAttributeNames()).isEmpty(); + } + private void assertPropagationRequiresNew() { ArgumentCaptor argument = ArgumentCaptor.forClass(TransactionDefinition.class);