From 1993182f13c70b9754b3403ba364a3458b625878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Sejkora?= Date: Wed, 11 Jun 2025 21:32:54 +0200 Subject: [PATCH 1/2] [SignalR] [Java] Fix NPE when closing hub connection during negotiation --- .../com/microsoft/signalr/HubConnection.java | 3 ++- .../microsoft/signalr/HubConnectionTest.java | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java b/src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java index ab7763e6f54c..455a0323b6f9 100644 --- a/src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java +++ b/src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java @@ -445,7 +445,8 @@ private Completable stop(String errorMessage) { CompletableSubject subject = CompletableSubject.create(); startTask.onErrorComplete().subscribe(() -> { - Completable stop = connectionState.transport.stop(); + Transport transport = connectionState.transport; + Completable stop = (transport != null) ? transport.stop() : Completable.complete(); stop.subscribe(() -> subject.onComplete(), e -> subject.onError(e)); }); diff --git a/src/SignalR/clients/java/signalr/test/src/main/java/com/microsoft/signalr/HubConnectionTest.java b/src/SignalR/clients/java/signalr/test/src/main/java/com/microsoft/signalr/HubConnectionTest.java index 396b58518df3..d68f56ce5d51 100644 --- a/src/SignalR/clients/java/signalr/test/src/main/java/com/microsoft/signalr/HubConnectionTest.java +++ b/src/SignalR/clients/java/signalr/test/src/main/java/com/microsoft/signalr/HubConnectionTest.java @@ -2783,6 +2783,26 @@ public void negotiateSentOnStart() { assertEquals("http://example.com/negotiate?negotiateVersion=1", sentRequests.get(0).getUrl()); } + @Test + public void closeWithPendingNegotiate() { + TestHttpClient client = new TestHttpClient() + .on("POST", (req) -> Single.just(new HttpResponse(404, "", TestUtils.emptyByteBuffer)).delay(200, TimeUnit.MILLISECONDS)); + + HubConnection hubConnection = HubConnectionBuilder + .create("http://example.com") + .withHttpClient(client) + .build(); + + Completable start = hubConnection.start(); + assertEquals(HubConnectionState.CONNECTING, hubConnection.getConnectionState()); + hubConnection.stop().timeout(3, TimeUnit.SECONDS).blockingAwait(); + assertEquals(HubConnectionState.DISCONNECTED, hubConnection.getConnectionState()); + + HttpRequestException exception = assertThrows(HttpRequestException.class, () -> start.blockingAwait(10, TimeUnit.SECONDS)); + assertEquals("Unexpected status code returned from negotiate: 404 .", exception.getMessage()); + assertEquals(404, exception.getStatusCode()); + } + @Test public void negotiateThatRedirectsForeverFailsAfter100Tries() { TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate?negotiateVersion=1", From dd127b1c14b23e40188d2d7fd5d9ca42c58e1eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Sejkora?= Date: Tue, 22 Jul 2025 22:01:09 +0200 Subject: [PATCH 2/2] Remove unnecessary test delay --- .../java/com/microsoft/signalr/HubConnectionTest.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/SignalR/clients/java/signalr/test/src/main/java/com/microsoft/signalr/HubConnectionTest.java b/src/SignalR/clients/java/signalr/test/src/main/java/com/microsoft/signalr/HubConnectionTest.java index d68f56ce5d51..e68009f51039 100644 --- a/src/SignalR/clients/java/signalr/test/src/main/java/com/microsoft/signalr/HubConnectionTest.java +++ b/src/SignalR/clients/java/signalr/test/src/main/java/com/microsoft/signalr/HubConnectionTest.java @@ -2785,8 +2785,10 @@ public void negotiateSentOnStart() { @Test public void closeWithPendingNegotiate() { + SingleSubject responseSubject = SingleSubject.create(); + TestHttpClient client = new TestHttpClient() - .on("POST", (req) -> Single.just(new HttpResponse(404, "", TestUtils.emptyByteBuffer)).delay(200, TimeUnit.MILLISECONDS)); + .on("POST", (req) -> responseSubject); HubConnection hubConnection = HubConnectionBuilder .create("http://example.com") @@ -2795,7 +2797,11 @@ public void closeWithPendingNegotiate() { Completable start = hubConnection.start(); assertEquals(HubConnectionState.CONNECTING, hubConnection.getConnectionState()); - hubConnection.stop().timeout(3, TimeUnit.SECONDS).blockingAwait(); + + Completable stop = hubConnection.stop(); + + responseSubject.onSuccess(new HttpResponse(404, "", TestUtils.emptyByteBuffer)); + stop.timeout(3, TimeUnit.SECONDS).blockingAwait(); assertEquals(HubConnectionState.DISCONNECTED, hubConnection.getConnectionState()); HttpRequestException exception = assertThrows(HttpRequestException.class, () -> start.blockingAwait(10, TimeUnit.SECONDS));