This is an automated email from the ASF dual-hosted git repository.

stankiewicz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new 9ae08d5a068 [Solace] Close the HTTP response content stream in 
BrokerResponse (#39404)
9ae08d5a068 is described below

commit 9ae08d5a06803357e399956400f00ca043a049be
Author: ZIHAN DAI <[email protected]>
AuthorDate: Tue Jul 28 20:49:49 2026 +1000

    [Solace] Close the HTTP response content stream in BrokerResponse (#39404)
    
    BrokerResponse read the SEMP HTTP response body via a BufferedReader but
    never closed the underlying InputStream, so every SEMP call leaked the
    HTTP response content stream (the HttpResponse is never disconnected
    elsewhere either). Wrap the reader in try-with-resources so the stream
    is always closed once the body has been read, and add a regression
    test.
---
 .../beam/sdk/io/solace/broker/BrokerResponse.java  | 13 +++--
 .../sdk/io/solace/broker/BrokerResponseTest.java   | 66 ++++++++++++++++++++++
 2 files changed, 75 insertions(+), 4 deletions(-)

diff --git 
a/sdks/java/io/solace/src/main/java/org/apache/beam/sdk/io/solace/broker/BrokerResponse.java
 
b/sdks/java/io/solace/src/main/java/org/apache/beam/sdk/io/solace/broker/BrokerResponse.java
index 1a47f801228..6f3f4248b7c 100644
--- 
a/sdks/java/io/solace/src/main/java/org/apache/beam/sdk/io/solace/broker/BrokerResponse.java
+++ 
b/sdks/java/io/solace/src/main/java/org/apache/beam/sdk/io/solace/broker/BrokerResponse.java
@@ -22,6 +22,7 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.UncheckedIOException;
 import java.nio.charset.StandardCharsets;
 import java.util.stream.Collectors;
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -35,10 +36,14 @@ public class BrokerResponse {
     this.code = responseCode;
     this.message = message;
     if (content != null) {
-      this.content =
-          new BufferedReader(new InputStreamReader(content, 
StandardCharsets.UTF_8))
-              .lines()
-              .collect(Collectors.joining("\n"));
+      // Use try-with-resources so the underlying InputStream is always closed 
once the
+      // response body has been read; otherwise the HTTP connection stream 
leaks.
+      try (BufferedReader reader =
+          new BufferedReader(new InputStreamReader(content, 
StandardCharsets.UTF_8))) {
+        this.content = reader.lines().collect(Collectors.joining("\n"));
+      } catch (IOException e) {
+        throw new UncheckedIOException("Failed to read broker response 
content", e);
+      }
     }
   }
 
diff --git 
a/sdks/java/io/solace/src/test/java/org/apache/beam/sdk/io/solace/broker/BrokerResponseTest.java
 
b/sdks/java/io/solace/src/test/java/org/apache/beam/sdk/io/solace/broker/BrokerResponseTest.java
new file mode 100644
index 00000000000..08614219423
--- /dev/null
+++ 
b/sdks/java/io/solace/src/test/java/org/apache/beam/sdk/io/solace/broker/BrokerResponseTest.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.sdk.io.solace.broker;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import org.junit.Test;
+
+public class BrokerResponseTest {
+
+  /** An {@link java.io.InputStream} that records whether {@code close()} was 
invoked. */
+  private static class CloseTrackingInputStream extends ByteArrayInputStream {
+    private boolean closed = false;
+
+    CloseTrackingInputStream(String data) {
+      super(data.getBytes(StandardCharsets.UTF_8));
+    }
+
+    boolean wasClosed() {
+      return closed;
+    }
+
+    @Override
+    public void close() {
+      closed = true;
+    }
+  }
+
+  @Test
+  public void testContentIsReadAndStreamIsClosed() {
+    CloseTrackingInputStream stream = new 
CloseTrackingInputStream("line1\nline2");
+
+    BrokerResponse response = new BrokerResponse(200, "OK", stream);
+
+    assertEquals("line1\nline2", response.content);
+    assertTrue(
+        "the content InputStream must be closed after the response body has 
been read",
+        stream.wasClosed());
+  }
+
+  @Test
+  public void testNullContentIsHandled() {
+    BrokerResponse response = new BrokerResponse(204, "No Content", null);
+
+    assertNull(response.content);
+  }
+}

Reply via email to