diff --git a/spring-session-core/src/main/java/org/springframework/session/events/AbstractSessionEvent.java b/spring-session-core/src/main/java/org/springframework/session/events/AbstractSessionEvent.java index a48048af4..6b99945df 100644 --- a/spring-session-core/src/main/java/org/springframework/session/events/AbstractSessionEvent.java +++ b/spring-session-core/src/main/java/org/springframework/session/events/AbstractSessionEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-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. @@ -29,16 +29,11 @@ */ @SuppressWarnings("serial") public abstract class AbstractSessionEvent extends ApplicationEvent { + private final String sessionId; private final Session session; - protected AbstractSessionEvent(Object source, String sessionId) { - super(source); - this.sessionId = sessionId; - this.session = null; - } - AbstractSessionEvent(Object source, Session session) { super(source); this.session = session; @@ -62,4 +57,5 @@ public S getSession() { public String getSessionId() { return this.sessionId; } + } diff --git a/spring-session-core/src/main/java/org/springframework/session/events/SessionCreatedEvent.java b/spring-session-core/src/main/java/org/springframework/session/events/SessionCreatedEvent.java index a5ba8597f..77c469507 100644 --- a/spring-session-core/src/main/java/org/springframework/session/events/SessionCreatedEvent.java +++ b/spring-session-core/src/main/java/org/springframework/session/events/SessionCreatedEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-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. @@ -25,19 +25,14 @@ * * @author Rob Winch * @since 1.0 - * */ @SuppressWarnings("serial") public class SessionCreatedEvent extends AbstractSessionEvent { - public SessionCreatedEvent(Object source, String sessionId) { - super(source, sessionId); - } - /** * Create a new {@link SessionCreatedEvent}. - * @param source The Source of the SessionCreatedEvent - * @param session the Session that was created + * @param source the source of the event + * @param session the session that was created */ public SessionCreatedEvent(Object source, Session session) { super(source, session); diff --git a/spring-session-core/src/main/java/org/springframework/session/events/SessionDeletedEvent.java b/spring-session-core/src/main/java/org/springframework/session/events/SessionDeletedEvent.java index 484a8bd6c..bf662ae2b 100644 --- a/spring-session-core/src/main/java/org/springframework/session/events/SessionDeletedEvent.java +++ b/spring-session-core/src/main/java/org/springframework/session/events/SessionDeletedEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-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. @@ -26,16 +26,17 @@ * @author Mark Anderson * @author Rob Winch * @since 1.1 - * */ @SuppressWarnings("serial") public class SessionDeletedEvent extends SessionDestroyedEvent { - public SessionDeletedEvent(Object source, String sessionId) { - super(source, sessionId); - } - + /** + * Create a new {@link SessionDeletedEvent}. + * @param source the source of the event + * @param session the session that was created + */ public SessionDeletedEvent(Object source, Session session) { super(source, session); } + } diff --git a/spring-session-core/src/main/java/org/springframework/session/events/SessionDestroyedEvent.java b/spring-session-core/src/main/java/org/springframework/session/events/SessionDestroyedEvent.java index 9eacbe43c..e60838021 100644 --- a/spring-session-core/src/main/java/org/springframework/session/events/SessionDestroyedEvent.java +++ b/spring-session-core/src/main/java/org/springframework/session/events/SessionDestroyedEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-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. @@ -23,21 +23,17 @@ * * @author Rob Winch * @since 1.0 - * */ @SuppressWarnings("serial") public class SessionDestroyedEvent extends AbstractSessionEvent { - public SessionDestroyedEvent(Object source, String sessionId) { - super(source, sessionId); - } - /** * Create a new {@link SessionDestroyedEvent}. - * @param source The Source of the SessionDestoryedEvent - * @param session the Session that was created + * @param source the source of the event + * @param session the session that was created */ public SessionDestroyedEvent(Object source, Session session) { super(source, session); } + } diff --git a/spring-session-core/src/main/java/org/springframework/session/events/SessionExpiredEvent.java b/spring-session-core/src/main/java/org/springframework/session/events/SessionExpiredEvent.java index f2efeacf2..06d4286bc 100644 --- a/spring-session-core/src/main/java/org/springframework/session/events/SessionExpiredEvent.java +++ b/spring-session-core/src/main/java/org/springframework/session/events/SessionExpiredEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-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. @@ -26,16 +26,17 @@ * @author Mark Anderson * @author Rob Winch * @since 1.1 - * */ @SuppressWarnings("serial") public class SessionExpiredEvent extends SessionDestroyedEvent { - public SessionExpiredEvent(Object source, String sessionId) { - super(source, sessionId); - } - + /** + * Create a new {@link SessionExpiredEvent}. + * @param source the source of the event + * @param session the session that was created + */ public SessionExpiredEvent(Object source, Session session) { super(source, session); } + } diff --git a/spring-session-core/src/main/java/org/springframework/session/web/http/HttpSessionAdapter.java b/spring-session-core/src/main/java/org/springframework/session/web/http/HttpSessionAdapter.java index 555fea0cc..becdbda92 100644 --- a/spring-session-core/src/main/java/org/springframework/session/web/http/HttpSessionAdapter.java +++ b/spring-session-core/src/main/java/org/springframework/session/web/http/HttpSessionAdapter.java @@ -37,12 +37,22 @@ */ @SuppressWarnings("deprecation") class HttpSessionAdapter implements HttpSession { + private S session; + private final ServletContext servletContext; + private boolean invalidated; + private boolean old; HttpSessionAdapter(S session, ServletContext servletContext) { + if (session == null) { + throw new IllegalArgumentException("session cannot be null"); + } + if (servletContext == null) { + throw new IllegalArgumentException("servletContext cannot be null"); + } this.session = session; this.servletContext = servletContext; } @@ -162,6 +172,7 @@ private void checkState() { } private static final HttpSessionContext NOOP_SESSION_CONTEXT = new HttpSessionContext() { + @Override public HttpSession getSession(String sessionId) { return null; @@ -171,9 +182,11 @@ public HttpSession getSession(String sessionId) { public Enumeration getIds() { return EMPTY_ENUMERATION; } + }; private static final Enumeration EMPTY_ENUMERATION = new Enumeration() { + @Override public boolean hasMoreElements() { return false; @@ -183,5 +196,7 @@ public boolean hasMoreElements() { public String nextElement() { throw new NoSuchElementException("a"); } + }; + } diff --git a/spring-session-core/src/test/java/org/springframework/session/web/http/SessionEventHttpSessionListenerAdapterTests.java b/spring-session-core/src/test/java/org/springframework/session/web/http/SessionEventHttpSessionListenerAdapterTests.java index f8a08b31f..a60e1ac0a 100644 --- a/spring-session-core/src/test/java/org/springframework/session/web/http/SessionEventHttpSessionListenerAdapterTests.java +++ b/spring-session-core/src/test/java/org/springframework/session/web/http/SessionEventHttpSessionListenerAdapterTests.java @@ -31,6 +31,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.mock.web.MockServletContext; import org.springframework.session.MapSession; import org.springframework.session.Session; import org.springframework.session.events.SessionCreatedEvent; @@ -42,28 +43,37 @@ import static org.mockito.Mockito.verifyZeroInteractions; /** + * Tests for {@link SessionEventHttpSessionListenerAdapter}. + * * @author Rob Winch * @since 1.1 */ @RunWith(MockitoJUnitRunner.class) public class SessionEventHttpSessionListenerAdapterTests { + @Mock - HttpSessionListener listener1; + private HttpSessionListener listener1; + @Mock - HttpSessionListener listener2; + private HttpSessionListener listener2; + @Mock - ServletContext servletContext; + private ServletContext servletContext; + @Captor - ArgumentCaptor sessionEvent; + private ArgumentCaptor sessionEvent; + + private SessionDestroyedEvent destroyed; - SessionDestroyedEvent destroyed; - SessionCreatedEvent created; - SessionEventHttpSessionListenerAdapter listener; + private SessionCreatedEvent created; + + private SessionEventHttpSessionListenerAdapter listener; @Before public void setup() { this.listener = new SessionEventHttpSessionListenerAdapter( Arrays.asList(this.listener1, this.listener2)); + this.listener.setServletContext(new MockServletContext()); Session session = new MapSession(); this.destroyed = new SessionDestroyedEvent(this, session); @@ -114,4 +124,5 @@ public void onApplicationEventCreated() { assertThat(this.sessionEvent.getValue().getSession().getId()) .isEqualTo(this.created.getSessionId()); } + } diff --git a/spring-session-core/src/test/java/org/springframework/session/web/socket/handler/WebSocketRegistryListenerTests.java b/spring-session-core/src/test/java/org/springframework/session/web/socket/handler/WebSocketRegistryListenerTests.java index f1f37c06c..08ae75f16 100644 --- a/spring-session-core/src/test/java/org/springframework/session/web/socket/handler/WebSocketRegistryListenerTests.java +++ b/spring-session-core/src/test/java/org/springframework/session/web/socket/handler/WebSocketRegistryListenerTests.java @@ -29,6 +29,7 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.simp.SimpMessageHeaderAccessor; +import org.springframework.session.MapSession; import org.springframework.session.events.SessionDeletedEvent; import org.springframework.session.events.SessionExpiredEvent; import org.springframework.session.web.socket.events.SessionConnectEvent; @@ -46,36 +47,40 @@ @RunWith(MockitoJUnitRunner.class) public class WebSocketRegistryListenerTests { + @Mock - WebSocketSession wsSession; - @Mock - WebSocketSession wsSession2; + private WebSocketSession wsSession; + @Mock - Message message; + private WebSocketSession wsSession2; + @Mock - Principal principal; + private Message message; - SessionConnectEvent connect; + @Mock + private Principal principal; - SessionConnectEvent connect2; + private SessionConnectEvent connect; - SessionDisconnectEvent disconnect; + private SessionConnectEvent connect2; - SessionDeletedEvent deleted; + private SessionDisconnectEvent disconnect; - SessionExpiredEvent expired; + private SessionDeletedEvent deleted; - Map attributes; + private SessionExpiredEvent expired; - String sessionId; + private Map attributes; - WebSocketRegistryListener listener; + private WebSocketRegistryListener listener; @Before public void setup() { - this.sessionId = "session-id"; + String sessionId = "session-id"; + MapSession session = new MapSession(sessionId); + this.attributes = new HashMap<>(); - SessionRepositoryMessageInterceptor.setSessionId(this.attributes, this.sessionId); + SessionRepositoryMessageInterceptor.setSessionId(this.attributes, sessionId); given(this.wsSession.getAttributes()).willReturn(this.attributes); given(this.wsSession.getPrincipal()).willReturn(this.principal); @@ -94,8 +99,8 @@ public void setup() { this.connect2 = new SessionConnectEvent(this.listener, this.wsSession2); this.disconnect = new SessionDisconnectEvent(this.listener, this.message, this.wsSession.getId(), CloseStatus.NORMAL); - this.deleted = new SessionDeletedEvent(this.listener, this.sessionId); - this.expired = new SessionExpiredEvent(this.listener, this.sessionId); + this.deleted = new SessionDeletedEvent(this.listener, session); + this.expired = new SessionExpiredEvent(this.listener, session); } @Test @@ -170,4 +175,5 @@ public void onApplicationEventConnectConnectDisonnect() throws Exception { verify(this.wsSession2).close(WebSocketRegistryListener.SESSION_EXPIRED_STATUS); verify(this.wsSession, times(0)).close(any(CloseStatus.class)); } + } diff --git a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java index 1ab35c842..30c451953 100644 --- a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java +++ b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java @@ -527,6 +527,12 @@ public void onMessage(Message message, byte[] pattern) { RedisSession session = getSession(sessionId, true); + if (session == null) { + logger.warn("Unable to publish SessionDestroyedEvent for session " + + sessionId); + return; + } + if (logger.isDebugEnabled()) { logger.debug("Publishing SessionDestroyedEvent for session " + sessionId); } @@ -534,18 +540,15 @@ public void onMessage(Message message, byte[] pattern) { cleanupPrincipalIndex(session); if (isDeleted) { - handleDeleted(sessionId, session); + handleDeleted(session); } else { - handleExpired(sessionId, session); + handleExpired(session); } } } private void cleanupPrincipalIndex(RedisSession session) { - if (session == null) { - return; - } String sessionId = session.getId(); String principal = PRINCIPAL_NAME_RESOLVER.resolvePrincipal(session); if (principal != null) { @@ -554,28 +557,18 @@ private void cleanupPrincipalIndex(RedisSession session) { } } - public void handleCreated(Map loaded, String channel) { + private void handleCreated(Map loaded, String channel) { String id = channel.substring(channel.lastIndexOf(":") + 1); Session session = loadSession(id, loaded); publishEvent(new SessionCreatedEvent(this, session)); } - private void handleDeleted(String sessionId, RedisSession session) { - if (session == null) { - publishEvent(new SessionDeletedEvent(this, sessionId)); - } - else { - publishEvent(new SessionDeletedEvent(this, session)); - } + private void handleDeleted(RedisSession session) { + publishEvent(new SessionDeletedEvent(this, session)); } - private void handleExpired(String sessionId, RedisSession session) { - if (session == null) { - publishEvent(new SessionExpiredEvent(this, sessionId)); - } - else { - publishEvent(new SessionExpiredEvent(this, session)); - } + private void handleExpired(RedisSession session) { + publishEvent(new SessionExpiredEvent(this, session)); } private void publishEvent(ApplicationEvent event) {