diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/session/AbstractSockJsSession.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/session/AbstractSockJsSession.java index ba8cdc94d8..fca70afd39 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/session/AbstractSockJsSession.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/session/AbstractSockJsSession.java @@ -396,7 +396,12 @@ public abstract class AbstractSockJsSession implements SockJsSession { if (!isClosed()) { try { updateLastActiveTime(); - cancelHeartbeat(); + // Avoid cancelHeartbeat() and responseLock within server "close" callback + ScheduledFuture future = this.heartbeatFuture; + if (future != null) { + this.heartbeatFuture = null; + future.cancel(false); + } } finally { this.state = State.CLOSED; @@ -446,7 +451,7 @@ public abstract class AbstractSockJsSession implements SockJsSession { @Override public void run() { synchronized (responseLock) { - if (!this.expired) { + if (!this.expired && !isClosed()) { try { sendHeartbeat(); } diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/session/SockJsSessionTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/session/SockJsSessionTests.java index 46433ce771..1d5e3f0352 100644 --- a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/session/SockJsSessionTests.java +++ b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/session/SockJsSessionTests.java @@ -31,8 +31,17 @@ import org.springframework.web.socket.sockjs.SockJsMessageDeliveryException; import org.springframework.web.socket.sockjs.SockJsTransportFailureException; import org.springframework.web.socket.sockjs.frame.SockJsFrame; -import static org.junit.Assert.*; -import static org.mockito.BDDMockito.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.BDDMockito.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.mock; +import static org.mockito.BDDMockito.verify; +import static org.mockito.BDDMockito.verifyNoMoreInteractions; +import static org.mockito.BDDMockito.willReturn; +import static org.mockito.BDDMockito.willThrow; /** * Test fixture for {@link AbstractSockJsSession}. @@ -130,7 +139,6 @@ public class SockJsSessionTests extends AbstractSockJsSessionTests