Remove MapReactorSessionRepository default constructor

This commit removes the default `MapReactorSessionRepository` so that the users are required to explicitly supply the `Map` used to store the sessions.
This commit is contained in:
Vedran Pavic
2017-09-10 19:39:46 +02:00
committed by Rob Winch
parent b72c600884
commit 1e46630467
4 changed files with 35 additions and 113 deletions

View File

@@ -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[]

View File

@@ -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.
*
* <p>
* 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<MapSession> {
/**
* If non-null, this value is used to override
* {@link Session#setMaxInactiveInterval(Duration)}.
@@ -49,15 +49,8 @@ public class MapReactorSessionRepository implements ReactorSessionRepository<Map
private final Map<String, Session> 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<Map
this.sessions = sessions;
}
/**
* 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(Session... sessions) {
if (sessions == null) {
throw new IllegalArgumentException("sessions cannot be null");
}
this.sessions = new ConcurrentHashMap<>();
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<Session> 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<Map
}
public Mono<Void> 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<MapSession> 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<Void> delete(String id) {
@@ -143,4 +104,5 @@ public class MapReactorSessionRepository implements ReactorSessionRepository<Map
return Mono.just(result);
});
}
}

View File

@@ -19,7 +19,6 @@ package org.springframework.session;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -30,51 +29,23 @@ import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MapReactorSessionRepository}.
*
* @author Rob Winch
* @since 2.0
*/
public class MapReactorSessionRepositoryTests {
MapReactorSessionRepository repository;
private MapReactorSessionRepository repository;
MapSession session;
private MapSession session;
@Before
public void setup() {
this.repository = new MapReactorSessionRepository();
this.repository = new MapReactorSessionRepository(new HashMap<>());
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<Session> sessions = null;
new MapReactorSessionRepository(sessions);
}
@Test
public void constructorMapThenFound() {
Map<String, Session> 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();
}
}

View File

@@ -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();
}
}
}