DefaultWebSessionManager decoupled from DefaultWebSession
DefaultWebSessionManager no longer requires the WebSessionStore to use DefaultWebSession. Removed explicit start() in save(). This seemed unnecessary since at that point isStarted is guaranteed to return true. The status can be updated through the copy constructor. DefaultWebSessionTests added. Issue: SPR-15875
This commit is contained in:
committed by
Rossen Stoyanchev
parent
86912475af
commit
8ad14ae95c
@@ -15,10 +15,6 @@
|
||||
*/
|
||||
package org.springframework.web.server.session;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -32,8 +28,6 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.util.IdGenerator;
|
||||
import org.springframework.util.JdkIdGenerator;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebSession;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
@@ -42,11 +36,11 @@ import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
@@ -57,11 +51,6 @@ import static org.mockito.Mockito.when;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DefaultWebSessionManagerTests {
|
||||
|
||||
private static final Clock CLOCK = Clock.system(ZoneId.of("GMT"));
|
||||
|
||||
private static final IdGenerator idGenerator = new JdkIdGenerator();
|
||||
|
||||
|
||||
private DefaultWebSessionManager manager;
|
||||
|
||||
private ServerWebExchange exchange;
|
||||
@@ -72,10 +61,23 @@ public class DefaultWebSessionManagerTests {
|
||||
@Mock
|
||||
private WebSessionStore store;
|
||||
|
||||
@Mock
|
||||
private WebSession createSession;
|
||||
|
||||
@Mock
|
||||
private WebSession retrieveSession;
|
||||
|
||||
@Mock
|
||||
private WebSession updateSession;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
when(this.store.createWebSession()).thenReturn(Mono.just(createDefaultWebSession()));
|
||||
when(this.store.updateLastAccessTime(any())).thenAnswer( invocation -> Mono.just(invocation.getArgument(0)));
|
||||
when(this.store.createWebSession()).thenReturn(Mono.just(this.createSession));
|
||||
when(this.store.updateLastAccessTime(any())).thenReturn(Mono.just(this.updateSession));
|
||||
when(this.store.retrieveSession(any())).thenReturn(Mono.just(this.retrieveSession));
|
||||
when(this.createSession.save()).thenReturn(Mono.empty());
|
||||
when(this.updateSession.getId()).thenReturn("update-session-id");
|
||||
when(this.retrieveSession.getId()).thenReturn("retrieve-session-id");
|
||||
|
||||
this.manager = new DefaultWebSessionManager();
|
||||
this.manager.setSessionIdResolver(this.idResolver);
|
||||
@@ -87,90 +89,71 @@ public class DefaultWebSessionManagerTests {
|
||||
ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getSessionWithoutStarting() throws Exception {
|
||||
public void getSessionSaveWhenCreatedAndNotStartedThenNotSaved() throws Exception {
|
||||
when(this.idResolver.resolveSessionIds(this.exchange)).thenReturn(Collections.emptyList());
|
||||
WebSession session = this.manager.getSession(this.exchange).block();
|
||||
session.save().block();
|
||||
this.exchange.getResponse().setComplete().block();
|
||||
|
||||
assertFalse(session.isStarted());
|
||||
assertFalse(session.isExpired());
|
||||
verify(this.store, never()).storeSession(any());
|
||||
verifyZeroInteractions(this.retrieveSession, this.updateSession);
|
||||
verify(this.createSession, never()).save();
|
||||
verify(this.idResolver, never()).setSessionId(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startSessionExplicitly() throws Exception {
|
||||
public void getSessionSaveWhenCreatedAndStartedThenSavesAndSetsId() throws Exception {
|
||||
when(this.idResolver.resolveSessionIds(this.exchange)).thenReturn(Collections.emptyList());
|
||||
when(this.store.storeSession(any())).thenReturn(Mono.empty());
|
||||
WebSession session = this.manager.getSession(this.exchange).block();
|
||||
session.start();
|
||||
session.save().block();
|
||||
when(this.createSession.isStarted()).thenReturn(true);
|
||||
this.exchange.getResponse().setComplete().block();
|
||||
|
||||
String id = session.getId();
|
||||
verify(this.store).createWebSession();
|
||||
verify(this.store).storeSession(any());
|
||||
verify(this.createSession).save();
|
||||
verify(this.idResolver).setSessionId(any(), eq(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startSessionImplicitly() throws Exception {
|
||||
when(this.idResolver.resolveSessionIds(this.exchange)).thenReturn(Collections.emptyList());
|
||||
when(this.store.storeSession(any())).thenReturn(Mono.empty());
|
||||
WebSession session = this.manager.getSession(this.exchange).block();
|
||||
session.getAttributes().put("foo", "bar");
|
||||
session.save().block();
|
||||
|
||||
verify(this.store).createWebSession();
|
||||
verify(this.idResolver).setSessionId(any(), any());
|
||||
verify(this.store).storeSession(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exchangeWhenResponseSetCompleteThenSavesAndSetsId() throws Exception {
|
||||
when(this.idResolver.resolveSessionIds(this.exchange)).thenReturn(Collections.emptyList());
|
||||
when(this.store.storeSession(any())).thenReturn(Mono.empty());
|
||||
String id = this.createSession.getId();
|
||||
WebSession session = this.manager.getSession(this.exchange).block();
|
||||
String id = session.getId();
|
||||
session.getAttributes().put("foo", "bar");
|
||||
when(this.createSession.isStarted()).thenReturn(true);
|
||||
this.exchange.getResponse().setComplete().block();
|
||||
|
||||
verify(this.idResolver).setSessionId(any(), eq(id));
|
||||
verify(this.store).storeSession(any());
|
||||
verify(this.createSession).save();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existingSession() throws Exception {
|
||||
DefaultWebSession existing = createDefaultWebSession();
|
||||
String id = existing.getId();
|
||||
when(this.store.retrieveSession(id)).thenReturn(Mono.just(existing));
|
||||
String id = this.updateSession.getId();
|
||||
when(this.store.retrieveSession(id)).thenReturn(Mono.just(this.updateSession));
|
||||
when(this.idResolver.resolveSessionIds(this.exchange)).thenReturn(Collections.singletonList(id));
|
||||
|
||||
WebSession actual = this.manager.getSession(this.exchange).block();
|
||||
assertNotNull(actual);
|
||||
assertEquals(existing.getId(), actual.getId());
|
||||
assertEquals(id, actual.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existingSessionIsExpired() throws Exception {
|
||||
DefaultWebSession existing = createDefaultWebSession();
|
||||
existing.start();
|
||||
Instant lastAccessTime = Instant.now(CLOCK).minus(Duration.ofMinutes(31));
|
||||
existing = new DefaultWebSession(existing, lastAccessTime, s -> Mono.empty());
|
||||
when(this.store.retrieveSession(existing.getId())).thenReturn(Mono.just(existing));
|
||||
when(this.store.removeSession(existing.getId())).thenReturn(Mono.empty());
|
||||
when(this.idResolver.resolveSessionIds(this.exchange)).thenReturn(Collections.singletonList(existing.getId()));
|
||||
String id = this.retrieveSession.getId();
|
||||
when(this.retrieveSession.isExpired()).thenReturn(true);
|
||||
when(this.idResolver.resolveSessionIds(this.exchange)).thenReturn(Collections.singletonList(id));
|
||||
when(this.store.removeSession(any())).thenReturn(Mono.empty());
|
||||
|
||||
WebSession actual = this.manager.getSession(this.exchange).block();
|
||||
assertNotSame(existing, actual);
|
||||
verify(this.store).removeSession(existing.getId());
|
||||
assertEquals(this.createSession.getId(), actual.getId());
|
||||
verify(this.store).removeSession(id);
|
||||
verify(this.idResolver).expireSession(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleSessionIds() throws Exception {
|
||||
DefaultWebSession existing = createDefaultWebSession();
|
||||
WebSession existing = this.updateSession;
|
||||
String id = existing.getId();
|
||||
when(this.store.retrieveSession(any())).thenReturn(Mono.empty());
|
||||
when(this.store.retrieveSession(id)).thenReturn(Mono.just(existing));
|
||||
@@ -180,8 +163,4 @@ public class DefaultWebSessionManagerTests {
|
||||
assertNotNull(actual);
|
||||
assertEquals(existing.getId(), actual.getId());
|
||||
}
|
||||
|
||||
private DefaultWebSession createDefaultWebSession() {
|
||||
return new DefaultWebSession(idGenerator, CLOCK, (s, session) -> Mono.empty(), s -> Mono.empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.web.server.session;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.util.IdGenerator;
|
||||
import org.springframework.util.JdkIdGenerator;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.ZoneId;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public class DefaultWebSessionTests {
|
||||
private static final Clock CLOCK = Clock.system(ZoneId.of("GMT"));
|
||||
|
||||
private static final IdGenerator idGenerator = new JdkIdGenerator();
|
||||
|
||||
@Test
|
||||
public void constructorWhenImplicitStartCopiedThenCopyIsStarted() {
|
||||
DefaultWebSession original = createDefaultWebSession();
|
||||
original.getAttributes().put("foo", "bar");
|
||||
|
||||
DefaultWebSession copy = new DefaultWebSession(original, CLOCK.instant());
|
||||
|
||||
assertTrue(copy.isStarted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenExplicitStartCopiedThenCopyIsStarted() {
|
||||
DefaultWebSession original = createDefaultWebSession();
|
||||
original.start();
|
||||
|
||||
DefaultWebSession copy = new DefaultWebSession(original, CLOCK.instant());
|
||||
|
||||
assertTrue(copy.isStarted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startsSessionExplicitly() {
|
||||
DefaultWebSession session = createDefaultWebSession();
|
||||
session.start();
|
||||
assertTrue(session.isStarted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startsSessionImplicitly() {
|
||||
DefaultWebSession session = createDefaultWebSession();
|
||||
session.getAttributes().put("foo", "bar");
|
||||
assertTrue(session.isStarted());
|
||||
}
|
||||
|
||||
private DefaultWebSession createDefaultWebSession() {
|
||||
return new DefaultWebSession(idGenerator, CLOCK, (s, session) -> Mono.empty(), s -> Mono.empty());
|
||||
}
|
||||
}
|
||||
@@ -110,10 +110,10 @@ public class WebSessionIntegrationTests extends AbstractHttpHandlerIntegrationTe
|
||||
assertEquals(2, this.handler.getSessionRequestCount());
|
||||
|
||||
// Now set the clock of the session back by 31 minutes
|
||||
WebSessionStore store = this.sessionManager.getSessionStore();
|
||||
InMemoryWebSessionStore store = (InMemoryWebSessionStore) this.sessionManager.getSessionStore();
|
||||
DefaultWebSession session = (DefaultWebSession) store.retrieveSession(id).block();
|
||||
assertNotNull(session);
|
||||
Instant lastAccessTime = Clock.offset(this.sessionManager.getClock(), Duration.ofMinutes(-31)).instant();
|
||||
Instant lastAccessTime = Clock.offset(store.getClock(), Duration.ofMinutes(-31)).instant();
|
||||
session = new DefaultWebSession(session, lastAccessTime);
|
||||
session.save().block();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user