Why are those changes in the 5.6 and not in 5.7? SSE module in is master and is not in the 5.6.x branch.

Oleg

https://github.com/apache/httpcomponents-website/tree/master/src/site/markdown/httpcomponents-client-5.7.x

On 12/23/2025 10:10, [email protected] wrote:
This is an automated email from the ASF dual-hosted git repository.

abernal pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-website.git


The following commit(s) were added to refs/heads/master by this push:
      new bb99baa  Add HttpClient SSE module docs (overview, guide, examples, 
javadocs links)
bb99baa is described below

commit bb99baa372e97666bb4624452afef77cba20f8fa
Author: Arturo Bernal <[email protected]>
AuthorDate: Tue Dec 23 10:10:10 2025 +0100

     Add HttpClient SSE module docs (overview, guide, examples, javadocs links)
---
  .../httpcomponents-client-5.6.x/examples-sse.md    | 191 ++++++++++++++++++++
  .../markdown/httpcomponents-client-5.6.x/index.md  |   6 +
  .../markdown/httpcomponents-client-5.6.x/sse.md    | 192 +++++++++++++++++++++
  3 files changed, 389 insertions(+)

diff --git a/src/site/markdown/httpcomponents-client-5.6.x/examples-sse.md 
b/src/site/markdown/httpcomponents-client-5.6.x/examples-sse.md
new file mode 100644
index 0000000..6977ca6
--- /dev/null
+++ b/src/site/markdown/httpcomponents-client-5.6.x/examples-sse.md
@@ -0,0 +1,191 @@
+<!--
+    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.
+-->
+
+HttpClient SSE examples
+=======================
+
+This page shows complete examples for the optional SSE module 
(`httpclient5-sse`).
+
+Example 1: public stream (Wikimedia recent changes)
+---------------------------------------------------
+
+This example is based on 
`org.apache.hc.client5.http.sse.example.ClientSseExample` from the
+`httpclient5-sse` module tests.
+
+It demonstrates:
+
+- Custom async client with HTTP/2 negotiation and stream multiplexing.
+- Dedicated scheduler for reconnect backoff.
+- `SseParser.BYTE` for reduced allocations.
+- A simple listener with lifecycle handling.
+
+```java
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+
+import org.apache.hc.client5.http.config.TlsConfig;
+import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
+import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
+import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
+import 
org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
+import org.apache.hc.client5.http.sse.EventSource;
+import org.apache.hc.client5.http.sse.EventSourceConfig;
+import org.apache.hc.client5.http.sse.EventSourceListener;
+import org.apache.hc.client5.http.sse.SseExecutor;
+import org.apache.hc.client5.http.sse.impl.ExponentialJitterBackoff;
+import org.apache.hc.client5.http.sse.impl.SseParser;
+import org.apache.hc.core5.concurrent.DefaultThreadFactory;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
+import org.apache.hc.core5.http2.config.H2Config;
+import org.apache.hc.core5.reactor.IOReactorConfig;
+import org.apache.hc.core5.util.TimeValue;
+
+public final class ClientSseExample {
+
+    public static void main(final String[] args) throws Exception {
+        final URI uri = URI.create(args.length > 0
+                ? args[0]
+                : "https://stream.wikimedia.org/v2/stream/recentchange";);
+
+        final IOReactorConfig ioCfg = IOReactorConfig.custom()
+                .setIoThreadCount(Math.max(2, 
Runtime.getRuntime().availableProcessors()))
+                .setSoKeepAlive(true)
+                .setTcpNoDelay(true)
+                .build();
+
+        final PoolingAsyncClientConnectionManager connMgr =
+                PoolingAsyncClientConnectionManagerBuilder.create()
+                        .useSystemProperties()
+                        .setMessageMultiplexing(true)
+                        .setMaxConnPerRoute(32)
+                        .setMaxConnTotal(256)
+                        .setDefaultTlsConfig(
+                                TlsConfig.custom()
+                                        
.setVersionPolicy(HttpVersionPolicy.NEGOTIATE)
+                                        .build())
+                        .build();
+
+        final CloseableHttpAsyncClient httpClient = 
HttpAsyncClientBuilder.create()
+                .setIOReactorConfig(ioCfg)
+                .setConnectionManager(connMgr)
+                .setH2Config(H2Config.custom()
+                        .setPushEnabled(false)
+                        .setMaxConcurrentStreams(256)
+                        .build())
+                .useSystemProperties()
+                .evictExpiredConnections()
+                .evictIdleConnections(TimeValue.ofMinutes(1))
+                .build();
+
+        final ScheduledThreadPoolExecutor scheduler =
+                new ScheduledThreadPoolExecutor(4, new 
DefaultThreadFactory("sse-backoff", true));
+        scheduler.setRemoveOnCancelPolicy(true);
+
+        final Executor callbacks = Runnable::run;
+
+        final EventSourceConfig cfg = EventSourceConfig.builder()
+                .backoff(new ExponentialJitterBackoff(500L, 30_000L, 2.0, 
250L))
+                .maxReconnects(-1)
+                .build();
+
+        final Map<String, String> defaultHeaders = new HashMap<>();
+        defaultHeaders.put("User-Agent", "Apache-HttpClient-SSE/5.x");
+        defaultHeaders.put("Accept-Language", "en");
+
+        final SseExecutor exec = SseExecutor.custom()
+                .setHttpClient(httpClient)
+                .setScheduler(scheduler)
+                .setCallbackExecutor(callbacks)
+                .setEventSourceConfig(cfg)
+                .setDefaultHeaders(defaultHeaders)
+                .setParserStrategy(SseParser.BYTE)
+                .build();
+
+        final CountDownLatch done = new CountDownLatch(1);
+
+        final EventSourceListener listener = new EventSourceListener() {
+            @Override
+            public void onOpen() {
+                System.out.println("[SSE] open: " + uri);
+            }
+
+            @Override
+            public void onEvent(final String id, final String type, final 
String data) {
+                final String shortData = data.length() > 120 ? data.substring(0, 120) + 
"…" : data;
+                System.out.printf(Locale.ROOT, "[SSE] %s id=%s %s%n",
+                        type != null ? type : "message", id, shortData);
+            }
+
+            @Override
+            public void onFailure(final Throwable t, final boolean 
willReconnect) {
+                System.err.println("[SSE] failure: " + t + " willReconnect=" + 
willReconnect);
+                if (!willReconnect) {
+                    done.countDown();
+                }
+            }
+
+            @Override
+            public void onClosed() {
+                System.out.println("[SSE] closed");
+                done.countDown();
+            }
+        };
+
+        final EventSource es = exec.open(uri, listener);
+
+        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+            try {
+                es.cancel();
+            } catch (final Exception ignore) {
+            }
+            try {
+                exec.close();
+            } catch (final Exception ignore) {
+            }
+            try {
+                scheduler.shutdownNow();
+            } catch (final Exception ignore) {
+            }
+        }, "sse-shutdown"));
+
+        es.start();
+        done.await();
+
+        es.cancel();
+        exec.close();
+        scheduler.shutdownNow();
+    }
+}
+```
+
+Example 2: perf harness
+----------------------
+
+The `httpclient5-sse` tests also include a small performance harness:
+
+- `org.apache.hc.client5.http.sse.example.performance.SsePerfServer` – local 
SSE server with configurable rate/payload.
+- `org.apache.hc.client5.http.sse.example.performance.SsePerfClient` – many 
connections, ramp-up batching, simple
+  latency histogram.
+
+Those classes are intended for development / benchmarking (not as a public 
API).
diff --git a/src/site/markdown/httpcomponents-client-5.6.x/index.md 
b/src/site/markdown/httpcomponents-client-5.6.x/index.md
index dd05275..311d5e1 100644
--- a/src/site/markdown/httpcomponents-client-5.6.x/index.md
+++ b/src/site/markdown/httpcomponents-client-5.6.x/index.md
@@ -53,6 +53,8 @@ Documentation
     * [Observation](observation.md)
     * [SCRAM-SHA-256](scram-sha-256.md)
     * [SPKI pinning TLS strategy](spki-pinning.md)
+   * [Server-Sent Events (SSE)](sse.md)
+
6. Examples demonstrating some common as well as more complex use cases @@ -60,6 +62,7 @@ Documentation
     * [HttpClient (async APIs)](examples-async.md)
     * [HttpClient (reactive APIs)](examples-reactive.md)
     * [HttpClient (observation APIs)](examples-observation.md)
+   * [HttpClient (SSE APIs)](examples-sse.md)
1. Javadocs @@ -67,6 +70,7 @@ Documentation
     * [HC Fluent](./current/httpclient5-fluent/apidocs/)
     * [HttpClient Cache](./current/httpclient5-cache/apidocs/)
     * [HttpClient Observation](./current/httpclient5-observation/apidocs/)
+   * [HttpClient SSE](./current/httpclient5-sse/apidocs/)
1. API compatibility reports @@ -99,6 +103,8 @@ Features
  - Optional Server-Sent Events (SSE) module for consuming long-lived event
    streams over HTTP/1.1 and HTTP/2 using the async transport.
  - Source code is freely available under the Apache License.
+- Optional Server-Sent Events (SSE) module for consuming long-lived event
+  streams over HTTP/1.1 and HTTP/2 using the async transport.
Standards Compliance
diff --git a/src/site/markdown/httpcomponents-client-5.6.x/sse.md 
b/src/site/markdown/httpcomponents-client-5.6.x/sse.md
new file mode 100644
index 0000000..748770d
--- /dev/null
+++ b/src/site/markdown/httpcomponents-client-5.6.x/sse.md
@@ -0,0 +1,192 @@
+<!--
+    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.
+-->
+
+Server-Sent Events (SSE)
+========================
+
+Server-Sent Events (SSE) is a simple, server → client streaming protocol built 
on top of HTTP. The server keeps an
+HTTP response open and sends events as lines in the `text/event-stream` format.
+
+HttpClient provides an optional SSE module (`httpclient5-sse`) that consumes 
long-lived event streams over HTTP/1.1 and
+HTTP/2 using the async transport.
+
+Requirements
+------------
+
+- Java 8+
+- Apache HttpClient 5.7+ (the SSE module is `@since 5.7`)
+
+Dependency
+----------
+
+Maven:
+
+```xml
+<dependency>
+  <groupId>org.apache.httpcomponents.client5</groupId>
+  <artifactId>httpclient5-sse</artifactId>
+  <version>${httpclient.version}</version>
+</dependency>
+```
+
+Gradle:
+
+```gradle
+implementation("org.apache.httpcomponents.client5:httpclient5-sse:${httpclientVersion}")
+```
+
+Quick start
+-----------
+
+The SSE API is intentionally small:
+
+- `SseExecutor` is the entry point.
+- `EventSource` represents a single SSE stream.
+- `EventSourceListener` receives events and lifecycle callbacks.
+
+Minimal example (shared async client):
+
+```java
+import java.net.URI;
+
+import org.apache.hc.client5.http.sse.EventSource;
+import org.apache.hc.client5.http.sse.EventSourceListener;
+import org.apache.hc.client5.http.sse.SseExecutor;
+
+public final class MinimalSse {
+
+    public static void main(final String[] args) throws Exception {
+        final URI uri = 
URI.create("https://stream.wikimedia.org/v2/stream/recentchange";);
+
+        final SseExecutor exec = SseExecutor.newInstance();
+        final EventSource es = exec.open(uri, new EventSourceListener() {
+            @Override
+            public void onOpen() {
+                System.out.println("[SSE] open");
+            }
+
+            @Override
+            public void onEvent(final String id, final String type, final 
String data) {
+                System.out.println("[SSE] " + (type != null ? type : "message") + 
": " + data);
+            }
+
+            @Override
+            public void onFailure(final Throwable t, final boolean 
willReconnect) {
+                System.err.println("[SSE] failure=" + t + " willReconnect=" + 
willReconnect);
+            }
+
+            @Override
+            public void onClosed() {
+                System.out.println("[SSE] closed");
+            }
+        });
+
+        es.start();
+
+        // ... do other work ...
+
+        // Stop the stream (no further reconnects) when you are done.
+        es.cancel();
+
+        // When using the shared client, exec.close() is a no-op.
+        // Call SseExecutor.closeSharedClient() if you want to explicitly shut 
it down.
+    }
+}
+```
+
+Configuration
+-------------
+
+Reconnect / backoff
+~~~~~~~~~~~~~~~~~~~
+
+Reconnects are controlled by `EventSourceConfig` and `BackoffStrategy`.
+
+- `maxReconnects = -1` means “try forever”.
+- The default backoff is `ExponentialJitterBackoff` and it honors server hints:
+  - the SSE `retry:` field (milliseconds)
+  - the HTTP `Retry-After` header
+
+Example:
+
+```java
+import org.apache.hc.client5.http.sse.EventSourceConfig;
+import org.apache.hc.client5.http.sse.impl.ExponentialJitterBackoff;
+
+final EventSourceConfig cfg = EventSourceConfig.builder()
+        .backoff(new ExponentialJitterBackoff(500L, 30_000L, 2.0, 250L))
+        .maxReconnects(-1)
+        .build();
+```
+
+Threading
+~~~~~~~~~
+
+Listener callbacks must be non-blocking.
+
+- If you do heavy work in `onEvent(...)`, provide a callback executor so the 
I/O threads stay responsive.
+- Reconnect scheduling can use an application scheduler (recommended for large 
fan-out).
+
+The builder makes those defaults explicit:
+
+```java
+import java.util.concurrent.Executor;
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.apache.hc.client5.http.sse.SseExecutor;
+
+final ScheduledExecutorService scheduler = /* your scheduler */;
+final Executor callbacks = /* your callback executor */;
+
+final SseExecutor exec = SseExecutor.custom()
+        .setScheduler(scheduler)
+        .setCallbackExecutor(callbacks)
+        .build();
+```
+
+HTTP/2 multiplexing
+~~~~~~~~~~~~~~~~~~~
+
+SSE works over HTTP/1.1 and HTTP/2.
+
+- The default shared client created by `SseExecutor.newInstance()` uses a 
pooling async connection manager with message
+  multiplexing enabled.
+- If you provide your own async client, enable message multiplexing if you 
plan to run many streams over a small number
+  of HTTP/2 connections.
+
+Request headers and resumption
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- The implementation always sends `Accept: text/event-stream`.
+- The most recent non-null event id is tracked and used as `Last-Event-ID` on 
reconnect.
+- You can set and remove headers on the `EventSource` to affect subsequent 
reconnects.
+
+```java
+es.setHeader("Authorization", "Bearer ...");
+es.removeHeader("Authorization");
+
+final String last = es.lastEventId();
+es.setLastEventId(last); // override / resume manually
+```
+
+See also
+--------
+
+- [SSE examples](examples-sse.md)
+- Module javadocs: `./current/httpclient5-sse/apidocs/`



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to