Skip to content

Commit 59df2b9

Browse files
committed
GH-8785: Propagate WebSocket client connect fail
Fixes #8785 The `ClientWebSocketContainer.start()` delegates to the `IntegrationWebSocketConnectionManager` which performs an async connection to the server. * Wait for `connectionLatch` in the `ClientWebSocketContainer.start()` and check for `this.openConnectionException != null` to re-throw. Mark `ClientWebSocketContainer` as stopped in that case **Cherry-pick to `6.1.x` & `6.0.x`** # Conflicts: # spring-integration-websocket/src/main/java/org/springframework/integration/websocket/ClientWebSocketContainer.java
1 parent 72ce758 commit 59df2b9

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

spring-integration-websocket/src/main/java/org/springframework/integration/websocket/ClientWebSocketContainer.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,19 @@ public synchronized void start() {
189189
this.openConnectionException = null;
190190
this.connectionLatch = new CountDownLatch(1);
191191
this.connectionManager.start();
192+
try {
193+
this.connectionLatch.await(this.connectionTimeout, TimeUnit.SECONDS);
194+
}
195+
catch (InterruptedException ex) {
196+
logger.error("'clientSession' has not been established during 'openConnection'");
197+
}
198+
199+
if (this.openConnectionException != null) {
200+
// The next 'this.connectionManager.stop()' call resets 'this.openConnectionException' to null
201+
IllegalStateException exceptionToRethrow = new IllegalStateException(this.openConnectionException);
202+
this.connectionManager.stop();
203+
throw exceptionToRethrow;
204+
}
192205
}
193206
}
194207

spring-integration-websocket/src/test/java/org/springframework/integration/websocket/ClientWebSocketContainerTests.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.concurrent.TimeUnit;
2929
import java.util.concurrent.atomic.AtomicBoolean;
3030

31+
import jakarta.websocket.DeploymentException;
3132
import org.apache.tomcat.websocket.Constants;
3233
import org.junit.jupiter.api.AfterAll;
3334
import org.junit.jupiter.api.BeforeAll;
@@ -126,10 +127,8 @@ protected CompletableFuture<WebSocketSession> executeInternal(WebSocketHandler w
126127

127128
failure.set(true);
128129

129-
container.start();
130-
131130
assertThatIllegalStateException()
132-
.isThrownBy(() -> container.getSession(null))
131+
.isThrownBy(container::start)
133132
.withCauseInstanceOf(CancellationException.class);
134133

135134
failure.set(false);
@@ -170,6 +169,20 @@ public void testWebSocketContainerOverflowStrategyPropagation() throws Exception
170169
.isEqualTo(ConcurrentWebSocketSessionDecorator.OverflowStrategy.DROP);
171170
}
172171

172+
@Test
173+
public void webSocketContainerFailsOnStartForInvalidUrl() {
174+
StandardWebSocketClient webSocketClient = new StandardWebSocketClient();
175+
176+
ClientWebSocketContainer container =
177+
new ClientWebSocketContainer(webSocketClient, server.getWsBaseUrl() + "/no_such_endpoint");
178+
179+
assertThatIllegalStateException()
180+
.isThrownBy(container::start)
181+
.withCauseExactlyInstanceOf(DeploymentException.class)
182+
.withStackTraceContaining(
183+
"The HTTP response from the server [404] did not permit the HTTP upgrade to WebSocket");
184+
}
185+
173186
private static class TestWebSocketListener implements WebSocketListener {
174187

175188
public final CountDownLatch messageLatch = new CountDownLatch(1);

0 commit comments

Comments
 (0)