diff --git a/spring-session/src/main/java/org/springframework/session/MapSession.java b/spring-session/src/main/java/org/springframework/session/MapSession.java index 531772f5..9388f067 100644 --- a/spring-session/src/main/java/org/springframework/session/MapSession.java +++ b/spring-session/src/main/java/org/springframework/session/MapSession.java @@ -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. @@ -18,6 +18,7 @@ package org.springframework.session; import java.io.Serializable; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -141,7 +142,7 @@ public final class MapSession implements ExpiringSession, Serializable { } public Set getAttributeNames() { - return this.sessionAttrs.keySet(); + return new HashSet(this.sessionAttrs.keySet()); } public void setAttribute(String attributeName, Object attributeValue) { diff --git a/spring-session/src/test/java/org/springframework/session/MapSessionRepositoryTests.java b/spring-session/src/test/java/org/springframework/session/MapSessionRepositoryTests.java index 0c3bffdd..5a2d1ec7 100644 --- a/spring-session/src/test/java/org/springframework/session/MapSessionRepositoryTests.java +++ b/spring-session/src/test/java/org/springframework/session/MapSessionRepositoryTests.java @@ -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. @@ -64,4 +64,18 @@ public class MapSessionRepositoryTests { assertThat(session.getMaxInactiveIntervalInSeconds()) .isEqualTo(expectedMaxInterval); } + + @Test // gh-1129 + public void getAttributeNamesAndRemove() { + ExpiringSession 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/src/test/java/org/springframework/session/MapSessionTests.java b/spring-session/src/test/java/org/springframework/session/MapSessionTests.java index 3088495a..da072d93 100644 --- a/spring-session/src/test/java/org/springframework/session/MapSessionTests.java +++ b/spring-session/src/test/java/org/springframework/session/MapSessionTests.java @@ -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. @@ -85,6 +85,18 @@ public class MapSessionTests { assertThat(this.session.isExpired(now)).isTrue(); } + @Test // gh-1129 + 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 ExpiringSession { public long getCreationTime() { diff --git a/spring-session/src/test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryTests.java b/spring-session/src/test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryTests.java index af299816..918ee1ce 100644 --- a/spring-session/src/test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryTests.java +++ b/spring-session/src/test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryTests.java @@ -805,6 +805,19 @@ public class RedisOperationsSessionRepositoryTests { this.redisRepository.setRedisFlushMode(null); } + @Test // gh-1129 + 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/src/test/java/org/springframework/session/hazelcast/HazelcastSessionRepositoryTests.java b/spring-session/src/test/java/org/springframework/session/hazelcast/HazelcastSessionRepositoryTests.java index c1de42e3..2cb8e368 100644 --- a/spring-session/src/test/java/org/springframework/session/hazelcast/HazelcastSessionRepositoryTests.java +++ b/spring-session/src/test/java/org/springframework/session/hazelcast/HazelcastSessionRepositoryTests.java @@ -339,4 +339,17 @@ public class HazelcastSessionRepositoryTests { verify(this.sessions, times(1)).values(isA(EqualPredicate.class)); } + @Test // gh-1129 + 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/src/test/java/org/springframework/session/jdbc/JdbcOperationsSessionRepositoryTests.java b/spring-session/src/test/java/org/springframework/session/jdbc/JdbcOperationsSessionRepositoryTests.java index 6a85627d..29b71901 100644 --- a/spring-session/src/test/java/org/springframework/session/jdbc/JdbcOperationsSessionRepositoryTests.java +++ b/spring-session/src/test/java/org/springframework/session/jdbc/JdbcOperationsSessionRepositoryTests.java @@ -525,6 +525,19 @@ public class JdbcOperationsSessionRepositoryTests { verify(this.jdbcOperations, times(1)).update(startsWith("DELETE"), anyLong()); } + @Test // gh-1129 + 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);