This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch docs
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/docs by this push:
new a2471197b8 docs: document juneau-rest-server decoupling from Apache
HttpClient 4.5 (TODO-40)
a2471197b8 is described below
commit a2471197b8c58c2ea23dd60335f108a2dcb07fd4
Author: James Bognar <[email protected]>
AuthorDate: Tue May 19 20:45:50 2026 -0400
docs: document juneau-rest-server decoupling from Apache HttpClient 4.5
(TODO-40)
Co-authored-by: Cursor <[email protected]>
---
pages/release-notes/9.5.0.md | 73 +++++++++++++++++++++++++++++-
pages/topics/01.04.RestServer.md | 2 +-
pages/topics/10.25.ResponseProcessors.md | 2 +-
pages/topics/23.01.V9.5-migration-guide.md | 67 ++++++++++++++++++++++++++-
4 files changed, 140 insertions(+), 4 deletions(-)
diff --git a/pages/release-notes/9.5.0.md b/pages/release-notes/9.5.0.md
index 928482f2fb..05a1f20880 100644
--- a/pages/release-notes/9.5.0.md
+++ b/pages/release-notes/9.5.0.md
@@ -2163,7 +2163,7 @@ Mirroring the `juneau-rest-client` split above, the
`juneau-rest-common` module
**Backward compatibility:**
- Fully qualified class names are unchanged —
`org.apache.juneau.http.classic.header.EntityTag` is still
`org.apache.juneau.http.classic.header.EntityTag`. Source-compatible.
-- Code that already depended on `juneau-rest-common` and used a `classic.*`
type now needs an additional `<dependency>` on `juneau-rest-common-classic`.
The aggregator artifacts (`juneau-rest-server`, `juneau-rest-client-classic`,
`juneau-rest-mock`, `juneau-microservice`, `juneau-rest-server-springboot`,
`juneau-shaded-rest-server`, `juneau-shaded-rest-client`, `juneau-shaded-all`,
`juneau-distrib`) already pull both modules in transitively, so most callers
see no Maven change.
+- Code that already depended on `juneau-rest-common` and used a `classic.*`
type now needs an additional `<dependency>` on `juneau-rest-common-classic`.
The aggregator artifacts (`juneau-rest-client-classic`, `juneau-rest-mock`,
`juneau-microservice`, `juneau-shaded-rest-server`,
`juneau-shaded-rest-client`, `juneau-shaded-all`, `juneau-distrib`) already
pull both modules in transitively, so most callers using those uber artifacts
see no Maven change. (As of 9.5, `juneau-rest-server` and [...]
- `EntityTag` / `EntityTags` value types (no HC 4.5 dependency, despite the
historical package) moved out of `classic.header` to
`org.apache.juneau.http.header.EntityTag` / `EntityTags`. **This is a
source-incompatible change** for any caller that imported them explicitly — see
the v9.5 migration guide.
- `@Remote(headerList = ...)` annotation method changed from `Class<? extends
HeaderList>` to `Class<?>`. Existing user annotations like `@Remote(headerList
= MyHeaderList.class)` continue to work; the classic `RemoteMeta` performs an
`instanceof HeaderList` check at runtime before invoking. The default sentinel
changed from `HeaderList.Void.class` to `java.lang.Void.class`.
@@ -2217,6 +2217,77 @@ The classic `RestClient` / `juneau-rest-common` APIs
remain fully supported. Mig
The classic stack is **not** deprecated in 9.5; the canonical stack will
graduate to stable in a future release, at which point the classic stack may be
deprecated and eventually removed.
+### `juneau-rest-server` decoupled from Apache HttpClient 4.5 (TODO-40)
+
+Completes the HC 4.5 removal started by TODO-38 / TODO-42.
`juneau-rest-server` is now genuinely transport-neutral — it neither imports
`org.apache.http.*` nor depends on `juneau-rest-common-classic`, so `mvn -pl
juneau-rest/juneau-rest-server dependency:tree | grep httpcomponents` returns
nothing. Pulling `juneau-rest-server` no longer drags
`org.apache.httpcomponents:httpcore:4.4.16` onto the consumer classpath.
+
+#### New transport-neutral types in `juneau-rest-common`
+
+To give the server somewhere to migrate **to**, the following
transport-neutral siblings of the classic HC 4.5 types were added in
`org.apache.juneau.http.*`. They use only JDK types — no `org.apache.http.*`
dependency.
+
+| New type | Replaces (classic) | Notes |
+|---|---|---|
+| `HttpRequestLine` (interface) + `request/HttpRequestLineBean` |
`org.apache.http.RequestLine` | Method / URI / `HttpProtocolVersion`. |
+| `HttpProtocolVersion` (record) | `org.apache.http.ProtocolVersion` |
`protocol()` / `major()` / `minor()` accessors plus `parse(String)`. |
+| `header/HttpHeaderList` | `org.apache.juneau.http.classic.header.HeaderList`
| Mutable ordered list of `HttpHeader` with
`getFirst/getLast/getAll/forEach/copy` plus case-sensitive and case-insensitive
lookup. |
+| `part/HttpPartList` | `org.apache.juneau.http.classic.part.PartList` |
Mutable ordered list of `HttpPart` mirroring `HttpHeaderList`. |
+| `part/HttpStringPart`, `HttpBooleanPart`, `HttpIntegerPart`, `HttpLongPart`,
`HttpDatePart`, `HttpUriPart`, `HttpCsvArrayPart` |
`org.apache.juneau.http.classic.part.Basic*Part` | Concrete typed parts so
`RequestQueryParam` / `RequestFormParam` / `RequestPathParam` / `RequestHeader`
can keep their typed conversion ergonomics (`.asInteger()`, `.asLong()`,
`.asDate()`, etc.). |
+| `header/HttpStringHeader`, `HttpBooleanHeader`, `HttpIntegerHeader`,
`HttpLongHeader`, `HttpDateHeader`, `HttpEntityTagHeader`,
`HttpEntityTagsHeader`, `HttpMediaTypeHeader`, `HttpMediaRangesHeader`,
`HttpStringRangesHeader`, `HttpCsvHeader`, `HttpUriHeader` |
`org.apache.juneau.http.classic.header.Basic*Header` | Abstract bases with
typed accessors; subclassed by the ~73 RFC-named header classes (`Accept`,
`ContentType`, `Authorization`, …). |
+| `resource/HttpResourceBean` |
`org.apache.juneau.http.classic.resource.BasicResource` | Concrete
`HttpResource` implementation backed by `HttpBody` + `List<HttpHeader>`. |
+
+`BasicHttpException` (and therefore all ~62 named status subclasses in
`org.apache.juneau.http.response.*` — `BadRequest`, `Ok`, `NotFound`,
`InternalServerError`, …) gained the full classic fluent setter surface so
server-side handlers that build responses via `throw new
BadRequest().setHeader(...).setReasonPhrase(...)` keep working unchanged after
the package swap:
+
+- `setStatusCode(int)`, `setReasonPhrase(String)`,
`setProtocolVersion(HttpProtocolVersion)`
+- `setHeader(HttpHeader)`, `setHeader(String name, String value)`
+- `setHeaders(HttpHeader...)`, `setHeaders(List<HttpHeader>)`
+- `setContent(HttpBody)`, `setContent(String)`
+- `setLocale(Locale)`, `setUnmodifiable()`
+
+#### Public API changes in `juneau-rest-server`
+
+The 9.5 release retypes the server-side public surface from
`org.apache.http.*` onto the new transport-neutral types. The signature changes
below are **source-incompatible** for any caller that imported the classic
types directly:
+
+| Member | Was | Is |
+|---|---|---|
+| `RestRequest#getAllHeaders()` | `org.apache.http.Header[]` |
`org.apache.juneau.http.HttpHeader[]` |
+| `RestRequest#getRequestLine()` | `org.apache.http.RequestLine` |
`org.apache.juneau.http.HttpRequestLine` |
+| `RestRequest#getProtocolVersion()` | `org.apache.http.ProtocolVersion` |
`org.apache.juneau.http.HttpProtocolVersion` |
+| `RestRequest#addDefault(...)` / `RestOpContext.getDefaultRequestHeaders()` |
`org.apache.http.Header[]` / `HeaderList` |
`org.apache.juneau.http.HttpHeader[]` / `HttpHeaderList` |
+| `RequestHeader`, `RequestQueryParam`, `RequestFormParam`,
`RequestPathParam`, `RequestHttpPart`, `BasicNamedAttribute` | extended
`org.apache.http.Header` / `org.apache.http.NameValuePair` | extend
`org.apache.juneau.http.HttpHeader` / `org.apache.juneau.http.HttpPart` |
+| `BasicStaticFiles` / `BasicStaticFiles.Builder` header collections |
`org.apache.http.Header[]` | `org.apache.juneau.http.HttpHeader[]` |
+| `FluentRequestLineAssertion` | over `org.apache.http.RequestLine` | over
`HttpRequestLine` |
+| `FluentProtocolVersionAssertion` | over `org.apache.http.ProtocolVersion` |
over `HttpProtocolVersion` |
+| `HttpStatusLine#getProtocolVersion()` | `String` | `HttpProtocolVersion` |
+
+#### Class renames in `juneau-rest-server`
+
+The four request-side part-list classes were renamed for naming consistency
with the new `HttpHeaderList` / `HttpPartList` siblings in
`juneau-rest-common`. No backward-compatibility shims are kept — callers must
update imports and references.
+
+| Was | Is |
+|---|---|
+| `org.apache.juneau.rest.httppart.RequestFormParams` |
`org.apache.juneau.rest.httppart.RequestFormParamList` |
+| `org.apache.juneau.rest.httppart.RequestHeaders` |
`org.apache.juneau.rest.httppart.RequestHeaderList` |
+| `org.apache.juneau.rest.httppart.RequestPathParams` |
`org.apache.juneau.rest.httppart.RequestPathParamList` |
+| `org.apache.juneau.rest.httppart.RequestQueryParams` |
`org.apache.juneau.rest.httppart.RequestQueryParamList` |
+
+The argument resolvers and `RestPreCall` / `RestPostCall` lifecycle hooks were
updated to recognize the new names; any user method signature that referenced
the old names needs to be updated.
+
+#### Response processor rename
+
+`org.apache.juneau.rest.processor.HttpEntityProcessor` was renamed to
`HttpBodyProcessor`. The class was already internally rewritten to operate on
`HttpBody` instead of HC 4.5's `HttpEntity`, but the class name kept the legacy
term until this release. The default response-processor chain registered by
`DefaultConfig` was updated accordingly; any custom
`RestContext.responseProcessors(...)` configuration that names
`HttpEntityProcessor.class` needs to be updated to `HttpBodyProcessor.class`.
+
+#### Backward-compatibility shim for legacy return types
+
+A small reflective bridge —
`org.apache.juneau.rest.processor.LegacyHttpResponseAdapter` — was added so
user `@RestOp` methods that still return classic `org.apache.http.HttpResponse`
/ `org.apache.http.HttpEntity` /
`org.apache.juneau.http.classic.resource.BasicResource` instances keep working
when `juneau-rest-common-classic` is on the runtime classpath, even though
`juneau-rest-server` itself no longer compiles against those types. The bridge
is invoked by `HttpBodyProcessor` and `Htt [...]
+
+#### Verification
+
+After this change:
+
+- `mvn -pl juneau-rest/juneau-rest-server dependency:tree | grep
httpcomponents` returns nothing.
+- `rg -n '^import\s+org\.apache\.http\.'
juneau-rest/juneau-rest-server/src/main/java` returns nothing.
+- `rg -n '^import\s+org\.apache\.juneau\.http\.classic\.'
juneau-rest/juneau-rest-server/src/main/java` returns nothing.
+
### JDK `HttpClient` is now the built-in default transport (TODO-41)
The JDK `java.net.http.HttpClient`–based transport (`JavaHttpTransport`) is
now part of the `juneau-rest-client` artifact itself. The previously separate
`juneau-rest-client-java-httpclient` module — which had no third-party
dependencies and was never released — has been folded in and removed.
diff --git a/pages/topics/01.04.RestServer.md b/pages/topics/01.04.RestServer.md
index c9ed85f208..f126d7761f 100644
--- a/pages/topics/01.04.RestServer.md
+++ b/pages/topics/01.04.RestServer.md
@@ -161,7 +161,7 @@ public interface BasicUniversalConfig extends
DefaultConfig, DefaultHtmlConfig {
ThrowableProcessor.class,
HttpResponseProcessor.class,
HttpResourceProcessor.class,
- HttpEntityProcessor.class,
+ HttpBodyProcessor.class,
ResponseBeanProcessor.class,
PlainTextPojoProcessor.class,
SerializedPojoProcessor.class
diff --git a/pages/topics/10.25.ResponseProcessors.md
b/pages/topics/10.25.ResponseProcessors.md
index b5fb332514..d55eb09dfa 100644
--- a/pages/topics/10.25.ResponseProcessors.md
+++ b/pages/topics/10.25.ResponseProcessors.md
@@ -8,7 +8,7 @@ or set through <a
href="/site/apidocs/org/apache/juneau/rest/RestResponse.html#s
By default, REST resource classes are registered with the following response
processors:
<tree>
-<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/rest/processor/HttpEntityProcessor.html"
target="_blank">HttpEntityProcessor</a></java-class></node-0>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/rest/processor/HttpBodyProcessor.html"
target="_blank">HttpBodyProcessor</a></java-class></node-0>
<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/rest/processor/HttpResourceProcessor.html"
target="_blank">HttpResourceProcessor</a></java-class></node-0>
<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/rest/processor/HttpResponseProcessor.html"
target="_blank">HttpResponseProcessor</a></java-class></node-0>
<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/rest/processor/InputStreamProcessor.html"
target="_blank">InputStreamProcessor</a></java-class></node-0>
diff --git a/pages/topics/23.01.V9.5-migration-guide.md
b/pages/topics/23.01.V9.5-migration-guide.md
index a38f51cda4..1b2966d40c 100644
--- a/pages/topics/23.01.V9.5-migration-guide.md
+++ b/pages/topics/23.01.V9.5-migration-guide.md
@@ -347,7 +347,7 @@ Continues the work started in TODO-38: `juneau-rest-common`
is now split into a
| Old (single artifact) | New (two artifacts) | Notes |
|-----|-----|-------|
-| `<artifactId>juneau-rest-common</artifactId>` *(carries `httpcore`
transitively)* | `<artifactId>juneau-rest-common</artifactId>`
*(transport-neutral, **no** `httpcore`)* **and/or**
`<artifactId>juneau-rest-common-classic</artifactId>` *(new, depends on
`httpcore`)* | Code using only `org.apache.juneau.http.*` /
`org.apache.juneau.http.header.*` / `org.apache.juneau.http.remote.*` /
`org.apache.juneau.http.part.*` / `org.apache.juneau.http.entity.*` /
`org.apache.juneau.http.response.* [...]
+| `<artifactId>juneau-rest-common</artifactId>` *(carries `httpcore`
transitively)* | `<artifactId>juneau-rest-common</artifactId>`
*(transport-neutral, **no** `httpcore`)* **and/or**
`<artifactId>juneau-rest-common-classic</artifactId>` *(new, depends on
`httpcore`)* | Code using only `org.apache.juneau.http.*` /
`org.apache.juneau.http.header.*` / `org.apache.juneau.http.remote.*` /
`org.apache.juneau.http.part.*` / `org.apache.juneau.http.entity.*` /
`org.apache.juneau.http.response.* [...]
### Class moves (source-incompatible)
@@ -370,5 +370,70 @@ Every other `org.apache.juneau.http.classic.*` type stayed
in place — only the
| `Class<? extends HeaderList> hl =
Remote.class.getMethod("headerList").getReturnType().asSubclass(HeaderList.class);`
| `Class<?> hl = remoteAnnotation.headerList();` followed by an explicit
`isAssignableFrom` check before use. | Reflective callers must cast/check
explicitly. |
| `Remote.headerList()` default was `HeaderList.Void.class`. | Default is
`java.lang.Void.class`. | The framework's `isVoid` check still recognizes the
default and skips header-list resolution. |
+## `juneau-rest-server` Decoupled from Apache HttpClient 4.5 (TODO-40)
+
+Completes the HC 4.5 removal started by TODO-38 / TODO-42.
`juneau-rest-server` no longer imports `org.apache.http.*` and no longer
depends on `juneau-rest-common-classic`, so its dependency tree is free of
`org.apache.httpcomponents:httpcore`. The server-side public API was retyped
onto the new transport-neutral types in `org.apache.juneau.http.*` — see the
table below for the source-incompatible changes most callers will have to react
to.
+
+### Maven dependency change
+
+The Maven coordinate stays the same; the transitive set shrinks:
+
+| Old (9.4) | New (9.5) | Notes |
+|-----|-----|-------|
+| `juneau-rest-server` pulled `juneau-rest-common-classic` →
`httpcomponents:httpcore:4.4.16` transitively. | `juneau-rest-server` pulls
only `juneau-rest-common`. No `org.apache.httpcomponents:*` on the classpath. |
If your `@Rest` resource still references any
`org.apache.juneau.http.classic.*` type (e.g. throws
`org.apache.juneau.http.classic.response.BadRequest`, accepts a
`org.apache.juneau.http.classic.header.HeaderList`, returns a
`org.apache.juneau.http.classic.resource.BasicReso [...]
+
+The shaded aggregator artifacts (`juneau-shaded-rest-server`,
`juneau-shaded-rest-server-springboot`, `juneau-shaded-all`, `juneau-distrib`)
continue to bundle both flavors, so callers that pull them in see no Maven
change.
+
+### Server-side public API changes
+
+The server-side surface that used to expose `org.apache.http.*` types was
retyped. These signature changes are **source-incompatible**:
+
+| Old (9.4) | New (9.5) | Notes |
+|-----|-----|-------|
+| `org.apache.http.Header[] hdrs = req.getAllHeaders();` |
`org.apache.juneau.http.HttpHeader[] hdrs = req.getAllHeaders();` |
`RestRequest#getAllHeaders()` retyped. The new `HttpHeader` is a JDK-only
interface; `getName()` / `getValue()` are unchanged. |
+| `org.apache.http.RequestLine rl = req.getRequestLine();` |
`org.apache.juneau.http.HttpRequestLine rl = req.getRequestLine();` |
`getMethod()` / `getUri()` are unchanged; `getProtocolVersion()` now returns
`HttpProtocolVersion` instead of `org.apache.http.ProtocolVersion`. |
+| `org.apache.http.ProtocolVersion pv = req.getProtocolVersion();` |
`org.apache.juneau.http.HttpProtocolVersion pv = req.getProtocolVersion();` |
Record with `protocol()` / `major()` / `minor()` accessors plus
`parse(String)`. |
+| `RequestHeader implements org.apache.http.Header` | `RequestHeader
implements org.apache.juneau.http.HttpHeader` | Same for `RequestHttpPart`,
`RequestQueryParam`, `RequestFormParam`, `RequestPathParam`,
`BasicNamedAttribute`. They now implement the JDK-typed Juneau interfaces. |
+|
`restContextBuilder.staticFiles(BasicStaticFiles.create()....headers(org.apache.http.Header...).build())`
| `....headers(org.apache.juneau.http.HttpHeader...).build()` |
`BasicStaticFiles` / `BasicStaticFiles.Builder` retyped. |
+| `FluentRequestLineAssertion<…>` over `org.apache.http.RequestLine` | over
`org.apache.juneau.http.HttpRequestLine` | Assertion plumbing on
`FluentProtocolVersionAssertion` follows the same pattern. |
+| `HttpStatusLine#getProtocolVersion()` returned `String` | returns
`HttpProtocolVersion` | The wire-level numeric major / minor parts are now
available directly without re-parsing. |
+
+### Class renames in `org.apache.juneau.rest.httppart`
+
+The four request-side part-list classes were renamed for consistency with the
new `HttpHeaderList` / `HttpPartList` siblings in `juneau-rest-common`. **No
backward-compatibility shims are kept** — callers must update imports and
references.
+
+| Old | New | Notes |
+|-----|-----|-------|
+| `org.apache.juneau.rest.httppart.RequestFormParams` |
`org.apache.juneau.rest.httppart.RequestFormParamList` | Used in `@RestOp`
method signatures (`@RestPost public ... method(RequestFormParams formData)`)
and `@RestPreCall` / `@RestPostCall` hooks. Update the type reference. |
+| `org.apache.juneau.rest.httppart.RequestHeaders` |
`org.apache.juneau.rest.httppart.RequestHeaderList` | Same pattern. |
+| `org.apache.juneau.rest.httppart.RequestPathParams` |
`org.apache.juneau.rest.httppart.RequestPathParamList` | Same pattern. |
+| `org.apache.juneau.rest.httppart.RequestQueryParams` |
`org.apache.juneau.rest.httppart.RequestQueryParamList` | Same pattern. |
+
+### Response processor rename
+
+| Old | New | Notes |
+|-----|-----|-------|
+| `org.apache.juneau.rest.processor.HttpEntityProcessor` |
`org.apache.juneau.rest.processor.HttpBodyProcessor` | The class was already
internally rewritten to operate on `org.apache.juneau.http.HttpBody` rather
than HC 4.5's `org.apache.http.HttpEntity`; the class name was kept for
compatibility through earlier 9.5 snapshots but is now renamed. The default
response-processor chain registered by `DefaultConfig` is updated; any custom
`RestContext.responseProcessors(...)` configuration th [...]
+
+### Legacy return-type handling
+
+`@RestOp` methods that still return classic `org.apache.http.HttpResponse` /
`org.apache.http.HttpEntity` /
`org.apache.juneau.http.classic.resource.BasicResource` instances keep working
at runtime: a new `org.apache.juneau.rest.processor.LegacyHttpResponseAdapter`
reflectively bridges those legacy return types into the canonical `HttpBody` /
`HttpHeader` pipeline. The bridge is invoked by `HttpBodyProcessor` and
`HttpResponseProcessor` only when the returned object is a recognized legac
[...]
+
+### New transport-neutral types you can migrate **to**
+
+These are new in `juneau-rest-common` and replace the corresponding HC 4.5 /
`org.apache.juneau.http.classic.*` types in `juneau-rest-server`'s public API.
They're available to user code too — typical migration is just an import swap.
+
+| Classic (HC 4.5–based) | Transport-neutral (new) |
+|-----|-----|
+| `org.apache.http.RequestLine` | `org.apache.juneau.http.HttpRequestLine`
(interface) + `org.apache.juneau.http.request.HttpRequestLineBean` (default
impl) |
+| `org.apache.http.ProtocolVersion` |
`org.apache.juneau.http.HttpProtocolVersion` (record) |
+| `org.apache.juneau.http.classic.header.HeaderList` |
`org.apache.juneau.http.header.HttpHeaderList` |
+| `org.apache.juneau.http.classic.part.PartList` |
`org.apache.juneau.http.part.HttpPartList` |
+|
`org.apache.juneau.http.classic.part.Basic{String,Boolean,Integer,Long,Date,Uri,CsvArray}Part`
|
`org.apache.juneau.http.part.Http{String,Boolean,Integer,Long,Date,Uri,CsvArray}Part`
|
+|
`org.apache.juneau.http.classic.header.Basic{String,Boolean,Integer,Long,Date,EntityTag,EntityTags,MediaType,MediaRanges,StringRanges,Csv,Uri}Header`
|
`org.apache.juneau.http.header.Http{String,Boolean,Integer,Long,Date,EntityTag,EntityTags,MediaType,MediaRanges,StringRanges,Csv,Uri}Header`
|
+| `org.apache.juneau.http.classic.resource.BasicResource` |
`org.apache.juneau.http.resource.HttpResourceBean` |
+
+`BasicHttpException` and all ~62 named status subclasses in
`org.apache.juneau.http.response.*` (`BadRequest`, `Ok`, `NotFound`,
`InternalServerError`, …) gained the full classic fluent-setter surface
(`setHeader` / `setHeaders` / `setProtocolVersion` / `setStatusCode` /
`setReasonPhrase` / `setLocale` / `setContent` / `setUnmodifiable`), so
server-side handlers that build responses via `throw new
BadRequest().setHeader(...).setReasonPhrase(...)` keep their ergonomics after
the `classic` [...]
+
<!-- Additional rows will be populated as 9.5 breaking changes land. See
todo/TODO-17 for the
ongoing 9.5.0 audit. -->