From 903017285b4b126df2ba40f97482b64e662e0ea6 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Wed, 30 Jul 2014 11:56:43 -0500 Subject: [PATCH] Create ExpiringSession which extends Session This provides a better separation for consumers of the API. Most users are likely not interested in checking to see if a session is expired so they can focus on the Session API. Fixes #28 --- README.adoc | 6 +-- samples/web/src/main/java/Config.java | 3 +- ...edisOperationsSessionRepositoryITests.java | 7 ++-- .../session/ExpiringSession.java | 39 +++++++++++++++++++ .../springframework/session/MapSession.java | 4 +- .../session/MapSessionRepository.java | 16 ++++---- .../org/springframework/session/Session.java | 28 ------------- .../RedisOperationsSessionRepository.java | 13 ++++--- .../web/http/SessionRepositoryFilter.java | 7 ++-- .../session/MapSessionTests.java | 2 +- ...RedisOperationsSessionRepositoryTests.java | 7 ++-- 11 files changed, 73 insertions(+), 59 deletions(-) create mode 100644 spring-session/src/main/java/org/springframework/session/ExpiringSession.java diff --git a/README.adoc b/README.adoc index a162a62..4a38dab 100644 --- a/README.adoc +++ b/README.adoc @@ -189,8 +189,8 @@ public class Config { } @Bean - public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { - RedisTemplate template = new RedisTemplate(); + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setConnectionFactory(connectionFactory); @@ -198,7 +198,7 @@ public class Config { } @Bean - public RedisOperationsSessionRepository sessionRepository(RedisTemplate redisTemplate) { + public RedisOperationsSessionRepository sessionRepository(RedisTemplate redisTemplate) { return new RedisOperationsSessionRepository(redisTemplate); } diff --git a/samples/web/src/main/java/Config.java b/samples/web/src/main/java/Config.java index 25f569a..8f02a5c 100644 --- a/samples/web/src/main/java/Config.java +++ b/samples/web/src/main/java/Config.java @@ -22,6 +22,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.session.ExpiringSession; import org.springframework.session.Session; import org.springframework.session.data.redis.RedisOperationsSessionRepository; import org.springframework.session.web.http.SessionRepositoryFilter; @@ -72,7 +73,7 @@ public class Config { } @Bean - public RedisOperationsSessionRepository sessionRepository(RedisTemplate redisTemplate) { + public RedisOperationsSessionRepository sessionRepository(RedisTemplate redisTemplate) { return new RedisOperationsSessionRepository(redisTemplate); } diff --git a/spring-session/src/integration-test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryITests.java b/spring-session/src/integration-test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryITests.java index 58b4a23..e356162 100644 --- a/spring-session/src/integration-test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryITests.java +++ b/spring-session/src/integration-test/java/org/springframework/session/data/redis/RedisOperationsSessionRepositoryITests.java @@ -18,6 +18,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.session.ExpiringSession; import org.springframework.session.Session; import org.springframework.session.SessionRepository; import org.springframework.test.context.ContextConfiguration; @@ -100,8 +101,8 @@ public class RedisOperationsSessionRepositoryITests { } @Bean - public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { - RedisTemplate template = new RedisTemplate(); + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setConnectionFactory(connectionFactory); @@ -109,7 +110,7 @@ public class RedisOperationsSessionRepositoryITests { } @Bean - public RedisOperationsSessionRepository sessionRepository(RedisTemplate redisTemplate) { + public RedisOperationsSessionRepository sessionRepository(RedisTemplate redisTemplate) { return new RedisOperationsSessionRepository(redisTemplate); } } diff --git a/spring-session/src/main/java/org/springframework/session/ExpiringSession.java b/spring-session/src/main/java/org/springframework/session/ExpiringSession.java new file mode 100644 index 0000000..962029c --- /dev/null +++ b/spring-session/src/main/java/org/springframework/session/ExpiringSession.java @@ -0,0 +1,39 @@ +package org.springframework.session; + +/** + * A {@link Session} that contains additional attributes that are useful for determining if a session is expired. + * + * @since 1.0 + * @author Rob Winch + */ +public interface ExpiringSession extends Session { + + /** + * Gets the time when this session was created in milliseconds since midnight of 1/1/1970 GMT. + * + * @return the time when this session was created in milliseconds since midnight of 1/1/1970 GMT. + */ + long getCreationTime(); + + /** + * Gets the last time this {@link Session} was accessed expressed in milliseconds since midnight of 1/1/1970 GMT + * + * @return the last time the client sent a request associated with the session expressed in milliseconds since midnight of 1/1/1970 GMT + */ + long getLastAccessedTime(); + + /** + * Sets the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout. + * + * @param interval the number of seconds that the {@link Session} should be kept alive between client requests. + */ + void setMaxInactiveInterval(int interval); + + /** + * Gets the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout. + * + * @return the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout. + */ + int getMaxInactiveInterval(); + +} 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 ab95cc3..d7fc659 100644 --- a/spring-session/src/main/java/org/springframework/session/MapSession.java +++ b/spring-session/src/main/java/org/springframework/session/MapSession.java @@ -40,7 +40,7 @@ import java.util.UUID; * @since 1.0 * @author Rob Winch */ -public final class MapSession implements Session { +public final class MapSession implements ExpiringSession { /** * Default {@link #setMaxInactiveInterval(int)} (30 minutes) */ @@ -67,7 +67,7 @@ public final class MapSession implements Session { * * @param session the {@link Session} to initialize this {@link Session} with. Cannot be null. */ - public MapSession(Session session) { + public MapSession(ExpiringSession session) { Assert.notNull(session, "session cannot be null"); this.id = session.getId(); this.sessionAttrs = new HashMap(session.getAttributeNames().size()); diff --git a/spring-session/src/main/java/org/springframework/session/MapSessionRepository.java b/spring-session/src/main/java/org/springframework/session/MapSessionRepository.java index 280d39b..6c3d982 100644 --- a/spring-session/src/main/java/org/springframework/session/MapSessionRepository.java +++ b/spring-session/src/main/java/org/springframework/session/MapSessionRepository.java @@ -28,14 +28,14 @@ import java.util.concurrent.ConcurrentHashMap; * @author Rob Winch * @since 1.0 */ -public class MapSessionRepository implements SessionRepository { - private final Map sessions; +public class MapSessionRepository implements SessionRepository { + private final Map sessions; /** * Creates an instance backed by a {@link java.util.concurrent.ConcurrentHashMap} */ public MapSessionRepository() { - this(new ConcurrentHashMap()); + this(new ConcurrentHashMap()); } /** @@ -43,17 +43,17 @@ public class MapSessionRepository implements SessionRepository { * * @param sessions the {@link java.util.Map} to use. Cannot be null. */ - public MapSessionRepository(Map sessions) { + public MapSessionRepository(Map sessions) { Assert.notNull(sessions, "sessions cannot be null"); this.sessions = sessions; } - public void save(Session session) { + public void save(ExpiringSession session) { sessions.put(session.getId(), new MapSession(session)); } - public Session getSession(String id) { - Session saved = sessions.get(id); + public ExpiringSession getSession(String id) { + ExpiringSession saved = sessions.get(id); if(saved == null) { return null; } @@ -66,7 +66,7 @@ public class MapSessionRepository implements SessionRepository { sessions.remove(id); } - public Session createSession() { + public ExpiringSession createSession() { return new MapSession(); } } diff --git a/spring-session/src/main/java/org/springframework/session/Session.java b/spring-session/src/main/java/org/springframework/session/Session.java index 7feaa89..ed97243 100644 --- a/spring-session/src/main/java/org/springframework/session/Session.java +++ b/spring-session/src/main/java/org/springframework/session/Session.java @@ -27,13 +27,6 @@ import java.util.Set; */ public interface Session { - /** - * Gets the time when this session was created in milliseconds since midnight of 1/1/1970 GMT. - * - * @return the time when this session was created in milliseconds since midnight of 1/1/1970 GMT. - */ - long getCreationTime(); - /** * Gets a unique string that identifies the {@link Session} * @@ -41,27 +34,6 @@ public interface Session { */ String getId(); - /** - * Gets the last time this {@link Session} was accessed expressed in milliseconds since midnight of 1/1/1970 GMT - * - * @return the last time the client sent a request associated with the session expressed in milliseconds since midnight of 1/1/1970 GMT - */ - long getLastAccessedTime(); - - /** - * Sets the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout. - * - * @param interval the number of seconds that the {@link Session} should be kept alive between client requests. - */ - void setMaxInactiveInterval(int interval); - - /** - * Gets the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout. - * - * @return the maximum inactive interval in seconds between requests before this session will be invalidated. A negative time indicates that the session will never timeout. - */ - int getMaxInactiveInterval(); - /** * Gets the Object associated with the specified name or null if no Object is associated to that name. * diff --git a/spring-session/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java b/spring-session/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java index 5820022..2ebb226 100644 --- a/spring-session/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java +++ b/spring-session/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java @@ -17,6 +17,7 @@ package org.springframework.session.data.redis; import org.springframework.data.redis.core.BoundHashOperations; import org.springframework.data.redis.core.RedisOperations; +import org.springframework.session.ExpiringSession; import org.springframework.session.MapSession; import org.springframework.session.Session; import org.springframework.session.SessionRepository; @@ -99,17 +100,17 @@ public class RedisOperationsSessionRepository implements SessionRepository redisOperations; + private final RedisOperations redisOperations; /** * If non-null, this value is used to override {@link RedisSession#setDefaultMaxInactiveInterval(int)}. @@ -132,7 +133,7 @@ public class RedisOperationsSessionRepository implements SessionRepository redisOperations) { + public RedisOperationsSessionRepository(RedisOperations redisOperations) { Assert.notNull(redisOperations, "RedisOperations cannot be null"); this.redisOperations = redisOperations; } @@ -232,7 +233,7 @@ public class RedisOperationsSessionRepository implements SessionRepository delta = new HashMap(); diff --git a/spring-session/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java b/spring-session/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java index 34f5a86..57ba2d6 100644 --- a/spring-session/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java +++ b/spring-session/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java @@ -15,7 +15,7 @@ */ package org.springframework.session.web.http; -import org.springframework.session.Session; +import org.springframework.session.ExpiringSession; import org.springframework.session.SessionRepository; import org.springframework.util.Assert; @@ -43,15 +43,14 @@ import java.util.Set; *
    *
  • The session id is looked up using {@link HttpSessionStrategy#getRequestedSessionId(javax.servlet.http.HttpServletRequest)}. * The default is to look in a cookie named SESSION.
  • - *
  • The session id of newly created {@link org.springframework.session.Session} is sent to the client using - * {@link HttpSessionStrategy#onNewSession(org.springframework.session.Session, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
  • + *
  • The session id of newly created {@link org.springframework.session.ExpiringSession} is sent to the client using *
  • The client is notified that the session id is no longer valid with {@link HttpSessionStrategy#onInvalidateSession(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
  • *
* * @since 1.0 * @author Rob Winch */ -public class SessionRepositoryFilter extends OncePerRequestFilter { +public class SessionRepositoryFilter extends OncePerRequestFilter { private final SessionRepository sessionRepository; private HttpSessionStrategy httpSessionStrategy = new CookieHttpSessionStrategy(); 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 d614a4b..4b85207 100644 --- a/spring-session/src/test/java/org/springframework/session/MapSessionTests.java +++ b/spring-session/src/test/java/org/springframework/session/MapSessionTests.java @@ -50,7 +50,7 @@ public class MapSessionTests { assertThat(session.hashCode()).isEqualTo(session.getId().hashCode()); } - static class CustomSession implements Session { + static class CustomSession implements ExpiringSession { @Override 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 0ef1342..0cab7d1 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 @@ -17,6 +17,7 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.data.redis.core.BoundHashOperations; import org.springframework.data.redis.core.RedisOperations; +import org.springframework.session.ExpiringSession; import org.springframework.session.MapSession; import org.springframework.session.Session; import org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession; @@ -25,7 +26,7 @@ import org.springframework.session.data.redis.RedisOperationsSessionRepository.R @RunWith(MockitoJUnitRunner.class) public class RedisOperationsSessionRepositoryTests { @Mock - RedisOperations redisOperations; + RedisOperations redisOperations; @Mock BoundHashOperations boundHashOperations; @Captor @@ -40,7 +41,7 @@ public class RedisOperationsSessionRepositoryTests { @Test public void createSessionDefaultMaxInactiveInterval() throws Exception { - Session session = redisRepository.createSession(); + ExpiringSession session = redisRepository.createSession(); assertThat(session.getMaxInactiveInterval()).isEqualTo(new MapSession().getMaxInactiveInterval()); } @@ -48,7 +49,7 @@ public class RedisOperationsSessionRepositoryTests { public void createSessionCustomMaxInactiveInterval() throws Exception { int interval = 1; redisRepository.setDefaultMaxInactiveInterval(interval); - Session session = redisRepository.createSession(); + ExpiringSession session = redisRepository.createSession(); assertThat(session.getMaxInactiveInterval()).isEqualTo(interval); }