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 a960571373 Add pluggable query-protocol adapters over the ObjectTools
query engine (TODO-355)
a960571373 is described below
commit a96057137314488ae67efb432437cc9912f7bf01
Author: James Bognar <[email protected]>
AuthorDate: Thu Aug 13 12:02:11 2026 -0400
Add pluggable query-protocol adapters over the ObjectTools query engine
(TODO-355)
Decouples the query wire-protocol from the search/view/sort/page engine via
a new QueryProtocol SPI. NativeQueryProtocol extracts the s/v/o/p/l parsing
(RequestQueryParamList's query-arg accessors moved behind it); Queryable is
reshaped onto the native adapter via composition; ProtocolQueryable +
QueryableSettings select a protocol per resource (default native). New
juneau-rest-server-datatables module ships DataTablesQueryProtocol +
DataTablesResults and client-side helpers (DataTabl [...]
---
artifact-paths.json | 1 +
pages/release-notes/10.0.0.md | 23 ++++++++
pages/topics/10.15.Converters.md | 79 +++++++++++++++++++++++++-
pages/topics/10.31.03.HtmlPredefinedWidgets.md | 2 +-
pages/topics/27.V10MigrationGuide.md | 31 ++++++++++
src/pages/about.md | 1 +
6 files changed, 135 insertions(+), 2 deletions(-)
diff --git a/artifact-paths.json b/artifact-paths.json
index 816e7fb1a1..ad497ebd86 100644
--- a/artifact-paths.json
+++ b/artifact-paths.json
@@ -59,6 +59,7 @@
"juneau-rest-server-auth-oauth": "juneau-rest/juneau-rest-server-auth-oauth",
"juneau-rest-server-auth-oidc-rp":
"juneau-rest/juneau-rest-server-auth-oidc-rp",
"juneau-rest-server-auth-saml": "juneau-rest/juneau-rest-server-auth-saml",
+ "juneau-rest-server-datatables": "juneau-rest/juneau-rest-server-datatables",
"juneau-rest-server-management-logging":
"juneau-rest/juneau-rest-server-management-logging",
"juneau-rest-server-mcp": "juneau-rest/juneau-rest-server-mcp",
"juneau-rest-server-mcp-v20250618":
"juneau-rest/juneau-rest-server-mcp-v20250618",
diff --git a/pages/release-notes/10.0.0.md b/pages/release-notes/10.0.0.md
index bfda00ed30..e17cfe7f76 100644
--- a/pages/release-notes/10.0.0.md
+++ b/pages/release-notes/10.0.0.md
@@ -417,6 +417,16 @@ public class RootResource extends BasicRestServlet {
See the new [REST Authenticator — Resource-Level
Authentication](/docs/topics/RestServerAuthenticator) topic page.
+### Pluggable query protocols + `juneau-rest-server-datatables` (new module)
+
+Juneau 10.0 decouples the query *wire protocol* (request parameter names +
response envelope shape) from the query *engine*
(`ObjectSearcher`/`ObjectSorter`/`ObjectViewer`/`ObjectPaginator`), so the one
engine can be driven from multiple client protocols. The `Queryable` converter
is reshaped onto a new `QueryProtocol` SPI
(`QueryProtocol`/`QueryArgs`/`QueryResult`/`NativeQueryProtocol`/`ProtocolQueryable`/`QueryableSettings`
in `org.apache.juneau.rest.server.converter` — see Breaking Ch [...]
+
+- **`ProtocolQueryable` + `QueryableSettings`** — a resource selects its
protocol by registering a `QueryableSettings` bean (bean-store resolved,
mirroring `IntrospectableSettings`); the default is the native `s/v/o/p/l`
protocol so it is drop-in identical to `Queryable`.
+- **`juneau-rest-server-datatables` module**
(`org.apache.juneau:juneau-rest-server-datatables`) — a new opt-in add-on (not
bundled in `juneau-distrib`, mirroring the
`juneau-rest-server-management-logging` precedent) with:
+ - **`DataTablesQueryProtocol`** — parses the [DataTables server-side
contract](https://datatables.net/manual/server-side)
(`draw`/`start`/`length`/`search[value]`/`search[regex]`/`order[i][…]`/`columns[i][…]`),
mapping per-column search → AND, global search → cross-column OR, order →
sort, start/length → page. Search terms map to case-insensitive quoted
`'*term*'` patterns; client regex is **off by default** and gated behind
`QueryableSettings.allowRegexSearch(true)` (closing a ReDoS v [...]
+ - **`DataTablesResults<T>`** — the
`{draw,recordsTotal,recordsFiltered,data}` (+ optional `error`) envelope bean,
rendered by the negotiated serializer (no hardcoded JSON).
+ - **Browser-side helpers** — `DataTablesColumns` (generate `columns:[…]`
from bean-property order + `@Schema` titles), `DataTablesTable` (build a
DataTables-ready HTML5 `Table` DOM bean, with `MarshallingContext` overloads),
and `DataTablesMixin` (serves a first-party `juneau-datatables.js` auto-init
glue script). DataTables' own JS/CSS and jQuery remain **caller-provided** (not
vendored — their license is not ASF category-A).
+
### juneau-rest-client / juneau-rest-common
### Next-generation remote-proxy declarative features
@@ -434,6 +444,13 @@ Juneau 10.0 significantly expands what the [REST
proxy](/docs/topics/RestProxies
See the expanded [Declarative Remote-Proxy
Features](/docs/topics/NextGenRestClient#declarative-remote-proxy-features-next-gen)
section of the Next-Generation REST Client topic page for full examples and
precedence rules.
+### Transport robustness — stale pooled-connection retry
+
+The next-generation REST client's HTTP transports now transparently retry a
request **exactly once** when a pooled keep-alive connection is torn down by
the server before any response bytes are received (an immediate `EOF` /
connection reset) — a common source of intermittent failures against servers
that idle-close persistent connections. The retry is gated on provable safety:
an [idempotent](https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.2)
HTTP method (`GET`, `HEAD`, `PUT`, [...]
+
+- **`JettyHttpTransport`** and **`ApacheHc45Transport`** gained this in an
earlier 10.0.0 change; **`JavaHttpTransport`** (the default, JDK
`HttpClient`-backed transport) now matches them. The JDK client self-retries
only body-less `GET`s on such a failure, so the transport-level retry closes
the gap for the other idempotent methods (e.g. `PUT` / `DELETE`).
+- A shared predicate,
`TransportException.isStaleConnectionFailure(Throwable)`, recognizes the
failure signature across transports (`EOFException` / `ClosedChannelException`
/ a connection-reset `SocketException` / the JDK's `"HTTP/1.1 header parser
received no bytes"` message).
+
### juneau-marshall
### Token-Streaming and Record-Streaming API
@@ -728,6 +745,8 @@ Juneau's first [Model Context
Protocol](https://modelcontextprotocol.io/) suppor
The duplex path builds directly on the new general-purpose SSE APIs in
`juneau-rest-client` (`RestRequest.openEventStream()`,
`ResponseBody.asEventStream()`) and keeps server->client payloads raw/opaque by
design; typed sampling/elicitation modeling remains owned by later MCP server
slices.
+**Read-only-method stale-connection retry.** Every MCP call is transported as
an HTTP `POST`, which a transport can never safely replay on a stale
pooled-connection failure (the `POST` may already have executed server-side).
`AbstractMcpClient.send()` therefore adds its own **once-only** retry keyed on
**JSON-RPC method idempotency** rather than HTTP method: a pre-response
stale-connection failure on a side-effect-free method (`initialize`,
`server/discover`, `ping`, `tools/list`, `promp [...]
+
### `juneau-bean-jsonrpc` (new module)
A new bean module, `juneau-bean-jsonrpc`, models the revision-neutral JSON-RPC
2.0 envelope as Juneau `@Marshalled` POJOs. It carries no MCP-specific
knowledge — it depends on `juneau-marshall` only — and is the shared framing
layer beneath protocol-specific bean modules such as
`juneau-bean-mcp-v20250618`.
@@ -1249,6 +1268,10 @@ See
[juneau-rest-server-mcp](/docs/topics/JuneauRestServerMcp#resource-templates
Applications that relied on `Introspectable` to invoke methods over REST
should register an `IntrospectableSettings` bean allow-listing the specific
methods they need (preferred), or `.allowAll()` on a trusted,
non-internet-facing resource only.
- **Unaffected:** argument parsing and return-value casting behavior are
unchanged; only the pre-dispatch allow-list check is new.
+- **`Queryable` REST response converter reshaped onto a pluggable
`QueryProtocol` SPI (`juneau-rest-server`) (TODO-355 OQ2).** The `Queryable`
converter — which parsed the Juneau-native `&s=`/`&v=`/`&o=`/`&p=`/`&l=` query
parameters and ran the shared
`ObjectSearcher`/`ObjectSorter`/`ObjectViewer`/`ObjectPaginator` engine — was
decoupled so the same engine can be driven from other client wire contracts.
`org.apache.juneau.rest.server.converter.Queryable` is now a thin subclass of a
new g [...]
+
+- **`RequestQueryParamList` native-arg accessors removed
(`juneau-rest-server`) (TODO-355 OQ6).** The four public native-protocol-shaped
accessors
`org.apache.juneau.rest.server.httppart.RequestQueryParamList#getSearchArgs()`/`getSortArgs()`/`getViewArgs()`/`getPageArgs()`
were removed — their parsing moved fully behind `NativeQueryProtocol`.
**Migration:** obtain the equivalent normalized args via
`NativeQueryProtocol.INSTANCE.parse(req)`, whose returned `QueryArgs` exposes
`getSearch() [...]
+
_Other entries TBD — to be filled in before release. See also the major
version bump note above._
### Deprecations
diff --git a/pages/topics/10.15.Converters.md b/pages/topics/10.15.Converters.md
index e7166fd6f6..fd057557b2 100644
--- a/pages/topics/10.15.Converters.md
+++ b/pages/topics/10.15.Converters.md
@@ -34,6 +34,83 @@ Juneau defines the following converters out-of-the-box:
<tree>
<node-0><java-interface><a
href="/site/apidocs/org/apache/juneau/rest/server/converter/RestConverter.html"
target="_blank">RestConverter</a></java-interface></node-0>
<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/rest/server/converter/Queryable.html"
target="_blank">Queryable</a></java-class> - Provides query parameters that can
be used to transform the response (i.e. search/view/sort the POJO response
before being serialized).</node-1>
+<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/rest/server/converter/ProtocolQueryable.html"
target="_blank">ProtocolQueryable</a></java-class> - Protocol-agnostic variant
of <c>Queryable</c> that drives a pluggable query protocol (e.g. DataTables
server-side processing).</node-1>
<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/rest/server/converter/Traversable.html"
target="_blank">Traversable</a></java-class> - Allows nodes in the POJO
response tree to be individually accessed through additional path info on the
request.</node-1>
<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/rest/server/converter/Introspectable.html"
target="_blank">Introspectable</a></java-class> - Allows method calls to be
made on the response POJO, and for the result of that method call to be
serialized as the response.</node-1>
-</tree>
\ No newline at end of file
+</tree>
+
+## Query protocols
+
+As of 10.0, the query engine behind `Queryable` (search/view/sort/page over
tabular POJO responses) is decoupled from the wire protocol that carries the
query parameters. This is expressed through a small SPI:
+
+<tree>
+<node-0><java-interface><a
href="/site/apidocs/org/apache/juneau/rest/server/converter/QueryProtocol.html"
target="_blank">QueryProtocol</a></java-interface> - Parses a request into
normalized <a
href="/site/apidocs/org/apache/juneau/rest/server/converter/QueryArgs.html"
target="_blank">QueryArgs</a> and wraps the engine's <a
href="/site/apidocs/org/apache/juneau/rest/server/converter/QueryResult.html"
target="_blank">QueryResult</a> into a response object.</node-0>
+<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/rest/server/converter/NativeQueryProtocol.html"
target="_blank">NativeQueryProtocol</a></java-class> - The historical
Juneau-native <c>s/v/o/p/l</c> parameters returning a bare filtered result.
This is the default.</node-1>
+</tree>
+
+`Queryable` is the **native adapter**: it always uses `NativeQueryProtocol`,
so its behavior is unchanged from prior releases.
+
+To speak a different wire protocol, register the `ProtocolQueryable` converter
and select a protocol per-resource with a <a
href="/site/apidocs/org/apache/juneau/rest/server/converter/QueryableSettings.html"
target="_blank">QueryableSettings</a> bean. When no bean is registered,
`ProtocolQueryable` falls back to the native protocol, so it is drop-in
compatible with `Queryable`.
+
+:::tip Example — DataTables server-side processing
+The optional `juneau-rest-server-datatables` module ships a <a
href="/site/apidocs/org/apache/juneau/rest/server/datatables/DataTablesQueryProtocol.html"
target="_blank">DataTablesQueryProtocol</a> that maps the [DataTables
server-side protocol](https://datatables.net/manual/server-side)
(`draw`/`start`/`length`/`search`/`order`/`columns`) onto the same engine and
returns a <a
href="/site/apidocs/org/apache/juneau/rest/server/datatables/DataTablesResults.html"
target="_blank">DataTablesR [...]
+
+```java
+@Rest(converters=ProtocolQueryable.class)
+public class MyResource extends BasicRestServlet {
+
+ @Bean
+ public QueryableSettings queryableSettings() {
+ return QueryableSettings.create().protocol(new
DataTablesQueryProtocol()).build();
+ }
+
+ @RestGet
+ public List<MyRow> getRows() {...}
+}
+```
+:::
+
+:::note DataTables hardening knobs
+`QueryableSettings` exposes a few guardrails for the DataTables adapter, all
defaulting to safe values:
+
+- **`allowRegexSearch(boolean)`** (default **false**) — when off, a
`search[regex]=true` flag is treated as a literal case-insensitive substring
search; when on, a malformed client regex returns HTTP 400 (not 500). Leaving
it off closes a ReDoS / CPU-burn vector from untrusted regex input.
+- **`maxColumns(int)`** (default **64**) / **`maxOrderColumns(int)`** (default
**8**) — cap how many `columns[i]`/`order[i]` descriptors are parsed, bounding
work from an oversized request.
+
+Non-regex search terms map to case-insensitive quoted `'*term*'` patterns, and
a text search against a numeric column returns HTTP 400 rather than a 500.
+:::
+
+:::note Breaking change (10.0)
+The native-protocol-shaped accessors `RequestQueryParamList.getSearchArgs()` /
`getSortArgs()` / `getViewArgs()` / `getPageArgs()` have been removed. That
parsing now lives behind `NativeQueryProtocol.parse(RestRequest)`.
+:::
+
+### Client-side helpers (DataTables)
+
+The `juneau-rest-server-datatables` module also ships thin, first-party
browser-side helpers so a server-rendered table can be upgraded into a
DataTables grid without hand-duplicating column lists or serving the wiring
yourself:
+
+<tree>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/rest/server/datatables/DataTablesColumns.html"
target="_blank">DataTablesColumns</a></java-class> - Generates the DataTables
<c>columns</c> array (one
<c>data</c>/<c>title</c>/<c>orderable</c>/<c>searchable</c> entry per column)
from a bean's property order, using <a
href="/site/apidocs/org/apache/juneau/commons/Schema.html"
target="_blank">@Schema(title)</a> titles (falling back to a humanized property
name), so the browser-si [...]
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/rest/server/datatables/DataTablesTable.html"
target="_blank">DataTablesTable</a></java-class> - Builds a plain,
DataTables-ready HTML <c><table></c> DOM bean (stable <c>id</c>, clean
<c><thead>/<tbody></c>, marked with <c>data-juneau-datatable</c>)
from a collection of rows. Rendered by any Juneau HTML serializer — no
coupling to the marshall-core <c>HtmlDocSerializer</c>.</node-0>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/rest/server/datatables/DataTablesMixin.html"
target="_blank">DataTablesMixin</a></java-class> - A <c>@Rest(mixins=...)</c>
mixin that serves the first-party <c>juneau-datatables.js</c> glue script at
<c>/juneau-datatables.js</c>. The glue auto-initializes every <c><table
data-juneau-datatable></c> on the page by calling
<c>$(table).DataTable(opts)</c> once the DataTables library is present.</node-0>
+</tree>
+
+:::warning DataTables library is caller-provided
+This is an Apache project, and the [DataTables](https://datatables.net)
library's license is **not** an ASF category-A license. Juneau therefore **does
not bundle DataTables' own JS/CSS (nor jQuery)** — the only asset it ships is
the thin first-party `juneau-datatables.js` glue. Reference the DataTables
library from a CDN or self-host it, and wire it into the page yourself via
`@HtmlDocConfig`. `@HtmlDocConfig` is resolved per endpoint / per
resource-class hierarchy — a mixin cannot inje [...]
+```java
+@Rest(path="/releases", mixins=DataTablesMixin.class)
+@HtmlDocConfig(
+
stylesheet="$S{juneau.datatables.cssUrl:https://cdn.datatables.net/2.1.8/css/dataTables.dataTables.min.css}",
+ head={
+ "<script
src='$S{juneau.datatables.jqueryUrl:https://code.jquery.com/jquery-3.7.1.min.js}'></script>",
+ "<script
src='$S{juneau.datatables.jsUrl:https://cdn.datatables.net/2.1.8/js/dataTables.min.js}'></script>",
+ "<script src='servlet:/juneau-datatables.js'></script>"
+ }
+)
+public class ReleasesResource extends BasicRestServlet {
+ @RestGet
+ public Table getReleases() {
+ return DataTablesTable.of("releases", releases, Release.class);
+ }
+}
+```
+The URLs are SVL-resolvable, so the DataTables distribution can be overridden
per environment without code changes. `DataTablesMixin` exposes
`JQUERY_CDN_URL` / `DATATABLES_JS_CDN_URL` / `DATATABLES_CSS_CDN_URL` constants
documenting known-good CDN coordinates.
+:::
\ No newline at end of file
diff --git a/pages/topics/10.31.03.HtmlPredefinedWidgets.md
b/pages/topics/10.31.03.HtmlPredefinedWidgets.md
index 4ad152c968..8782409ebd 100644
--- a/pages/topics/10.31.03.HtmlPredefinedWidgets.md
+++ b/pages/topics/10.31.03.HtmlPredefinedWidgets.md
@@ -80,7 +80,7 @@ It renders the following popup-box:
menu-item drop-down form for entering search/view/sort arguments.
The variable it resolves is `$W{QueryMenuItem}`.
-This widget is designed to be used in conjunction with the <a
href="/site/apidocs/org/apache/juneau/rest/server/converter/Queryable.html"
target="_blank">Queryable</a> converter, although implementations can process
the query parameters themselves if they wish to do so by using the <a
href="/site/apidocs/org/apache/juneau/rest/server/httppart/RequestQueryParamList.html#getSearchArgs()"
target="_blank">RequestQueryParamList.getSearchArgs()</a> method to retrieve
the arguments and process [...]
+This widget is designed to be used in conjunction with the <a
href="/site/apidocs/org/apache/juneau/rest/server/converter/Queryable.html"
target="_blank">Queryable</a> converter, although implementations can process
the query parameters themselves if they wish to do so by parsing the request
through <a
href="/site/apidocs/org/apache/juneau/rest/server/converter/NativeQueryProtocol.html"
target="_blank">NativeQueryProtocol</a>
(`NativeQueryProtocol.INSTANCE.parse(req)` returns the normali [...]
Neither of the currently-shipping petstore resources pairs this widget with
the `Queryable` converter, so the following is a
self-contained, minimal illustrative example rather than a citation of an
existing class:
diff --git a/pages/topics/27.V10MigrationGuide.md
b/pages/topics/27.V10MigrationGuide.md
index 20d492d510..e7066a6e95 100644
--- a/pages/topics/27.V10MigrationGuide.md
+++ b/pages/topics/27.V10MigrationGuide.md
@@ -645,6 +645,37 @@ These are new in `juneau-rest-common` and replace the
corresponding HC 4.5 / `or
`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` [...]
+## Query-Protocol Reshape (`Queryable` + new `QueryProtocol` SPI)
+
+The `Queryable` REST response converter — which parsed the Juneau-native `&s=`
/ `&v=` / `&o=` / `&p=` / `&l=` query parameters and ran the shared
`ObjectSearcher` / `ObjectSorter` / `ObjectViewer` / `ObjectPaginator` engine —
was decoupled into a pluggable **query-protocol** SPI so the same engine can be
driven from other client wire contracts (e.g. DataTables server-side
processing). Two source-incompatible changes come out of this reshape.
+
+### `Queryable` reshaped onto a protocol SPI (behavior-preserving)
+
+`org.apache.juneau.rest.server.converter.Queryable` is no longer a
self-contained converter; it is now a thin subclass of a new generic converter,
`ProtocolQueryable`, hard-wired to the new `NativeQueryProtocol`. The new SPI
in `org.apache.juneau.rest.server.converter` is:
+
+| New type | Role |
+|-----|-----|
+| `QueryProtocol` | SPI: `QueryArgs parse(RestRequest)` + `Object
wrap(RestRequest, QueryResult)` (plus a `default String swaggerParams()` hook).
|
+| `QueryArgs` / `QueryResult` | Normalized, protocol-agnostic query arguments
and result (data + `recordsTotal` / `recordsFiltered` counts). |
+| `NativeQueryProtocol` | The historical `s/v/o/p/l` parse + bare-result wrap
(extracted verbatim from the old `Queryable` / `RequestQueryParamList`).
Exposed as a stateless `NativeQueryProtocol.INSTANCE`. |
+| `ProtocolQueryable` | The generic converter: resolves a `QueryProtocol` from
a per-resource `QueryableSettings` bean (default = native), then `parse →
engine → wrap`. |
+| `QueryableSettings` | Per-resource selector bean (bean-store resolved,
mirroring `IntrospectableSettings`) choosing the active protocol and DataTables
hardening knobs. |
+
+**Migration:** none for the common case — `@Rest(converters=Queryable.class)`
still behaves byte-for-byte identically (native params, bare filtered result),
and the `Queryable.SWAGGER_PARAMS` constant is unchanged. Only code that
**subclassed** `Queryable` and overrode its old fused `convert(RestRequest,
Object)` body needs to react: that logic now lives in
`ProtocolQueryable.convert(...)` and the `NativeQueryProtocol` parse/wrap
methods. To speak a non-native protocol, switch the resour [...]
+
+### `RequestQueryParamList` native-arg accessors removed
+
+The four public native-protocol-shaped accessors on
`org.apache.juneau.rest.server.httppart.RequestQueryParamList` were removed
(their parsing moved fully behind `NativeQueryProtocol`):
+
+| Removed (9.x) | Replacement (10.0) |
+|-----|-----|
+| `RequestQueryParamList#getSearchArgs()` |
`NativeQueryProtocol.INSTANCE.parse(req).getSearch()` |
+| `RequestQueryParamList#getSortArgs()` |
`NativeQueryProtocol.INSTANCE.parse(req).getSort()` |
+| `RequestQueryParamList#getViewArgs()` |
`NativeQueryProtocol.INSTANCE.parse(req).getView()` |
+| `RequestQueryParamList#getPageArgs()` |
`NativeQueryProtocol.INSTANCE.parse(req).getPage()` |
+
+`NativeQueryProtocol.INSTANCE.parse(req)` returns a `QueryArgs` whose
`getSearch()` / `getSort()` / `getView()` / `getPage()` accessors return the
same `SearchArgs` / `SortArgs` / `ViewArgs` / `PageArgs` values (wrapped in
`Optional`) the old methods produced. Note also that the vestigial `&i=`
(ignore-case) parameter — listed in the old `Queryable` javadoc but never
actually parsed — is gone from the documented native parameter set.
+
## Format-Control Round-Trip Hardening
Closes out the format-control extension work described in the other
Format-Control sections with a cross-serializer/parser round-trip test matrix
and 18 production bug fixes. The breaking surface is narrow: two API signature
widenings on `TemporalFormat`, plus a wire-format change on three binary
serializers at non-`NOT_SET` `BinaryFormat` values.
diff --git a/src/pages/about.md b/src/pages/about.md
index 9b197c9753..3da4f80e68 100644
--- a/src/pages/about.md
+++ b/src/pages/about.md
@@ -66,6 +66,7 @@ The Juneau ecosystem consists of the following parts. A few
rows are **grouped f
|
[juneau-rest-server-metrics-micrometer](/docs/topics/RestServerMicrometerMetrics)
| Micrometer integration for REST server metrics. |
| [juneau-rest-server-tracing-otel](/docs/topics/RestServerOtelTracing) |
OpenTelemetry tracing integration for REST server. |
|
[juneau-rest-server-management-logging](/docs/topics/RestServerManagementLogging)
| Management and logging surface — dynamic log-level control, log tail, and
audit logging. |
+| [juneau-rest-server-datatables](/docs/topics/Converters#query-protocols) |
DataTables server-side-processing query protocol adapter (opt-in). |
| [juneau-rest-server-rdf](/docs/topics/RestServerRdf) | Predefined REST
resource config adding RDF (Jena) marshalling support. |
| [juneau-rest-server-reactive](/docs/topics/RestServerReactive) | Reactive
(Project Reactor / RxJava) endpoint support. |
| [juneau-rest-server-reactive-reactor](/docs/topics/RestServerReactive) |
Project Reactor / RxJava 3 / Reactive-Streams `Publisher` adapters layered on
juneau-rest-server-reactive. |