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 ba75ca38dd Add fluent programmatic builder API for REST resources and 
mixins
ba75ca38dd is described below

commit ba75ca38dde0500e710aef5194c478663c2eef4e
Author: James Bognar <[email protected]>
AuthorDate: Mon Jun 1 14:57:24 2026 -0400

    Add fluent programmatic builder API for REST resources and mixins
    
    Reintroduces a public, fluent builder surface (RestBuilder / 
AbstractRestBuilder)
    for configuring @Rest resources and mixins programmatically (the Spring 
@Bean use
    case) with builder-set values winning over @Rest annotation values.
    
    - RestBuilder<SELF> / AbstractRestBuilder<R, SELF>: full self-type CRTP 
spine
      (the builder is the override bag); 55 @Rest members + mdcAsyncPropagation 
+
      the generic set() escape hatch.
    - Three flavor builders (RestServlet/RestResource/RestMixin) leave SELF 
open for
      true covariant chaining, each with a concrete DefaultBuilder<R> leaf.
    - Constructor trio (no-arg + Foo(RestBuilder) + Foo.Builder) with a 
package-private
      restBuilder stash; RestContext.Args carries it and RestContext prepends a
      synthesized @Rest so builder values beat annotations (rung-1 precedence).
    - OQ-11 mirror-and-forward for the worker-backed multi-flavor capabilities
      (FaviconMixin -> FaviconProvider, VersionMixin -> VersionProvider) via
      composition; WellKnownMixin/SeoMixin re-parented for a uniform surface.
    - BeanInstantiator exact-type builder preference (Option D): strict-typed 
builder
      candidates are preferred and weak supertype-only candidates are declined 
when a
      usable direct constructor exists, resolving the builder(Class) 
autodetection
      collision in mixin sub-context instantiation.
    
    Adds RestBuilder_Test and BeanInstantiator_OptionD_Test; updates the 
heuristic-
    pinning BeanInstantiator_Test.w09 to the new stricter selection. Also adds
    constructor-rationale Javadoc to the worker+builder constructors.
---
 pages/release-notes/9.5.0.md | 182 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 136 insertions(+), 46 deletions(-)

diff --git a/pages/release-notes/9.5.0.md b/pages/release-notes/9.5.0.md
index 1c46e3c3d2..cd60d195bb 100644
--- a/pages/release-notes/9.5.0.md
+++ b/pages/release-notes/9.5.0.md
@@ -6,7 +6,7 @@ title: "Release 9.5.0"
 
 **Date:** TBD
 
-Juneau 9.5.0 is a minor release with native OpenAPI 3.1 emission (alongside 
Swagger v2, composed via the new four-class `org.apache.juneau.rest.docs` mixin 
pack — `BasicSwaggerResource` / `BasicSwaggerUiResource` / 
`BasicOpenApiResource` / `BasicRedocResource` — that replaces the 
previously-considered `apiFormat` string knob), native TOML and YAML support, 
BSON (Binary JSON) support for MongoDB-interoperable binary serialization, CBOR 
(Concise Binary Object Representation) per RFC 8949 f [...]
+Juneau 9.5.0 is a minor release with native OpenAPI 3.1 emission (alongside 
Swagger v2, composed via the new four-class `org.apache.juneau.rest.docs` mixin 
pack — `SwaggerMixin` / `SwaggerUiMixin` / `OpenApiMixin` / `RedocMixin` — that 
replaces the previously-considered `apiFormat` string knob), native TOML and 
YAML support, BSON (Binary JSON) support for MongoDB-interoperable binary 
serialization, CBOR (Concise Binary Object Representation) per RFC 8949 for IoT 
and constrained environme [...]
 
 ### Security
 
@@ -1451,7 +1451,7 @@ See [YAML Basics](/docs/topics/YamlBasics) for full 
documentation.
   utest suite (124k+ tests) runs at the same wall-clock as before.
 - Acceptance test: the full `BasicRestServlet` OpenAPI 3.1 document (six 
api-docs URLs + full
   components.schemas set) now round-trips JSON → YAML → JSON cleanly. 
Previously
-  `OpenApiYamlRoundTrip_Test#c01` had to scope to a single 
`BasicOpenApiResource` mount via
+  `OpenApiYamlRoundTrip_Test#c01` had to scope to a single `OpenApiMixin` 
mount via
   `noInherit={"mixins"}` to dodge the underflow; that workaround has been 
removed.
 
 #### Direct Iterator/Iterable/Stream/Enumeration Serialization
@@ -2308,8 +2308,13 @@ capability classes (it is retained only on the 
convenience-bundle bases that hav
 **New `RestMixin` base (opt-in).** A third base class 
`org.apache.juneau.rest.servlet.RestMixin` joins
 `RestServlet` and `RestResource` to complete the triad. It is **opt-in** — a 
plain `@Rest` POJO remains
 fully valid as a mixin or child via annotation-only configuration; extending 
`RestMixin` is a
-convenience and does not change composition semantics. (The fluent 
`RestBuilder` programmatic-config
-surface from TODO-143 is **not** part of this release and remains deferred.)
+convenience and does not change composition semantics. Beyond the fluent 
builder surface it shares with
+`RestServlet` / `RestResource` (see the builder-API entry below), `RestMixin` 
adds **`getHostContext()`**,
+which returns the host (mixed-into) resource's `RestContext` — backed by the 
mixin sub-context's parent
+linkage, so it is usable at config time and does not depend on an in-flight 
request — letting a mixin op
+introspect the host (e.g. enumerate the host's child resources for a 
navigation page) rather than its own
+childless sub-context. It returns `null` when a `RestMixin` subclass is 
instantiated standalone rather than
+composed via `@Rest(mixins=...)`.
 
 **Op-interfaces deleted; replaced by single-responsibility op-mixins.** 
`BasicRestOperations` and
 `BasicGroupOperations` are **removed**. Their endpoints are now true 
`@Rest(mixins=...)` mixins —
@@ -2324,25 +2329,110 @@ navigation page retains its `@HtmlDocConfig` chrome (a 
mixin op runs in its own
 lose the host's page decoration).
 
 **Favicon reconciliation.** The legacy `getFavIcon` op (which served 
`REST/favicon` → `images/juneau.png`
-through static files) is dropped in favor of the single convention 
`FaviconMixin`, which serves a
-classpath ICO (`/juneau-favicon.ico`) with a 30-day `Cache-Control`. This is a 
behavior change for the
-default favicon bytes and the configuration key.
-
-**Per-capability flavor fill-in (delegate-bean model).** Capabilities where 
standalone or routed-child
-deployment is a real use case gain their missing flavors as **independent 
classes** that delegate to a
-shared worker bean / mixin instance (so the forms cannot drift). New 
child-resource flavors:
+through static files) is dropped in favor of a `FaviconProvider`-backed flavor 
set: the flavor-neutral
+`FaviconProvider` worker bean holds the icon bytes + `Cache-Control` value and 
the serve logic, and the
+independent `FaviconMixin` (mixin) / `FaviconResource` (child) / 
`FaviconServlet` (servlet) flavors each
+hold a `FaviconProvider` and delegate to it. The default serves a classpath 
ICO (`/juneau-favicon.ico`)
+with a 30-day `Cache-Control` (`max-age=2592000, public`). This is a behavior 
change for both the default
+favicon bytes and the configuration key.
+
+**Per-capability flavor fill-in (flavor-neutral worker beans).** Capabilities 
where standalone or
+routed-child deployment is a real use case gain their missing flavors as 
**independent classes** that each
+delegate to a **flavor-neutral worker bean** — never to another flavor — so 
the forms cannot drift. The
+new worker beans are `FaviconProvider` / `VersionProvider` (in 
`rest.convention`), `AdminProvider` (in
+`rest.ops`), `HealthAggregator` (in `rest.health`), and the four view-engine 
raw-template dispatchers
+`JspDispatcher` / `MustacheDispatcher` / `ThymeleafDispatcher` / 
`FreemarkerDispatcher`; the static-files
+flavors resolve the existing `StaticFiles` worker bean from the request context
+(`RestContext.getStaticFiles()`) instead of holding a mixin instance. New 
child-resource flavors:
 `StaticFilesResource`, `VersionResource`, `AdminResource`, `HealthResource`, 
plus a `ViewResource`
 abstract base and per-engine `JspResource` / `MustacheResource` / 
`ThymeleafResource` /
 `FreemarkerResource`; new favicon flavors `FaviconServlet` and 
`FaviconResource`. `HealthServlet` /
-`HealthMixin` / `HealthResource` all delegate to a shared `HealthAggregator` 
worker bean (OQ-5 split of
-the former `BasicHealthResource`). All other capabilities (Swagger, SwaggerUi, 
OpenApi, Redoc,
-RouteIndex, Error, Stats, Htdoc, WellKnown, Seo) remain mixin-only.
+`HealthMixin` / `HealthResource` all delegate to a shared `HealthAggregator` 
(OQ-5 split of the former
+`BasicHealthResource`). All other capabilities (Swagger, SwaggerUi, OpenApi, 
Redoc, RouteIndex, Error,
+Stats, Htdoc, WellKnown, Seo) remain mixin-only.
 
 **`RestRequest.getStaticFiles()` removed.** The request-level forwarder is 
deleted; obtain the active
 `StaticFiles` bean via `RestContext.getStaticFiles()` (e.g. 
`req.getContext().getStaticFiles()`) or
 bean-store injection. `FileVar`, `Widget`, and the static-files flavors are 
repointed accordingly.
 `RestContext.getStaticFiles()` is unchanged.
 
+**Route-index endpoint now content-negotiated.** `RouteIndexMixin` 
(`/options`) returns a
+`RouteDescriptions` POJO instead of writing JSON directly, so the listing is 
now content-negotiated
+through the host's configured serializers: `Accept: text/html` renders a 
browsable table with clickable
+route links, while `application/json` / `text/xml` clients receive the same 
entries in their requested
+format (mirroring `NavigationMixin.getChildren(...)`). Because it now relies 
on the host's serializers,
+the host **must have serializers configured** (e.g. via `BasicUniversalConfig` 
or a `Basic*` servlet
+base) — a bare `@Rest` host with no serializers can no longer 
content-negotiate the listing, whereas the
+former JSON-only op did not require them. The historical `/routes` alias 
remains reachable via
+`-Djuneau.routeindex.path=routes`.
+
+#### Fluent programmatic builder API — `RestBuilder` / `AbstractRestBuilder` 
self-type CRTP (TODO-143)
+
+A public, fluent builder surface lets a `@Rest` resource, child resource, or 
mixin be configured
+**programmatically** — the primary use case being instantiating a configured 
resource bean in a Spring
+`@Bean` method — instead of (or layered over) the `@Rest` annotation. 
Builder-supplied values take
+**precedence** over the class's own `@Rest` annotation members.
+
+**`RestBuilder<SELF>` config surface + `AbstractRestBuilder<R, SELF>` base 
(full self-type CRTP).** The
+public interface `org.apache.juneau.rest.RestBuilder<SELF extends 
RestBuilder<SELF>>` declares one fluent
+setter per `@Rest` member, plus the programmatic-only 
`mdcAsyncPropagation(boolean)` knob and a
+`set(String, Object)` forward-compat escape hatch. The shared abstract base
+`AbstractRestBuilder<R, SELF extends AbstractRestBuilder<R, SELF>>` implements 
every setter once — recording
+into a backing `RestAnnotation.Builder` override bag and returning `self()` — 
and leaves the `SELF` self-type
+**open** so a builder subclass's bespoke setters chain with true covariant 
returns (Option B / CRTP, aligned
+with the project-wide `SELF` / `self()` convention).
+
+**Per-flavor builders with a concrete `DefaultBuilder<R>` leaf.** Each base 
class exposes its own self-typed
+flavor builder — `RestServlet.Builder<R, SELF>`, `RestResource.Builder<R, 
SELF>`, and
+`RestMixin.Builder<R, SELF>` — together with a concrete `DefaultBuilder<R>` 
leaf. The static factory
+`RestServlet.builder(MyRest.class)` (and the `RestResource` / `RestMixin` 
equivalents) returns the
+`DefaultBuilder<R>`, so the common, non-subclassed path never has to spell two 
type parameters:
+
+```java
+@Bean
+public MyRest myRest() {
+    return RestServlet.builder(MyRest.class)
+        .path("/foo")
+        .allowedHeaderParams("foo")
+        .build();
+}
+```
+
+A resource may also add a one-line `static Builder<MyRest> builder() { return 
RestServlet.builder(MyRest.class); }`
+sugar so callers can write `MyRest.builder().path("/foo")....build()`.
+
+**Constructor trio + builder-beats-annotation precedence.** Every family base 
provides the constructor trio:
+a no-arg constructor, a `Foo(RestBuilder)` builder-injection constructor, and 
a `Foo.Builder`. `build()`
+stashes the builder onto the produced instance (a package-private 
`restBuilder` field read non-reflectively
+via `getRestBuilder()`). At `RestContext` construction the stashed builder's 
override bag is turned into a
+**synthetic `@Rest` annotation prepended as the most-derived entry** of the 
resource's annotation chain, so
+builder-set values win over the class's own `@Rest` members (rung 1 of the 
existing override-resolution
+chain). Collection-valued members **replace** the annotation value rather than 
merging.
+
+**Mirror-and-forward builders for worker-backed capabilities (OQ-11).** For a 
multi-flavor capability whose
+logic lives in a flavor-neutral worker bean, the flavor builder **mirrors the 
worker bean's builder methods on
+its own surface and forwards** into the worker's builder, while inheriting the 
full `RestBuilder` surface from
+`RestMixin.Builder`. For example `FaviconMixin.create()` mirrors `bytes` / 
`classpath` / `cacheControl` into
+`FaviconProvider.Builder` and inherits `path` / `roleGuard` / etc.; 
`VersionMixin` mirrors `VersionProvider`
+the same way. This is how the three flavors share capability config without a 
shared flavor-builder base class
+(Java single inheritance forbids one — each flavor builder already extends its 
REST builder base):
+
+```java
+@Bean
+FaviconMixin favicon() {
+    return FaviconMixin.create()
+        .classpath("/myapp/icon.ico")   // mirrored → FaviconProvider.Builder
+        .path("/branding")              // inherited RestBuilder surface
+        .build();
+}
+```
+
+**Bean-instantiation preference (internal).** So the new generic 
`builder(Class)` factories don't hijack
+framework default instantiation, `BeanInstantiator` now prefers a builder that 
builds the **exact requested
+type** (or a usable direct constructor) over one that only promises a 
supertype. A flavor's own `create()` /
+nested `Builder` therefore wins over the inherited generic `builder(Class)` 
(whose `build()` erases to a base
+class), and a plain resource/mixin carrying only the inherited builder falls 
through to its no-arg constructor.
+
 #### Opt-in lazy `@Rest(children=...)` materialization (TODO-121)
 
 Parent resources annotated with `@Rest(lazyChildren=true)` now defer the 
construction of each child
@@ -3022,16 +3112,16 @@ The variable map:
 
 | Mixin | SVL variable | Default mount |
 |---|---|---|
-| `BasicSwaggerResource` | `${juneau.swagger.path:api}` | `/api/*` |
-| `BasicSwaggerUiResource` | `${juneau.swaggerui.path:swagger}` | `/swagger/*` 
|
-| `BasicOpenApiResource` | `${juneau.openapi.path:openapi}` | `/openapi/*`, 
`/openapi.json`, `/openapi.yaml` |
-| `BasicRedocResource` | `${juneau.redoc.path:redoc}` | `/redoc/*` |
-| `BasicStaticFilesResource` | `${juneau.staticfiles.path:static}` | 
`/static/*` |
-| `BasicVersionResource` | `${juneau.version.path:version}` | `/version` |
-| `BasicEchoResource` | `${juneau.echo.path:echo}` | `/echo/*` |
-| `BasicAdminResource` | `${juneau.admin.path:admin}` | `/admin/threads`, 
`/admin/heap`, `/admin/cache/flush`, `/admin/ratelimit` |
-| `BasicRouteIndexResource` | `${juneau.routeindex.path:options}` | `/options` 
|
-| `BasicJspResource` | `${juneau.jsp.path:jsp}` | `/jsp/*` |
+| `SwaggerMixin` | `${juneau.swagger.path:api}` | `/api/*` |
+| `SwaggerUiMixin` | `${juneau.swaggerui.path:swagger}` | `/swagger/*` |
+| `OpenApiMixin` | `${juneau.openapi.path:openapi}` | `/openapi/*`, 
`/openapi.json`, `/openapi.yaml` |
+| `RedocMixin` | `${juneau.redoc.path:redoc}` | `/redoc/*` |
+| `StaticFilesMixin` | `${juneau.staticfiles.path:static}` | `/static/*` |
+| `VersionMixin` | `${juneau.version.path:version}` | `/version` |
+| `EchoMixin` | `${juneau.echo.path:echo}` | `/echo/*` |
+| `AdminMixin` | `${juneau.admin.path:admin}` | `/admin/threads`, 
`/admin/heap`, `/admin/cache/flush`, `/admin/ratelimit` |
+| `RouteIndexMixin` | `${juneau.routeindex.path:options}` | `/options` |
+| `JspMixin` | `${juneau.jsp.path:jsp}` | `/jsp/*` |
 
 Example — relocate the Swagger UI mount to `/docs/swagger-ui`:
 
@@ -3042,11 +3132,11 @@ java -Djuneau.swaggerui.path=docs/swagger-ui -jar 
my-app.jar
 Three mixins remain hardcoded because their mount paths are 
specification-fixed and a runtime
 override would break spec-compliant clients:
 
-- `BasicFaviconResource` — `/favicon.ico` (browser convention + WHATWG HTML 
`rel="icon"` default).
-- `BasicSeoResource` — `/robots.txt` (RFC 9309 Robots Exclusion Protocol) and 
`/sitemap.xml`
+- `FaviconMixin` — `/favicon.ico` (browser convention + WHATWG HTML 
`rel="icon"` default).
+- `SeoMixin` — `/robots.txt` (RFC 9309 Robots Exclusion Protocol) and 
`/sitemap.xml`
   (sitemaps.org protocol). The two endpoints sit on separate handler methods, 
not a multi-path
   array, so they remain individually pinned.
-- `BasicWellKnownResource` — `/.well-known/security.txt` (RFC 8615 well-known 
URIs + RFC 9116
+- `WellKnownMixin` — `/.well-known/security.txt` (RFC 8615 well-known URIs + 
RFC 9116
   security.txt).
 
 **Migration note — multi-path collapse:** four mixins that previously declared 
multiple paths
@@ -3057,10 +3147,10 @@ default:
 
 | Mixin | Primary default | Removed secondary alias(es) | Migration |
 |---|---|---|---|
-| `BasicStaticFilesResource` | `/static/*` | `/htdocs/*` | 
`-Djuneau.staticfiles.path=htdocs` |
-| `BasicVersionResource` | `/version` | `/info`, `/about` | 
`-Djuneau.version.path=info` (or `about`) |
-| `BasicEchoResource` | `/echo/*` | `/debug/echo/*` | 
`-Djuneau.echo.path=debug/echo` |
-| `BasicRouteIndexResource` | `/options` | `/routes` | 
`-Djuneau.routeindex.path=routes` |
+| `StaticFilesMixin` | `/static/*` | `/htdocs/*` | 
`-Djuneau.staticfiles.path=htdocs` |
+| `VersionMixin` | `/version` | `/info`, `/about` | 
`-Djuneau.version.path=info` (or `about`) |
+| `EchoMixin` | `/echo/*` | `/debug/echo/*` | `-Djuneau.echo.path=debug/echo` |
+| `RouteIndexMixin` | `/options` | `/routes` | 
`-Djuneau.routeindex.path=routes` |
 
 Deployers who relied on a secondary default must either set the SVL override 
at startup or
 compose a second mixin instance with the override. The default 
`BasicStaticFiles` classpath
@@ -3120,31 +3210,31 @@ The api-docs surface is now four sibling 
`@Rest(mixins=...)` mixins in the new `
 
 | Mixin | Default `paths` | Owns |
 |---|---|---|
-| `BasicSwaggerResource` | `/api` | Swagger v2 spec + `SwaggerUI` swap. 
Standard content negotiation. |
-| `BasicSwaggerUiResource` | `/swagger` | HTML-first mount; 
`@Rest(defaultAccept="text/html")` so bare browser requests render the 
Swagger-UI view. Transitively pulls in `BasicSwaggerResource`. |
-| `BasicOpenApiResource` | `/openapi`, `/openapi.json`, `/openapi.yaml` | 
OpenAPI 3.1 spec + `RedocUI` swap on `/openapi`. The `.json` and `.yaml` paths 
are **format-pinned** — they ignore the request `Accept` header and always emit 
the file extension's wire format (implemented via 
`RestResponse.getDirectWriter(...)`, not content negotiation, so the pin 
survives `Accept: text/html`). Mixin declares 
`@Rest(serializers={YamlSerializer.class})` so YAML is available for the 
`/openapi` conten [...]
-| `BasicRedocResource` | `/redoc` | HTML-first mount; 
`@Rest(defaultAccept="text/html")`. Transitively pulls in 
`BasicOpenApiResource`. |
+| `SwaggerMixin` | `/api` | Swagger v2 spec + `SwaggerUI` swap. Standard 
content negotiation. |
+| `SwaggerUiMixin` | `/swagger` | HTML-first mount; 
`@Rest(defaultAccept="text/html")` so bare browser requests render the 
Swagger-UI view. Transitively pulls in `SwaggerMixin`. |
+| `OpenApiMixin` | `/openapi`, `/openapi.json`, `/openapi.yaml` | OpenAPI 3.1 
spec + `RedocUI` swap on `/openapi`. The `.json` and `.yaml` paths are 
**format-pinned** — they ignore the request `Accept` header and always emit the 
file extension's wire format (implemented via 
`RestResponse.getDirectWriter(...)`, not content negotiation, so the pin 
survives `Accept: text/html`). Mixin declares 
`@Rest(serializers={YamlSerializer.class})` so YAML is available for the 
`/openapi` content-negoti [...]
+| `RedocMixin` | `/redoc` | HTML-first mount; 
`@Rest(defaultAccept="text/html")`. Transitively pulls in `OpenApiMixin`. |
 
 Pick the mixins you want and the URL surface follows. Three common 
compositions:
 
 ```java
 // OpenAPI 3.1 spec only — /openapi, /openapi.json, /openapi.yaml.
-@Rest(path="/api", mixins=BasicOpenApiResource.class)
+@Rest(path="/api", mixins=OpenApiMixin.class)
 public class ApiResource extends RestServlet { ... }
 
-// OpenAPI 3.1 + Redoc UI — pulls BasicOpenApiResource in transitively.
-@Rest(path="/api", mixins=BasicRedocResource.class)
+// OpenAPI 3.1 + Redoc UI — pulls OpenApiMixin in transitively.
+@Rest(path="/api", mixins=RedocMixin.class)
 public class ApiResource extends RestServlet { ... }
 
-// Everything (post-9.5.0 default for BasicRestServlet / BasicRestObject).
-@Rest(path="/api", mixins={BasicSwaggerUiResource.class, 
BasicRedocResource.class})
+// Everything (post-9.5.0 default for BasicRestServlet / BasicRestResource).
+@Rest(path="/api", mixins={SwaggerUiMixin.class, RedocMixin.class})
 public class ApiResource extends RestServlet { ... }
 // Serves: /api, /swagger, /openapi, /openapi.json, /openapi.yaml, /redoc
 ```
 
 Transitive resolution dedupes by class identity (`LinkedHashSet` in the 
framework's `collectRestMixins(...)` walk), so listing both UI mixins doesn't 
double-instantiate the spec mixins. Parent-chain aggregation also works — a 
child class's `@Rest(mixins=...)` unions with the parent's.
 
-`BasicRestServlet` and `BasicRestObject` migrated to declare 
`@Rest(mixins={BasicSwaggerUiResource.class, BasicRedocResource.class})` so 
subclasses get all six api-docs URLs by default. Apps that want to opt out 
(e.g. to mount only OpenAPI) can use `@Rest(noInherit={"mixins"}, mixins=...)` 
to cut off the inherited docs mixins.
+`BasicRestServlet` and `BasicRestResource` migrated to declare 
`@Rest(mixins={SwaggerUiMixin.class, RedocMixin.class})` so subclasses get all 
six api-docs URLs by default. Apps that want to opt out (e.g. to mount only 
OpenAPI) can use `@Rest(noInherit={"mixins"}, mixins=...)` to cut off the 
inherited docs mixins.
 
 **Breaking changes (TODO-74):**
 
@@ -3154,8 +3244,8 @@ Transitive resolution dedupes by class identity 
(`LinkedHashSet` in the framewor
 | `juneau.rest.apiFormat` system property | Removed. No replacement — apps 
that toggled this at runtime should pick mixins at compile time. |
 | `RestContext.getApiFormat()` | Removed. |
 | `RestServerConstants.API_FORMAT_SWAGGER` / `_OPENAPI` / `_BOTH` / 
`SYSPROP_apiFormat` / `PROPERTY_apiFormat` | Removed. |
-| `BasicRestOperations.getSwagger(...)` / `getOpenApi(...)` | Removed from the 
interface. `BasicRestServlet` / `BasicRestObject` mount these via 
`BasicSwaggerResource` / `BasicOpenApiResource` instead. |
-| `BasicGroupOperations.getChildrenSwagger(...)` / `getChildrenOpenApi(...)` 
(the `?Swagger` / `?OpenApi` query mirrors on group resources) | Removed. Hit 
`/api`, `/swagger`, `/openapi`, or `/redoc` directly — they are always mounted 
on `BasicRestServletGroup` / `BasicRestObjectGroup`. |
+| `BasicRestOperations.getSwagger(...)` / `getOpenApi(...)` | Removed from the 
interface. `BasicRestServlet` / `BasicRestResource` mount these via 
`SwaggerMixin` / `OpenApiMixin` instead. |
+| `BasicGroupOperations.getChildrenSwagger(...)` / `getChildrenOpenApi(...)` 
(the `?Swagger` / `?OpenApi` query mirrors on group resources) | Removed. Hit 
`/api`, `/swagger`, `/openapi`, or `/redoc` directly — they are always mounted 
on `BasicRestServletGroup` / `BasicRestResourceGroup`. |
 | `BasicGroupOperations.HasSwaggerQueryParam` / `HasOpenApiQueryParam` matcher 
inner classes | Removed (no consumers left). |
 
 Migration sketch:
@@ -3166,14 +3256,14 @@ Migration sketch:
 public class MyApi extends BasicRestServlet { ... }
 
 // 9.5.0:
-@Rest(noInherit={"mixins"}, mixins=BasicRedocResource.class)   // opt out of 
Swagger
+@Rest(noInherit={"mixins"}, mixins=RedocMixin.class)   // opt out of Swagger
 public class MyApi extends BasicRestServlet { ... }
 // or extend RestServlet directly and pick what you want:
-@Rest(mixins=BasicRedocResource.class)
+@Rest(mixins=RedocMixin.class)
 public class MyApi extends RestServlet implements BasicUniversalConfig { ... }
 ```
 
-Apps that subclass `BasicRestServlet` / `BasicRestObject` without setting 
`apiFormat` or relying on the query mirrors get the new behavior (six api-docs 
URLs instead of one) automatically.
+Apps that subclass `BasicRestServlet` / `BasicRestResource` without setting 
`apiFormat` or relying on the query mirrors get the new behavior (six api-docs 
URLs instead of one) automatically.
 
 #### Static-Files Mixin (TODO-75)
 

Reply via email to