diff --git a/samples/javaconfig/webflux/src/main/java/sample/HelloWebfluxSessionConfig.java b/samples/javaconfig/webflux/src/main/java/sample/HelloWebfluxSessionConfig.java index 7cf81ed5..05d211bc 100644 --- a/samples/javaconfig/webflux/src/main/java/sample/HelloWebfluxSessionConfig.java +++ b/samples/javaconfig/webflux/src/main/java/sample/HelloWebfluxSessionConfig.java @@ -16,6 +16,8 @@ package sample; +import java.util.concurrent.ConcurrentHashMap; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.session.EnableSpringWebSession; @@ -29,7 +31,7 @@ public class HelloWebfluxSessionConfig { @Bean public MapReactorSessionRepository reactorSessionRepository() { - return new MapReactorSessionRepository(); + return new MapReactorSessionRepository(new ConcurrentHashMap<>()); } } // end::class[] diff --git a/spring-session-core/src/main/java/org/springframework/session/MapReactorSessionRepository.java b/spring-session-core/src/main/java/org/springframework/session/MapReactorSessionRepository.java index ee9d1976..f02f3058 100644 --- a/spring-session-core/src/main/java/org/springframework/session/MapReactorSessionRepository.java +++ b/spring-session-core/src/main/java/org/springframework/session/MapReactorSessionRepository.java @@ -18,7 +18,6 @@ package org.springframework.session; import java.time.Duration; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import reactor.core.publisher.Mono; @@ -26,10 +25,10 @@ import org.springframework.session.events.SessionDeletedEvent; import org.springframework.session.events.SessionExpiredEvent; /** - * A {@link SessionRepository} backed by a {@link Map} and that uses a - * {@link MapSession}. By default a {@link ConcurrentHashMap} is - * used, but a custom {@link Map} can be injected to use distributed maps - * provided by NoSQL stores like Redis and Hazelcast. + * A {@link ReactorSessionRepository} backed by a {@link Map} and that uses a + * {@link MapSession}. The injected {@link java.util.Map} can be backed by a distributed + * NoSQL store like Hazelcast, for instance. Note that the supplied map itself is + * responsible for purging the expired sessions. * *

* The implementation does NOT support firing {@link SessionDeletedEvent} or @@ -40,6 +39,7 @@ import org.springframework.session.events.SessionExpiredEvent; * @since 2.0 */ public class MapReactorSessionRepository implements ReactorSessionRepository { + /** * If non-null, this value is used to override * {@link Session#setMaxInactiveInterval(Duration)}. @@ -49,15 +49,8 @@ public class MapReactorSessionRepository implements ReactorSessionRepository sessions; /** - * Creates an instance backed by a {@link ConcurrentHashMap}. - */ - public MapReactorSessionRepository() { - this(new ConcurrentHashMap<>()); - } - - /** - * Creates a new instance backed by the provided {@link Map}. This allows - * injecting a distributed {@link Map}. + * Creates a new instance backed by the provided {@link Map}. This allows injecting a + * distributed {@link Map}. * * @param sessions the {@link Map} to use. Cannot be null. */ @@ -68,38 +61,6 @@ public class MapReactorSessionRepository implements ReactorSessionRepository(); - for (Session session : sessions) { - this.performSave(new MapSession(session)); - } - } - - /** - * Creates a new instance backed by the provided {@link Map}. This allows - * injecting a distributed {@link Map}. - * - * @param sessions the {@link Map} to use. Cannot be null. - */ - public MapReactorSessionRepository(Iterable sessions) { - if (sessions == null) { - throw new IllegalArgumentException("sessions cannot be null"); - } - this.sessions = new ConcurrentHashMap<>(); - for (Session session : sessions) { - this.performSave(new MapSession(session)); - } - } - /** * If non-null, this value is used to override * {@link Session#setMaxInactiveInterval(Duration)}. @@ -111,22 +72,22 @@ public class MapReactorSessionRepository implements ReactorSessionRepository save(MapSession session) { - return Mono.fromRunnable(() -> performSave(session)); - } - - private void performSave(MapSession session) { - if (!session.getId().equals(session.getOriginalId())) { - this.sessions.remove(session.getOriginalId()); - session.setOriginalId(session.getId()); - } - this.sessions.put(session.getId(), new MapSession(session)); + return Mono.fromRunnable(() -> { + if (!session.getId().equals(session.getOriginalId())) { + this.sessions.remove(session.getOriginalId()); + session.setOriginalId(session.getId()); + } + this.sessions.put(session.getId(), new MapSession(session)); + }); } public Mono findById(String id) { + // @formatter:off return Mono.defer(() -> Mono.justOrEmpty(this.sessions.get(id)) - .filter(session -> !session.isExpired()) - .map(MapSession::new) - .switchIfEmpty(delete(id).then(Mono.empty()))); + .filter(session -> !session.isExpired()) + .map(MapSession::new) + .switchIfEmpty(delete(id).then(Mono.empty()))); + // @formatter:on } public Mono delete(String id) { @@ -143,4 +104,5 @@ public class MapReactorSessionRepository implements ReactorSessionRepository()); this.session = new MapSession("session-id"); } - @Test - public void constructorVarargsThenFound() { - this.repository = new MapReactorSessionRepository(this.session); - - Session findByIdSession = this.repository.findById(this.session.getId()).block(); - assertThat(findByIdSession).isNotNull(); - assertThat(findByIdSession.getId()).isEqualTo(this.session.getId()); - } - - @Test(expected = IllegalArgumentException.class) - public void constructorVarargsWhenNullThenThrowsIllegalArgumentException() { - Session[] sessions = null; - new MapReactorSessionRepository(sessions); - } - - @Test - public void constructorIterableThenFound() { - this.repository = new MapReactorSessionRepository(Arrays.asList(this.session)); - - Session findByIdSession = this.repository.findById(this.session.getId()).block(); - assertThat(findByIdSession).isNotNull(); - assertThat(findByIdSession.getId()).isEqualTo(this.session.getId()); - } - - @Test(expected = IllegalArgumentException.class) - public void constructorIterableWhenNullThenThrowsIllegalArgumentException() { - Iterable sessions = null; - new MapReactorSessionRepository(sessions); - } - @Test public void constructorMapThenFound() { Map sessions = new HashMap<>(); @@ -108,24 +79,6 @@ public class MapReactorSessionRepositoryTests { assertThat(findByIdSession.getId()).isEqualTo(this.session.getId()); } - @Test - public void findByIdWhenNotExpiredThenFound() { - this.repository = new MapReactorSessionRepository(this.session); - - Session findByIdSession = this.repository.findById(this.session.getId()).block(); - assertThat(findByIdSession).isNotNull(); - assertThat(findByIdSession.getId()).isEqualTo(this.session.getId()); - } - - @Test - public void findByIdWhenExpiredThenEmpty() { - this.session.setMaxInactiveInterval(Duration.ofSeconds(1)); - this.session.setLastAccessedTime(Instant.now().minus(5, ChronoUnit.MINUTES)); - this.repository = new MapReactorSessionRepository(Arrays.asList(this.session)); - - assertThat(this.repository.findById(this.session.getId()).block()).isNull(); - } - @Test public void findByIdWhenExpiredRemovesFromSessionMap() { this.session.setMaxInactiveInterval(Duration.ofMinutes(1)); @@ -188,4 +141,5 @@ public class MapReactorSessionRepositoryTests { assertThat(this.repository.findById(originalId).block()).isNull(); assertThat(this.repository.findById(createSession.getId()).block()).isNotNull(); } + } diff --git a/spring-session-core/src/test/java/org/springframework/session/SpringWebSessionConfigurationTests.java b/spring-session-core/src/test/java/org/springframework/session/SpringWebSessionConfigurationTests.java index 976e65ca..4ed447dd 100644 --- a/spring-session-core/src/test/java/org/springframework/session/SpringWebSessionConfigurationTests.java +++ b/spring-session-core/src/test/java/org/springframework/session/SpringWebSessionConfigurationTests.java @@ -13,8 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.session; +import java.util.HashMap; + import org.junit.After; import org.junit.Test; @@ -108,7 +111,7 @@ public class SpringWebSessionConfigurationTests { */ @Bean ReactorSessionRepository reactorSessionRepository() { - return new MapReactorSessionRepository(); + return new MapReactorSessionRepository(new HashMap<>()); } } @@ -125,7 +128,7 @@ public class SpringWebSessionConfigurationTests { @Bean ReactorSessionRepository reactorSessionRepository() { - return new MapReactorSessionRepository(); + return new MapReactorSessionRepository(new HashMap<>()); } @Bean @@ -133,4 +136,5 @@ public class SpringWebSessionConfigurationTests { return new HeaderWebSessionIdResolver(); } } + }