Skip to content

Commit 6be0432

Browse files
committed
Use ConnectionLostException after heartbeat failures
ConnectionLostException was applies only after the WebSocket library notified us of a session close. However, read inactivity and heartbeat send failures are also cases of the connection being lost rather than closed intentionally. This commit also ensures resetConnection is called after a heartbeat write failure, consistent with other places where a transport error is handled that implies the connection is lost. See gh-32195
1 parent 6a5953d commit 6be0432

File tree

3 files changed

+17
-8
lines changed

3 files changed

+17
-8
lines changed

Diff for: spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/ConnectionLostException.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,4 +29,8 @@ public ConnectionLostException(String message) {
2929
super(message);
3030
}
3131

32+
public ConnectionLostException(String message, Throwable cause) {
33+
super(message, cause);
34+
}
35+
3236
}

Diff for: spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/DefaultStompSession.java

+11-6
Original file line numberDiff line numberDiff line change
@@ -714,9 +714,14 @@ private class WriteInactivityTask implements Runnable {
714714
public void run() {
715715
TcpConnection<byte[]> conn = connection;
716716
if (conn != null) {
717-
conn.sendAsync(HEARTBEAT).whenComplete((unused, throwable) -> {
718-
if (throwable != null) {
719-
handleFailure(throwable);
717+
conn.sendAsync(HEARTBEAT).whenComplete((unused, ex) -> {
718+
if (ex != null) {
719+
String msg = "Heartbeat write failure. Closing connection in session id=" + sessionId + ".";
720+
if (logger.isDebugEnabled()) {
721+
logger.debug(msg);
722+
}
723+
resetConnection();
724+
handleFailure(new ConnectionLostException(msg, ex));
720725
}
721726
});
722727
}
@@ -728,13 +733,13 @@ private class ReadInactivityTask implements Runnable {
728733

729734
@Override
730735
public void run() {
731-
String error = "Read inactivity. Closing connection in session id=" + sessionId + ".";
736+
String msg = "Read inactivity. Closing connection in session id=" + sessionId + ".";
732737
if (logger.isDebugEnabled()) {
733-
logger.debug(error);
738+
logger.debug(msg);
734739
}
735740
clientSideClose = true;
736741
resetConnection();
737-
handleFailure(new IllegalStateException(error));
742+
handleFailure(new ConnectionLostException(msg));
738743
}
739744
}
740745

Diff for: spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/DefaultStompSessionTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ void heartbeatTasks() {
221221

222222
reset(this.sessionHandler);
223223
readTask.run();
224-
verify(this.sessionHandler).handleTransportError(same(this.session), any(IllegalStateException.class));
224+
verify(this.sessionHandler).handleTransportError(same(this.session), any(ConnectionLostException.class));
225225
verifyNoMoreInteractions(this.sessionHandler);
226226
}
227227

0 commit comments

Comments
 (0)