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 7388618b64 docs: dynamic child REST resources + inject-aware 
microservice + next-gen REST client topics
7388618b64 is described below

commit 7388618b642074d1a08f3a05332d2f1ce038cc3c
Author: James Bognar <[email protected]>
AuthorDate: Fri May 15 10:44:59 2026 -0400

    docs: dynamic child REST resources + inject-aware microservice + next-gen 
REST client topics
    
    Co-authored-by: Cursor <[email protected]>
---
 pages/release-notes/9.5.0.md                  | 189 ++++++++++++++++++++
 pages/topics/10.03.03.ChildResources.md       |  65 +++++++
 pages/topics/12.15.NextGenRestClient.md       | 237 ++++++++++++++++++++++++++
 pages/topics/14.09.InjectAwareMicroservice.md | 184 ++++++++++++++++++++
 sidebars.ts                                   |  10 ++
 5 files changed, 685 insertions(+)

diff --git a/pages/release-notes/9.5.0.md b/pages/release-notes/9.5.0.md
index d33162ed5d..154dbf38d6 100644
--- a/pages/release-notes/9.5.0.md
+++ b/pages/release-notes/9.5.0.md
@@ -1514,6 +1514,29 @@ String name
 
 ### juneau-rest-server
 
+#### Dynamic Child Resources (TODO-33)
+
+Parent resources that extend `BasicRestServletGroup` or `BasicRestObjectGroup` 
can now mount and unmount children at runtime, in addition to declaring them 
statically via `@Rest(children=…)`.
+
+```java
+@Rest(path="/root")
+public class MyServer extends BasicRestServletGroup {}
+
+var server = new MyServer();
+// ... bootstrap into Jetty / Spring Boot / MockRestClient ...
+
+server.addChild(AlphaChild.class);          // by class, path from @Rest(path)
+server.addChild(new BetaChild());           // by instance, path from 
@Rest(path)
+server.addChild("/gamma", new AlphaChild()); // explicit path override
+server.removeChild("/alpha");
+server.removeChild(AlphaChild.class);
+var keys = server.getChildResources().asMap().keySet();
+```
+
+The underlying state lives on `RestChildren`, which now holds children in a 
`volatile` copy-on-write snapshot. Route matching reads the snapshot without 
locks (preserving hot-path performance), and mutations are serialized through 
an internal write lock. `@RestInit` / `@RestPostInit` / 
`@RestPostInitChildFirst` run before `addChild` returns; `@RestDestroy` and 
`Servlet.destroy()` run on `removeChild` (recursively for grandchildren). 
Adding to an occupied path without `replace=true` throw [...]
+
+See [Child Resources](/docs/topics/ChildResources#dynamic-child-resources) for 
the full API and usage notes.
+
 #### `@RestInject` Renamed to `@Bean` (moved to `juneau-commons`)
 
 `@RestInject` has been renamed to `@Bean` and moved from 
`org.apache.juneau.rest.annotation` to
@@ -1743,6 +1766,172 @@ If you previously relied on `@Bean` (inject) overriding 
a Spring `@Bean`, you ha
 
 - **RestClient `rootUrl`**: The `rootUrl` field is now stored as a 
`Supplier<String>` internally. Code that relies on reflection to access the 
private `rootUrl` field directly (unusual but possible) will now see a 
`Supplier<String>` instead of a `String`.
 
+### juneau-microservice-core
+
+#### Inject-Aware Microservice (TODO-31)
+
+`Microservice` is now inject-aware. Every microservice owns an internal 
`WritableBeanStore`
+(from `juneau-commons`) populated from `@Configuration` classes registered on 
the builder.
+
+**New builder methods**:
+
+- `Microservice.Builder.configurations(Class<?>...)` — register one or more 
`@Configuration` classes
+  whose `@Bean` methods/fields are processed at bootstrap.
+- `Microservice.Builder.configurations(List<Class<?>>)` — same, list form.
+- `Microservice.Builder.beanStore(WritableBeanStore)` — supply an 
externally-owned store instead of
+  letting the microservice construct a fresh one. Useful for composing into a 
larger application or
+  integrating with `juneau-rest-server-springboot`.
+
+**New accessor**:
+
+- `Microservice.getBeanStore()` — never null. Contains the resolved `Args`, 
`ManifestFile`, `Config`,
+  `VarResolver`, `MicroserviceListener`, the `Microservice` instance itself, 
plus everything
+  contributed by registered `@Configuration` classes.
+
+**Lifecycle**:
+
+- `@PostConstruct` callbacks fire on beans instantiated through the inject 
framework (e.g. via
+  constructor injection in `@Bean` factory methods or 
`BeanStore.instantiate(X)`).
+- `@PreDestroy` callbacks fire on `Microservice.stop()`, which now closes the 
bean store and walks
+  every resolved bean in LIFO order. Errors are logged at `WARNING` and do not 
abort the rest of
+  the shutdown sequence.
+
+**Resolution priority** for core types (`Args`, `Config`, etc.): explicit 
builder call wins, then
+`@Bean`-supplied value, then built-in default. The final resolved value is 
registered into the bean
+store so downstream `@Bean` factory methods see the same instance that the 
`Microservice.getXxx()`
+getter returns.
+
+This change is **fully additive** — every existing builder method continues to 
work unchanged, and
+microservices that never call `.configurations(...)` behave identically to 
pre-9.5.0.
+
+See <a href="/docs/topics/MicroserviceCoreInject">Inject-Aware 
Microservice</a> for the full guide.
+
+### juneau-microservice-jetty
+
+#### Auto-Discovery of `@Rest` Servlets (TODO-31)
+
+`JettyMicroservice.createServer()` now consults the bean store for `Servlet` 
beans contributed via
+`@Configuration` classes. Any servlet whose runtime class is annotated with 
`@Rest` is automatically
+mounted at the path declared by `@Rest(path = "...")` (or `/` when no path is 
set).
+
+**`@Bean`-supplied infrastructure** — when no builder value is set, these 
types are resolved from
+the bean store:
+
+- `JettyServerFactory` — replaces `BasicJettyServerFactory` if a custom 
factory is contributed.
+- `JettyMicroserviceListener` — replaces the default no-op listener.
+- `org.eclipse.jetty.server.Server` — when present (with 
`"ServletContextHandler"` attribute set),
+  `createServer()` uses it directly and skips the `jetty.xml` factory step 
entirely. Useful for
+  tests and fully-code-driven Jetty setups.
+
+**Path-collision enforcement** — `createServer()` now tracks each servlet 
pathspec with its
+declaring source and throws a `RuntimeException` with both contributor names 
when two servlets claim
+the same path. This covers all sources: `Jetty/servlets`, `Jetty/servletMap`, 
`.servlet(...)` builder
+calls, and `@Bean`-discovered servlets. Previously silent collisions are now 
hard failures at
+startup.
+
+> **Note on `@Bean` method return types** — declare `@Bean` methods that 
produce a servlet with
+> return type `Servlet` (not the concrete subclass). Juneau's 
`BeanStore.getBeansOfType` is
+> exact-type, so a bean registered under `MyRestServlet.class` would not be 
visible to the
+> auto-mount logic which queries for `Servlet.class`.
+
+### Next-Generation REST Client and HTTP Stack (Beta)
+
+Juneau 9.5.0 introduces a new REST client and HTTP type stack under 
`org.apache.juneau.ng.*` that decouples Juneau from Apache HttpClient 4.5. The 
new stack is shipped **alongside** the existing `juneau-rest-client` / 
`juneau-rest-common` APIs — both continue to work unchanged.
+
+**Beta API**: All public types under `org.apache.juneau.ng.*` are beta and may 
change incompatibly in the next major release. For production deployments that 
require strict binary stability, continue using the classic `RestClient` / 
`juneau-rest-common` APIs until the NG stack is declared stable.
+
+#### `org.apache.juneau.ng.http` (in `juneau-rest-common`)
+
+A JDK-native replacement for the Apache HttpCore-based types in 
`juneau-rest-common`. No `httpcore` dependency in this package — all interfaces 
(`HttpHeader`, `HttpPart`, `HttpBody`, `HttpStatusLine`, `HttpResponseMessage`) 
use JDK types only.
+
+- Typed header hierarchy (`HttpStringHeader`, `HttpMediaTypeHeader`, 
`HttpMediaRangesHeader`, `HttpStringRangesHeader`, `HttpCsvHeader`, 
`HttpDateHeader`, `HttpUriHeader`, `HttpIntegerHeader`, `HttpLongHeader`, 
`HttpBooleanHeader`, `HttpEntityTagHeader`, `HttpEntityTagsHeader`) with ~73 
RFC-named header classes (`Accept`, `ContentType`, `Authorization`, …).
+- Entity / body types: `HttpBodyBean`, `StringBody`, `ByteArrayBody`, 
`StreamBody`, `FileBody`, `MultipartBody` (RFC 7578 streaming).
+- Status / response types: `HttpStatusLineBean`, `BasicHttpResponse`, 
`BasicHttpException`, ~50 named status classes (`Ok`, `Created`, `NotFound`, 
`InternalServerError`, …).
+- Remote-proxy annotations re-homed under `org.apache.juneau.ng.http.remote` 
(`@Remote`, `@RemoteGet`, `@RemotePost`, `@RemotePut`, `@RemotePatch`, 
`@RemoteDelete`, `@RemoteOp`, `@RemoteReturn`).
+
+#### `org.apache.juneau.ng.rest.client` (in `juneau-rest-client`)
+
+The transport abstraction and the new `NgRestClient` / `NgRestRequest` / 
`NgRestResponse`.
+
+- `HttpTransport` — single integration point replacing 
`org.apache.http.client.HttpClient`. Provides synchronous 
`send(TransportRequest)` and a `sendAsync(...)` default that transports can 
override for native async.
+- `TransportRequest`, `TransportResponse` (`Closeable` — owns 
connection-release hook), `TransportHeader`, `TransportBody`, 
`TransportException` — transport-layer DTOs using JDK types only.
+- `HttpTransportBuilder` / `HttpTransportProvider` SPI — `ServiceLoader`-based 
auto-discovery; passing a fully-built transport or transport builder is also 
supported.
+- `NgRestClient` — composes an `HttpTransport`; one 
serializer/parser/marshaller per client (no multi-language mode); fluent 
`get/post/put/patch/delete/head/options/formPost/multipartPost` API; remote 
proxies via `getRemote(Class)`; explicit `shutdown()` (not `Closeable`).
+- `NgRestRequest` — the single `Closeable` in the user-facing API; resolves 
URI + path data + query, runs interceptors, serializes the body, calls the 
transport.
+- `CollectionFormat` enum (`COMMA`, `PIPE`, `SPACE`, `TAB`, `REPEATED`) for 
`Iterable` / array-valued params.
+- `BodyConverter` — pluggable request-body conversion; default chain handles 
`HttpBody`, `MultipartBody`, `InputStream`, `byte[]`, `Reader`, `File`, 
`PartList`, and falls back to a `SerializedBody` that streams through the 
client's serializer.
+- `RestCallInterceptor` — `onInit` / `onConnect` / `onClose` lifecycle hooks 
(no Apache types).
+- `RestLogger` / `RestLogEntry` / `RestLogLevelResolver` / `BasicRestLogger` — 
framework-agnostic logging via `java.lang.System.Logger`, with named-template 
formatting (`{method}`, `{uri}`, `{status}`, `{reason}`, `{elapsed}`, 
`{req.headers}`, `{req.body}`, `{res.headers}`, `{res.body}`, `{error}`) and 
configurable per-level templates.
+
+#### Transport Implementations (new modules)
+
+Each new module is independent and pulls in only its own native client. The 
`HttpTransportProvider` `ServiceLoader` entries let 
`NgRestClient.create().build()` auto-discover the highest-priority transport on 
the classpath.
+
+| Module | Artifact ID | Native client |
+|---|---|---|
+| Apache HttpClient 4.5 | `juneau-ng-rest-client-apache-httpclient-45` | 
`org.apache.httpcomponents:httpclient:4.5.x` |
+| Apache HttpClient 5 | `juneau-ng-rest-client-apache-httpclient-50` | 
`org.apache.httpcomponents.client5:httpclient5` |
+| JDK `HttpClient` | `juneau-ng-rest-client-java-httpclient` | 
`java.net.http.HttpClient` (Java 11+) — zero third-party deps |
+| OkHttp | `juneau-ng-rest-client-okhttp` | `com.squareup.okhttp3:okhttp` |
+| Eclipse Jetty client | `juneau-ng-rest-client-jetty` | 
`org.eclipse.jetty:jetty-client` |
+
+Each transport module ships `*Transport`, `*TransportBuilder` (with native 
client–specific configuration accessible via cast), and `*TransportProvider`. 
Common transport-builder configuration (`connectTimeout`, `readTimeout`, 
`sslContext`, `hostnameVerifier`, `proxy`, `maxConnections`, 
`maxConnectionsPerRoute`, `followRedirects`, …) lives on `HttpTransportBuilder` 
so most callers don't need to cast.
+
+#### `juneau-rest-mock` — `org.apache.juneau.ng.rest.mock`
+
+- `MockHttpTransport` — routes `TransportRequest` directly to a Juneau 
`RestContext` without network I/O.
+- `NgMockRestClient` — extends `NgRestClient` and wires it to 
`MockHttpTransport`. Replaces the classic 
`MockRestClient`-implements-`HttpClientConnection` shim with a plain 
`HttpTransport` implementation.
+
+#### Usage Examples
+
+```java
+// Pre-built serializer/parser — configure marshalling externally
+var serializer = Json5Serializer.create().build();
+var parser = Json5Parser.create().build();
+
+// Pick a transport explicitly
+NgRestClient client = NgRestClient.create()
+    .transportBuilder(ApacheHc45Transport.create()
+        .connectTimeout(Duration.ofSeconds(10))
+        .sslContext(mySSLContext)
+        .maxConnections(50))
+    .serializer(serializer)
+    .parser(parser)
+    .rootUrl("https://api.example.com";)
+    .build();
+
+// Or let the SPI auto-discover the best transport on the classpath
+NgRestClient zeroConfig = NgRestClient.create()
+    .marshaller(Json5.DEFAULT)
+    .rootUrl("https://api.example.com";)
+    .build();
+
+// Always use try-with-resources on the request — close releases the connection
+try (var req = client.get("/users/{id}").pathData("id", 42)) {
+    var user = req.run().as(User.class);
+}
+
+// Multipart upload
+try (var req = client.multipartPost("/upload")
+        .multipartField("album", "vacation")
+        .multipartFile("photo", Path.of("/tmp/beach.jpg"), "image/jpeg")) {
+    req.run();
+}
+
+// At application shutdown
+client.shutdown();
+```
+
+#### Migration Path
+
+The classic `RestClient` / `juneau-rest-common` APIs remain fully supported 
with no behavior change. Migration is **opt-in**:
+
+1. Add the NG transport module for your preferred HTTP stack to your build.
+2. Replace `RestClient.create()` with `NgRestClient.create()` and adapt 
builder calls — most configuration (`rootUrl`, default headers/query/form/path, 
interceptors, marshaller) maps 1:1.
+3. Use try-with-resources around `NgRestRequest`; call `shutdown()` on the 
client at application shutdown.
+
+The classic stack is **not** deprecated in 9.5; the NG stack will graduate to 
stable in a future release, at which point the classic stack may be deprecated 
and eventually removed.
+
 ### juneau-bean-mcp (new module)
 
 A new bean module, `juneau-bean-mcp`, models the [Model Context 
Protocol](https://modelcontextprotocol.io/) wire format as Juneau `@Bean` 
POJOs. The beans round-trip cleanly through any Juneau serializer/parser (JSON, 
JSON5, MessagePack, CBOR, YAML, etc.) and were the foundation for 
`juneau-rest-server-mcp`.
diff --git a/pages/topics/10.03.03.ChildResources.md 
b/pages/topics/10.03.03.ChildResources.md
index 87a7c67646..e4d60daff7 100644
--- a/pages/topics/10.03.03.ChildResources.md
+++ b/pages/topics/10.03.03.ChildResources.md
@@ -37,3 +37,68 @@ Children can be nested arbitrary deep to create complex REST 
interfaces with a s
 As explained earlier, child REST objects typically extend from <a 
href="/site/apidocs/org/apache/juneau/rest/servlet/BasicRestObject.html" 
target="_blank">BasicRestObject</a> or <a 
href="/site/apidocs/org/apache/juneau/rest/servlet/BasicRestObjectGroup.html" 
target="_blank">BasicRestObjectGroup</a> and not from one of the servlet 
classes.
 They also technically don't even need to extend from those classes and can 
instead just be a normal class annotated with
 the bare-minimum <a 
href="/site/apidocs/org/apache/juneau/rest/annotation/Rest.html" 
target="_blank">@Rest</a> and <a 
href="/site/apidocs/org/apache/juneau/rest/annotation/RestOp.html" 
target="_blank">@RestOp</a> annotations.
+
+## Dynamic Child Resources
+
+In addition to declaring children statically via `@Rest(children=…)`, parent 
resources that extend
+<a 
href="/site/apidocs/org/apache/juneau/rest/servlet/BasicRestServletGroup.html" 
target="_blank">BasicRestServletGroup</a>
+or <a 
href="/site/apidocs/org/apache/juneau/rest/servlet/BasicRestObjectGroup.html" 
target="_blank">BasicRestObjectGroup</a>
+can add and remove child resources at runtime.
+This is useful for plug-in architectures, integration tests, and other 
scenarios where the set of mounted endpoints is not known ahead of time.
+
+The convenience methods on the group classes delegate to <a 
href="/site/apidocs/org/apache/juneau/rest/RestChildren.html" 
target="_blank">RestChildren</a>,
+which holds children in a thread-safe, copy-on-write snapshot — reads on the 
request hot path are lock-free, while mutations are serialized through a write 
lock.
+
+:::tip Example
+```java
+@Rest(path="/root")
+public class MyServer extends BasicRestServletGroup {}
+
+@Rest(path="/alpha")
+public class AlphaChild extends BasicRestObject {
+    @RestGet("/ping")
+    public String ping() { return "alpha-pong"; }
+}
+
+var server = new MyServer();
+// ... bootstrap into Jetty / Spring Boot / MockRestClient ...
+
+// Add by class — path is derived from the child's @Rest(path) annotation.
+server.addChild(AlphaChild.class);
+
+// Add by instance — useful when the child is hand-constructed or comes from a 
bean store.
+var beta = new BetaChild();
+server.addChild(beta);
+
+// Add with an explicit path override.
+server.addChild("/gamma", new AlphaChild());
+
+// Remove by path or by class.
+server.removeChild("/alpha");
+server.removeChild(AlphaChild.class);
+
+// Inspect what is currently mounted.
+var keys = server.getChildResources().asMap().keySet();
+```
+:::
+
+### API surface
+
+| Method | Description |
+|---|---|
+| `addChild(Class<?>)` | Instantiate from the bean store (or via no-arg 
constructor) and mount at the child's `@Rest(path)`. |
+| `addChild(Object)` | Mount an existing instance at the child's 
`@Rest(path)`. |
+| `addChild(Object, boolean replace)` | Same as above but, when 
`replace=true`, atomically destroys any existing child mounted at the same 
path. |
+| `addChild(String path, Object)` | Mount an existing instance at an explicit 
path, ignoring any `@Rest(path)` on the resource. |
+| `addChild(String path, Object, boolean replace)` | Explicit-path variant 
with replace semantics. |
+| `removeChild(String path)` | Remove the child mounted at the given path. 
Returns the removed `RestContext` (or `null`). |
+| `removeChild(Class<?>)` | Remove the child whose resource is an instance of 
the given class. Returns the removed `RestContext` (or `null`). |
+| `getChildResources()` | Returns the underlying `RestChildren` for direct 
inspection. |
+
+### Lifecycle and concurrency
+
+When a child is added, its `@RestInit`, `@RestPostInit`, and 
`@RestPostInitChildFirst` hooks run before `addChild` returns.
+When a child is removed, its `@RestDestroy` hooks run and the resource's 
`Servlet.destroy()` is invoked (if applicable) — including for any 
grandchildren mounted underneath.
+
+Mutations are atomic: route matching either sees the full pre-add state or the 
full post-add state, never a partially-mounted child.
+Adding a second child at the same path without `replace=true` throws 
`IllegalStateException` to prevent silent route shadowing.
diff --git a/pages/topics/12.15.NextGenRestClient.md 
b/pages/topics/12.15.NextGenRestClient.md
new file mode 100644
index 0000000000..0a4ecd2d48
--- /dev/null
+++ b/pages/topics/12.15.NextGenRestClient.md
@@ -0,0 +1,237 @@
+---
+title: "Next-Generation REST Client (Beta)"
+slug: NextGenRestClient
+---
+
+:::warning Beta API
+All public types under `org.apache.juneau.ng.*` are **beta**. Source- and 
binary-incompatible changes
+may appear in the next major Juneau release. For production deployments that 
require strict
+binary stability, continue using the classic `RestClient` / 
`juneau-rest-common` APIs until the
+NG stack is declared stable in a future release.
+:::
+
+Juneau 9.5.0 introduces a next-generation REST client and HTTP type stack under
+`org.apache.juneau.ng.*` that **decouples Juneau from Apache HttpClient 4.5**. 
The new stack
+ships alongside the existing `juneau-rest-client` / `juneau-rest-common` APIs 
— both continue
+to work unchanged.
+
+The next-generation stack:
+
+- Uses **only JDK types** in its API surface (`org.apache.juneau.ng.http`). No 
`org.apache.http.*`
+  on any signature.
+- Introduces an `HttpTransport` abstraction so you can plug in **any HTTP 
client**
+  (Apache HC 4.5, Apache HC 5, JDK `HttpClient`, OkHttp, Jetty, or a custom 
transport)
+  without changing user code.
+- Replaces 40+ Apache HC–specific builder methods on the classic 
`RestClient.Builder` with a
+  small, focused builder. Transport-specific configuration lives on the 
**transport builder**,
+  not on `RestClient.Builder`.
+
+---
+
+## Package Layout
+
+| Package | Module | Role |
+|---|---|---|
+| `org.apache.juneau.ng.http` | `juneau-rest-common` | JDK-native HTTP types 
(`HttpHeader`, `HttpPart`, `HttpBody`, status types, ~73 RFC-named headers, ~50 
named response types, multipart, remote-proxy annotations). No `httpcore` 
dependency. |
+| `org.apache.juneau.ng.rest.client` | `juneau-rest-client` | `HttpTransport` 
abstraction, `NgRestClient` / `NgRestRequest` / `NgRestResponse`, interceptors, 
body converters, `RestLogger`. No `httpcore` dependency. |
+| `org.apache.juneau.ng.rest.mock` | `juneau-rest-mock` | `MockHttpTransport` 
and `NgMockRestClient` for in-process testing against a Juneau `RestContext`. |
+
+---
+
+## Transport Modules
+
+Each transport is a separate Maven module pulling in only its native HTTP 
client.
+The `HttpTransportProvider` `ServiceLoader` SPI auto-discovers the 
highest-priority transport
+on the classpath at `build()` time when no explicit transport is passed.
+
+| Module | Artifact ID | Native client |
+|---|---|---|
+| Apache HttpClient 4.5 | `juneau-ng-rest-client-apache-httpclient-45` | 
`org.apache.httpcomponents:httpclient:4.5.x` |
+| Apache HttpClient 5 | `juneau-ng-rest-client-apache-httpclient-50` | 
`org.apache.httpcomponents.client5:httpclient5` |
+| JDK `HttpClient` | `juneau-ng-rest-client-java-httpclient` | 
`java.net.http.HttpClient` (Java 11+) — zero third-party deps |
+| OkHttp | `juneau-ng-rest-client-okhttp` | `com.squareup.okhttp3:okhttp` |
+| Eclipse Jetty client | `juneau-ng-rest-client-jetty` | 
`org.eclipse.jetty:jetty-client` |
+
+Each module ships three classes:
+
+- `*Transport` — the `HttpTransport` implementation.
+- `*TransportBuilder` — extends `HttpTransportBuilder` with 
native-client–specific options
+  accessible via cast (e.g. 
`ApacheHc45TransportBuilder.httpClientBuilder(HttpClientBuilder)`).
+- `*TransportProvider` — `ServiceLoader` entry for auto-discovery.
+
+---
+
+## Quick Start
+
+```java
+import org.apache.juneau.json5.*;
+import org.apache.juneau.ng.rest.client.*;
+import org.apache.juneau.ng.rest.client.apachehttpclient45.*;
+import java.time.*;
+
+// Pre-build the serializer/parser — configure marshalling externally
+var serializer = Json5Serializer.create().build();
+var parser     = Json5Parser.create().build();
+
+// Choose a transport explicitly and configure it
+NgRestClient client = NgRestClient.create()
+    .transportBuilder(ApacheHc45Transport.create()
+        .connectTimeout(Duration.ofSeconds(10))
+        .maxConnections(50))
+    .serializer(serializer)
+    .parser(parser)
+    .rootUrl("https://api.example.com";)
+    .build();
+
+// Always use try-with-resources on the request — close releases the connection
+try (var req = client.get("/users/{id}").pathData("id", 42)) {
+    var user = req.run().as(User.class);
+}
+
+// At application shutdown
+client.shutdown();
+```
+
+### Auto-Discovery
+
+If you don't pass an explicit transport, `NgRestClient` uses `ServiceLoader` 
to pick the
+highest-priority `HttpTransportProvider` on the classpath:
+
+```java
+NgRestClient zeroConfig = NgRestClient.create()
+    .marshaller(Json5.DEFAULT)
+    .rootUrl("https://api.example.com";)
+    .build();
+```
+
+---
+
+## Key Design Differences from the Classic `RestClient`
+
+| Concern | Classic `RestClient` | `NgRestClient` |
+|---|---|---|
+| HTTP integration | Implements `org.apache.http.client.HttpClient`; bound to 
Apache HC 4.5 | Composes an `HttpTransport`; transport-agnostic |
+| Serialization model | Multi-language marshallers / format shortcuts 
(`json()`, `xml()`, …) | **One pre-built serializer/parser/marshaller per 
client**; no multi-language mode |
+| Builder surface | 40+ Apache HC passthrough methods | Small builder with 
only Juneau-specific concerns |
+| Lifecycle | `RestClient.close()` | Explicit `shutdown()` (not `Closeable`) — 
signalling app-lifecycle vs per-call |
+| Per-request lifecycle | `RestClient` and `RestResponse` were `Closeable` | 
**Only `NgRestRequest` is `Closeable`**; `close()` releases the connection |
+| Header/part types | Implement `org.apache.http.Header` / `NameValuePair` | 
Implement JDK-only `HttpHeader` / `HttpPart` interfaces |
+| Schema validation on `@Query`/`@Header`/`@FormData`/`@Path` | Supported | 
**Not supported** — `toString()` + `CollectionFormat` only |
+
+---
+
+## Resource Lifecycle
+
+`NgRestRequest` is the single `Closeable` in the user-facing API. Close it to 
release the
+underlying connection and stream:
+
+```java
+// Correct — try-with-resources releases the connection even if run() or as() 
throws
+try (var req = client.get("/users")) {
+    return req.run().as(UserList.class);
+}
+
+// At application shutdown
+client.shutdown();
+```
+
+`NgRestResponse` does **not** implement `Closeable` — its lifecycle is owned 
by the request.
+
+---
+
+## Multipart File Uploads
+
+`multipart/form-data` is a first-class body type:
+
+```java
+// Fluent multipart upload
+try (var req = client.multipartPost("/upload")
+        .multipartField("album", "vacation")
+        .multipartFile("photo", Path.of("/tmp/beach.jpg"), "image/jpeg")) {
+    req.run();
+}
+
+// Pre-built body (e.g. shared across requests)
+var mp = MultipartBody.builder()
+    .field("note", "hello")
+    .file("attachment", Path.of("report.pdf"), "application/pdf")
+    .build();
+try (var req = client.post("/cases/123/attachments").body(mp)) {
+    req.run();
+}
+```
+
+`formPost()` and `PartList` continue to produce 
`application/x-www-form-urlencoded`
+and should **not** be used for binary uploads.
+
+---
+
+## Logging
+
+Logging is framework-agnostic via `java.lang.System.Logger`:
+
+```java
+NgRestClient client = NgRestClient.create()
+    .transportBuilder(JavaHttpTransport.create())
+    .marshaller(Json5.DEFAULT)
+    .logger(BasicRestLogger.of(System.getLogger("myapp.http")))
+    .build();
+
+// Per-request verbose logging
+try (var req = client.get("/users/123").debug()) {
+    req.run();
+}
+```
+
+Custom log entries can be built using named templates
+(`{method}`, `{uri}`, `{status}`, `{reason}`, `{elapsed}`, `{req.headers}`, 
`{req.body}`,
+`{res.headers}`, `{res.body}`, `{error}`).
+
+---
+
+## Mock Transport (Serverless Testing)
+
+`MockHttpTransport` routes `TransportRequest` directly to a Juneau 
`RestContext` without
+network I/O. Use `NgMockRestClient` for unit tests that exercise 
serialization, remote proxies,
+interceptors, and assertions:
+
+```java
+NgRestClient mock = NgMockRestClient.create(MyRestResource.class)
+    .marshaller(Json5.DEFAULT)
+    .pathData("tenantId", "acme")
+    .build();
+
+try (var req = mock.get("/users/123")) {
+    var user = req.run().as(User.class);
+}
+```
+
+---
+
+## Migration Path
+
+The classic `RestClient` and `juneau-rest-common` APIs are **not deprecated** 
in 9.5.
+Migration is opt-in and incremental:
+
+1. Add the NG transport module for your preferred HTTP stack as a Maven 
dependency.
+2. Replace `RestClient.create()` with `NgRestClient.create()` and adapt 
builder calls —
+   most builder methods map 1:1 (`rootUrl`, default headers/query/form/path, 
interceptors,
+   marshaller, `errorCodes`, `executorService`).
+3. Wrap each request in **try-with-resources**. Call `shutdown()` on the 
client at
+   application shutdown.
+4. If you customized Apache HttpClient through `httpClientBuilder()` / 
`connectionManager()` /
+   `defaultRequestConfig()`, move those calls onto the **transport builder**
+   (e.g. `ApacheHc45TransportBuilder`).
+5. If you relied on multi-language marshallers or per-request language 
overrides, create
+   one `NgRestClient` per language.
+
+The NG stack will graduate to stable in a future release, at which point the 
classic stack
+may be deprecated and eventually removed.
+
+---
+
+## See Also
+
+- [juneau-rest-client Basics](/docs/topics/JuneauRestClientBasics) — the 
classic stack
+- [juneau-rest-mock Basics](/docs/topics/JuneauRestMockBasics) — classic mock 
client
+- Release notes: [9.5.0](/docs/release-notes/9.5.0) — Next-Generation REST 
Client and HTTP Stack
diff --git a/pages/topics/14.09.InjectAwareMicroservice.md 
b/pages/topics/14.09.InjectAwareMicroservice.md
new file mode 100644
index 0000000000..a5eae46dad
--- /dev/null
+++ b/pages/topics/14.09.InjectAwareMicroservice.md
@@ -0,0 +1,184 @@
+---
+title: "Inject-Aware Microservice"
+slug: MicroserviceCoreInject
+---
+
+Starting with **9.5.0**, the <a 
href="/site/apidocs/org/apache/juneau/microservice/Microservice.html" 
target="_blank">Microservice</a>
+class is **inject-aware**.  Every microservice owns an internal
+<a 
href="/site/apidocs/org/apache/juneau/commons/inject/WritableBeanStore.html" 
target="_blank">WritableBeanStore</a> (accessible via
+<a 
href="/site/apidocs/org/apache/juneau/microservice/Microservice.html#getBeanStore()"
 target="_blank">getBeanStore()</a>),
+populated from `@Configuration` classes registered on the builder.  Beans 
contributed this way
+can be consumed by other `@Bean` factory methods (via constructor injection), 
by subclasses
+(e.g. <a 
href="/site/apidocs/org/apache/juneau/microservice/jetty/JettyMicroservice.html"
 target="_blank">JettyMicroservice</a>
+auto-discovers `@Rest` servlets), and by user code via 
`getBeanStore().getBean(...)`.
+
+<tree>
+<node-0><java-class><a 
href="/site/apidocs/org/apache/juneau/microservice/Microservice.Builder.html" 
target="_blank">Microservice.Builder</a></java-class></node-0>
+<node-1><java-method><a 
href="/site/apidocs/org/apache/juneau/microservice/Microservice.Builder.html#configurations(java.lang.Class[])"
 target="_blank">configurations(Class...)</a></java-method> <java-method><a 
href="/site/apidocs/org/apache/juneau/microservice/Microservice.Builder.html#beanStore(org.apache.juneau.commons.inject.WritableBeanStore)"
 target="_blank">beanStore(WritableBeanStore)</a></java-method></node-1>
+<node-0><java-class><a 
href="/site/apidocs/org/apache/juneau/microservice/Microservice.html" 
target="_blank">Microservice</a></java-class></node-0>
+<node-1><java-method><a 
href="/site/apidocs/org/apache/juneau/microservice/Microservice.html#getBeanStore()"
 target="_blank">getBeanStore()</a></java-method></node-1>
+</tree>
+
+## Quick example
+
+```java
+import org.apache.juneau.commons.inject.*;
+import org.apache.juneau.microservice.*;
+
+@Configuration
+public class AppConfig {
+
+    @Bean
+    public MyService myService() {
+        return new MyService("hello");
+    }
+}
+
+public class App {
+    public static void main(String[] args) throws Exception {
+        Microservice.create()
+            .args(args)
+            .configurations(AppConfig.class)
+            .build()
+            .start()
+            .join();
+    }
+}
+```
+
+Inside the running microservice, the bean is available via:
+
+```java
+MyService svc = 
Microservice.getInstance().getBeanStore().getBean(MyService.class).orElseThrow();
+```
+
+## What lands in the bean store
+
+After bootstrap completes, the store contains every bean registered by your 
`@Configuration` classes
+**plus** the microservice's own resolved values:
+
+| Type | Notes |
+|---|---|
+| <a href="/site/apidocs/org/apache/juneau/microservice/Microservice.html" 
target="_blank">Microservice</a> | The microservice instance itself. |
+| <a href="/site/apidocs/org/apache/juneau/commons/runtime/Args.html" 
target="_blank">Args</a> | Resolved CLI args. |
+| <a href="/site/apidocs/org/apache/juneau/commons/runtime/ManifestFile.html" 
target="_blank">ManifestFile</a> | Resolved manifest. |
+| <a href="/site/apidocs/org/apache/juneau/config/Config.html" 
target="_blank">Config</a> | Resolved configuration. |
+| <a href="/site/apidocs/org/apache/juneau/commons/svl/VarResolver.html" 
target="_blank">VarResolver</a> | Resolved var resolver with `$A`, `$M`, `$C` 
and standard vars wired up. |
+| <a 
href="/site/apidocs/org/apache/juneau/microservice/MicroserviceListener.html" 
target="_blank">MicroserviceListener</a> | Either the builder-supplied 
listener, a `@Bean`-supplied one, or the default. |
+
+In `JettyMicroservice` the store additionally contains:
+
+| Type | Notes |
+|---|---|
+| <a 
href="/site/apidocs/org/apache/juneau/microservice/jetty/JettyMicroservice.html"
 target="_blank">JettyMicroservice</a> | The Jetty subclass instance. |
+| <a 
href="/site/apidocs/org/apache/juneau/microservice/jetty/JettyMicroserviceListener.html"
 target="_blank">JettyMicroserviceListener</a> | Jetty-specific listener. |
+| <a 
href="/site/apidocs/org/apache/juneau/microservice/jetty/JettyServerFactory.html"
 target="_blank">JettyServerFactory</a> | Factory used to build the Jetty 
`Server` from `jetty.xml`. |
+| `org.eclipse.jetty.server.Server` | The created Jetty server (after 
`createServer()`). |
+
+## Resolution priority
+
+Beans for these core types resolve in this order:
+
+1. **Explicit builder call** — e.g. `.config(myConfig)`, `.args(myArgs)`.  
Always wins.
+2. **`@Bean`-supplied value** — picked up if no builder call was made.
+3. **Built-in default** — typical fallbacks: empty `Args`, classpath 
`META-INF/MANIFEST.MF`, etc.
+
+Once resolved, the final value is registered into the bean store, 
**overwriting** any `@Bean` contribution
+of the same `(type, name)`.  This means downstream consumers (other `@Bean` 
factory methods, subclasses)
+always see the same `Args` / `Config` / etc. that `Microservice.getArgs()` 
returns.
+
+## Discovering `@Rest` servlets in Jetty
+
+`JettyMicroservice.createServer()` walks the bean store for entries registered 
under `Servlet.class`,
+filters them to those whose runtime class carries `@Rest`, and mounts each one 
at the path declared in
+`@Rest(path = "...")` (falling back to `/` when no path is set).
+
+```java
+@Rest(path = "/api")
+public class ApiServlet extends RestServlet { /* ... */ }
+
+@Configuration
+public class JettyConfig {
+    @Bean
+    Servlet apiServlet() { return new ApiServlet(); }   // mounted 
automatically at /api/*
+}
+```
+
+> **Note on declared return types** — Juneau's 
`BeanStore.getBeansOfType(Class)` is exact-type
+> (not assignable-to).  Declare your `@Bean` method return type as `Servlet` 
(not the concrete
+> subclass) so the bean is registered under `Servlet.class` and visible to the 
auto-mount logic.
+
+### Path collisions are a hard startup failure
+
+Mounting two servlets at the same pathspec — whether from `Jetty/servlets`, 
`Jetty/servletMap`,
+`.servlet(...)` on the builder, or `@Bean` discovery — raises a 
`RuntimeException` from
+`createServer()` with a message identifying both contributors:
+
+```
+Servlet mount path collision: '/api/*' is already mounted by @Bean ApiServletA;
+refused by @Bean ApiServletB[apiServletDup].
+```
+
+## Bypassing `jetty.xml` entirely
+
+If your `@Configuration` provides a `@Bean Server` whose attribute 
`"ServletContextHandler"` is set,
+`createServer()` will skip the `jetty.xml` factory step and use that server 
directly:
+
+```java
+@Configuration
+public class JettyConfig {
+
+    @Bean
+    public Server jettyServer() {
+        var server = new Server();
+        var ctx = new ServletContextHandler();
+        ctx.setContextPath("/");
+        server.setAttribute("ServletContextHandler", ctx);
+        server.setHandler(ctx);
+        return server;
+    }
+}
+```
+
+This is useful in tests and in programs that want fully-code-driven Jetty 
configuration.
+
+## Lifecycle: `@PostConstruct` and `@PreDestroy`
+
+`@PostConstruct` callbacks fire automatically on any bean instantiated through 
the inject framework
+(e.g. when a `@Bean` method constructs a class via constructor injection, or 
when `BeanStore.instantiate(X)`
+is used).  Note that beans you `return new MyBean()` directly from a `@Bean` 
method do **not** pass
+through that path and will not receive a `@PostConstruct` callback for the 
returned instance.
+
+`@PreDestroy` callbacks fire on `Microservice.stop()`, which closes the bean 
store and walks every
+**resolved** bean (anything that was retrieved via `getBean` / 
`getBeansOfType` at least once) in
+LIFO order.  Errors thrown from `@PreDestroy` are logged at `WARNING` level 
and do not abort the rest
+of the shutdown sequence.
+
+## External bean stores
+
+`Microservice.Builder.beanStore(WritableBeanStore)` lets you supply an 
externally-owned store rather
+than letting the microservice construct a fresh one.  This is the integration 
point for composing a
+microservice into a larger application that already owns a bean store, 
including the
+Spring-application-context bridge provided by `juneau-rest-server-springboot`.
+
+```java
+WritableBeanStore parent = new BasicBeanStore();
+parent.addBean(MyService.class, sharedService);
+
+Microservice.create()
+    .beanStore(parent)
+    .configurations(AppConfig.class)
+    .build()
+    .start();
+```
+
+## Back-compat
+
+The inject-aware bootstrap is **fully additive**:
+
+* Every existing builder method continues to work unchanged.
+* Microservices that never call `.configurations(...)` get an empty bean store 
and behave identically
+  to pre-9.5.0 behavior.
+* The `Microservice` field-resolution order (builder &gt; bean store &gt; 
default) means explicit
+  builder calls always win, so existing apps cannot be silently altered by an 
injected `@Bean Config`
+  or `@Bean Args`.
diff --git a/sidebars.ts b/sidebars.ts
index 7aca57ccaf..3411cf7c0d 100644
--- a/sidebars.ts
+++ b/sidebars.ts
@@ -1674,6 +1674,11 @@ const sidebars: SidebarsConfig = {
                                                                },
                                                        ],
                                                },
+                                               {
+                                                       type: 'doc',
+                                                       id: 
'topics/12.15.NextGenRestClient',
+                                                       label: '12.15. 
Next-Generation REST Client (Beta)',
+                                               },
                                        ],
                                },
                                {
@@ -1738,6 +1743,11 @@ const sidebars: SidebarsConfig = {
                                                        id: 
'topics/14.08.Listeners',
                                                        label: '14.8. 
Listeners',
                                                },
+                                               {
+                                                       type: 'doc',
+                                                       id: 
'topics/14.09.InjectAwareMicroservice',
+                                                       label: '14.9. 
Inject-Aware Microservice',
+                                               },
                                        ],
                                },
                                {


Reply via email to