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 9f3dc5acb2 Measure MCP schema-safety compute budget as thread CPU 
time; add view-mixin responseProcessor auto-fold opt-in; FreeMarker 
object-wrapper + fluent ConfigItem.setValue
9f3dc5acb2 is described below

commit 9f3dc5acb28d9ddb0b34b4138e3d80d9fbff5240
Author: James Bognar <[email protected]>
AuthorDate: Thu Aug 13 18:04:21 2026 -0400

    Measure MCP schema-safety compute budget as thread CPU time; add view-mixin 
responseProcessor auto-fold opt-in; FreeMarker object-wrapper + fluent 
ConfigItem.setValue
    
    McpSchemaSafety (mcp-v20260728): the tools/call input-schema-validation DoS 
budget is now charged against the validating thread's actual CPU time 
(ThreadMXBean.getThreadCpuTime) instead of wall-clock, so OS 
preemption/scheduling no longer counts against the ~100ms budget. Includes a 
support-check with a verbatim wall-clock fallback when thread-CPU timing is 
unavailable, correct ns/-1-sentinel handling, and sleep-vs-CPU-burn regression 
tests. Fixes an intermittent CI false-trip (-32602 [...]
    
    TODO-358 (juneau-rest-server view mixins): (1) FreemarkerDispatcher's 
bridge-default Configuration now installs a 
DefaultObjectWrapper(exposeFields=true) so public-field DTOs render instead of 
silently resolving to null, with new 
exposeFields(boolean)/objectWrapper(ObjectWrapper) builder knobs. (2) New 
non-silent, response-processor-scoped 
@Rest(mergeResponseProcessorsIntoHost=true) opt-in: a plain 
@Rest(mixins=<ViewMixin>.class) now folds the mixin's renderer into the host 
chain so t [...]
    
    TODO-320 (juneau-sc-server): ConfigItem.setValue(String) is now a fluent 
self-returning setter, matching the repo-wide convention (the lone void-setter 
outlier); source-compatible, no reflective contract broken.
    
    Docs: release notes for both behavioral changes, plus FreeMarker/JSP 
view-support and mixin-subcontexts topic updates.
---
 pages/release-notes/10.0.0.md                    |  19 +++++
 pages/topics/10.08.RestServerMixinSubContexts.md |  28 ++++++
 pages/topics/10.24.JspViewSupport.md             |   5 +-
 pages/topics/10.27.FreemarkerViewSupport.md      | 104 ++++++++++++++++++++---
 4 files changed, 141 insertions(+), 15 deletions(-)

diff --git a/pages/release-notes/10.0.0.md b/pages/release-notes/10.0.0.md
index d1980a4f5c..a51e835064 100644
--- a/pages/release-notes/10.0.0.md
+++ b/pages/release-notes/10.0.0.md
@@ -393,6 +393,21 @@ public class ApiResource extends BasicRestServlet { ... }
 
 Internally this also normalized mixin discovery (one `ResolvedMixin` carrier 
for both bare and rich forms) and replaced the `RestContext.Args` boolean 
`mixinContext` flag with a typed `ContextKind` discriminator 
(`Root`/`Child`/`Mixin`). See [Host-side overrides with 
`@Mixin`](/docs/topics/RestServerMixinSubContexts#host-side-overrides-with-mixin-1000).
 
+### Mixin-declared response-processor fold — 
`@Rest(mergeResponseProcessorsIntoHost=true)`
+
+By default a mixin's `responseProcessors` apply only to the mixin's own 
endpoints — a host's own `@RestOp` methods see only the host's chain. The 
host-side `@Mixin(mergeIntoHost=true)` directive can fold *all* of a mixin's 
list-shaped attributes into the host, but it must be spelled out at every 
use-site. New in 10.0.0, a mixin class can declare 
`@Rest(mergeResponseProcessorsIntoHost=true)` on **itself**, so that a plain 
`@Rest(mixins=ThatMixin.class)` reference automatically folds **onl [...]
+
+```java
+@Rest(responseProcessors=FreemarkerViewRenderer.class, 
mergeResponseProcessorsIntoHost=true)
+public class FreemarkerMixin { ... }
+```
+
+- **Opt-in and non-silent.** Defaults to `false`; only a mixin that declares 
it changes behavior. Mixins that don't keep today's isolated scoping exactly — 
no change to the default for arbitrary existing mixins.
+- **Response-processor-scoped.** Folds only `responseProcessors` — never 
`guards`, `serializers`, or any other list-shaped attribute (the narrower, 
mixin-declared counterpart to the host-side, fold-everything 
`@Mixin(mergeIntoHost=true)`). Same-class de-duplication applies.
+- **View mixins opt in.** All four view-renderer mixins — `FreemarkerMixin`, 
`JspMixin`, `MustacheMixin`, `ThymeleafMixin` — now declare it, so a bare 
`@Rest(mixins=FreemarkerMixin.class)` (etc.) renders the host's own `View` 
returns through the engine with no `mergeIntoHost` or explicit 
`responseProcessors=` ceremony.
+
+See [REST Server — Mixin 
Sub-Contexts](/docs/topics/RestServerMixinSubContexts#folding-a-mixins-contributions-into-the-host)
 and [FreeMarker View Support](/docs/topics/FreemarkerViewSupport).
+
 ### Host-side child seeding — `@Rest(childrenDefs=@Child(...))`
 
 Children are deliberately **isolated** from the host's resolution chain — a 
child's serializers, parsers, guards, call logger, etc. resolve against its own 
`RestContext` only, never inherited from the parent. New in 10.0.0, the 
`@Rest(childrenDefs=@Child(...))` attribute lets a host **seed** a curated set 
of settings onto a routed child's otherwise-isolated context, without editing 
the child class — the child-resource analog of the 
`@Rest(mixinDefs=@Mixin(...))` attribute above:
@@ -1032,6 +1047,10 @@ See 
[juneau-rest-server-mcp](/docs/topics/JuneauRestServerMcp#key-management-key
 
 See 
[juneau-rest-server-mcp](/docs/topics/JuneauRestServerMcp#replay-protection-replaycache-opt-in)
 for the full topic.
 
+### MCP `2026-07-28` — schema-safety compute budget measured as thread CPU time
+
+`2026-07-28`-only. The bounded, no-fetch `tools/call` input-schema validation 
guard enforces a compute budget so a pathological schema (for example a 
catastrophically-backtracking `pattern`) can't hang the request thread — 
tripping `-32602` ("Tool input schema validation exceeded 100 ms") instead. 
That budget is now charged against the **validating thread's actual CPU time** 
rather than wall-clock time: OS scheduler preemption and thread-pool queueing 
no longer count against it, only rea [...]
+
 ### MCP `2026-07-28` — OAuth 2.1 authorization: client acquisition + server 
resource server (TODO-312f)
 
 `2026-07-28`-only, and **off by default** — an endpoint that doesn't opt in 
behaves exactly as before. 10.0.0 lands the OAuth 2.1 / MCP authorization 
baseline in three slices: client-side token acquisition (F1), a server-side 
resource-server (F2), and dynamic client registration + authorization hardening 
(F3). Together they let a Juneau MCP client authenticate to, and a Juneau MCP 
endpoint protect, a `2026-07-28` MCP resource end to end, covering the MCP 
authorization SEPs at a baseline  [...]
diff --git a/pages/topics/10.08.RestServerMixinSubContexts.md 
b/pages/topics/10.08.RestServerMixinSubContexts.md
index 2be916d6fd..141f217599 100644
--- a/pages/topics/10.08.RestServerMixinSubContexts.md
+++ b/pages/topics/10.08.RestServerMixinSubContexts.md
@@ -339,6 +339,34 @@ wins (the bare entry is upgraded in place).
 `messages`, 
`defaultRequestHeaders`/`defaultResponseHeaders`/`defaultRequestAttributes`,
 `produces`/`consumes`/`defaultAccept`/`defaultContentType`/`defaultCharset`, 
and `maxInput`.
 
+### Folding a mixin's contributions into the host
+
+The override slots above apply the *host's* values to the *mixin's* endpoints. 
The reverse
+direction — appending the *mixin's* own list-shaped `@Rest` contributions into 
the *host's* own
+chain, so the host's own `@RestOp` methods pick them up too — is available via 
two opt-in
+directives. Both are strictly opt-in and non-silent: a mixin that declares 
neither keeps today's
+default scoping exactly (host endpoints see only the host's chain).
+
+| Directive | Declared on | Folds | Use when |
+|---|---|---|---|
+| `@Mixin(mergeIntoHost=true)` | the **host** (via `mixinDefs`) | **all** of 
the mixin's list-shaped `@Rest` attributes (serializers, parsers, encoders, 
converters, guards, responseProcessors, restOpArgs, default headers/attributes, 
produces, consumes) | the host wants to adopt a mixin's full list-shaped 
contribution surface into its own endpoints |
+| `@Rest(mergeResponseProcessorsIntoHost=true)` | the **mixin class** itself | 
**only** the mixin's `responseProcessors` | a mixin (typically a view-renderer 
mixin) wants "declare the mixin → it just works" for the host's own returns, 
under a plain `mixins=` reference, without folding anything but its renderer |
+
+```java
+// Host-side, broad: fold ALL of AdminResource's list-shaped attributes into 
the host chain.
+@Rest(mixinDefs = @Mixin(type = AdminResource.class, mergeIntoHost = true))
+public class ApiResource extends BasicRestServlet { ... }
+
+// Mixin-declared, narrow: a view mixin folds ONLY its renderer into any 
plain-mixins= host.
+@Rest(responseProcessors = FreemarkerViewRenderer.class, 
mergeResponseProcessorsIntoHost = true)
+public class FreemarkerMixin { ... }
+```
+
+`mergeResponseProcessorsIntoHost` is what makes a bare 
`@Rest(mixins=FreemarkerMixin.class)` render
+the host's own `FreemarkerView` returns (see [FreeMarker View 
Support](/docs/topics/FreemarkerViewSupport)
+and the sibling JSP / Thymeleaf / Mustache bridges, which all declare it). 
Same-class de-duplication
+applies to both directives, so a response processor the host already declares 
is never added twice.
+
 ### Precedence and `noInherit`
 
 A host `@Mixin` override resolves as if it were declared on the mixin class 
itself, but at the
diff --git a/pages/topics/10.24.JspViewSupport.md 
b/pages/topics/10.24.JspViewSupport.md
index 0d7a731555..f3ff63bb4d 100644
--- a/pages/topics/10.24.JspViewSupport.md
+++ b/pages/topics/10.24.JspViewSupport.md
@@ -212,7 +212,10 @@ known constraints that aren't bridge-module bugs but worth 
documenting up front:
 
[`ViewRenderer`](/site/apidocs/org/apache/juneau/rest/server/view/ViewRenderer.html)
 and is
 automatically positioned before `SerializedPojoProcessor` by the 
`ResponseProcessorList`
 partition pass.  A `@RestOp` method returning `JspView` reaches the renderer 
without any
-extra configuration — the mixin registers the renderer and the framework 
ensures ordering.
+extra configuration — `JspMixin` declares
+`@Rest(mergeResponseProcessorsIntoHost=true)`, so a plain 
`@Rest(mixins=JspMixin.class)` folds
+`JspViewRenderer` into the host's own chain and the framework ensures 
ordering. See
+[REST Server — Mixin Sub-Contexts](/docs/topics/RestServerMixinSubContexts) 
for the opt-in model.
 
 ## Multiple base paths
 
diff --git a/pages/topics/10.27.FreemarkerViewSupport.md 
b/pages/topics/10.27.FreemarkerViewSupport.md
index cacdd513f5..cfad0cc30e 100644
--- a/pages/topics/10.27.FreemarkerViewSupport.md
+++ b/pages/topics/10.27.FreemarkerViewSupport.md
@@ -33,7 +33,7 @@ matching Juneau's own license stance.
 | Class | Role |
 |---|---|
 | [`View`](/site/apidocs/org/apache/juneau/rest/server/view/View.html) (in 
`juneau-rest-server` core) | Engine-agnostic contract: `getTemplateName()`, 
`getAttributes()`, `getResponseHeaders()`. |
-| 
[`FreemarkerMixin`](/site/apidocs/org/apache/juneau/rest/server/view/freemarker/FreemarkerMixin.html)
 | Mixin. Mounts `/freemarker/*` for raw `.ftl` / `.ftlh` template requests; 
registers `FreemarkerViewRenderer` on the response-processor chain. Builder: 
`basePath(String)` (default `/`), `templateSuffix(String)` (default `""`), 
`cacheTemplates(boolean)` (default `true`). Builder implements the shared 
[`ViewMixinBuilder`](/site/apidocs/org/apache/juneau/rest/server/view/ViewMixinBuilder
 [...]
+| 
[`FreemarkerMixin`](/site/apidocs/org/apache/juneau/rest/server/view/freemarker/FreemarkerMixin.html)
 | Mixin. Mounts `/freemarker/*` for raw `.ftl` / `.ftlh` template requests; 
registers `FreemarkerViewRenderer` on the response-processor chain. Builder: 
`basePath(String)` (default `/`), `templateSuffix(String)` (default `""`), 
`cacheTemplates(boolean)` (default `true`), `exposeFields(boolean)` (default 
`true`), `objectWrapper(ObjectWrapper)` (default `null` — bridge builds its 
own). B [...]
 | 
[`FreemarkerView`](/site/apidocs/org/apache/juneau/rest/server/view/freemarker/FreemarkerView.html)
 | `View` implementation. Immutable; fluent: 
`FreemarkerView.of("hello.ftlh").attr("name", name).header("Cache-Control", 
"no-store")`. |
 | 
[`FreemarkerViewRenderer`](/site/apidocs/org/apache/juneau/rest/server/view/freemarker/FreemarkerViewRenderer.html)
 | `ResponseProcessor` that detects `FreemarkerView` returns and asks the 
configured `freemarker.template.Configuration` to 
`getTemplate(name).process(dataModel, writer)` directly onto the response 
writer. |
 
@@ -70,6 +70,56 @@ encodings / output formats you need.
 See https://juneau.apache.org/docs/topics/FreemarkerViewSupport for the full 
matrix.
 ```
 
+### Public-field DTOs and the default object wrapper
+
+FreeMarker's own version-default `ObjectWrapper` exposes only JavaBean getters 
to templates —
+a view-model bean written as a simple DTO with public fields and no getters 
resolves every
+`${bean.field}` reference to `null`/missing, **silently**. That silence is the 
dangerous part: a
+template using an `!'default'` fallback (`${bean.field!'—'}`) renders the 
fallback with no error
+at all, and a bare `${bean.field}` with no fallback throws at render time 
instead of failing at
+compile/wiring time.
+
+The bridge-default `Configuration` avoids this trap: it sets a 
`DefaultObjectWrapper` with
+`exposeFields=true`, so public-field DTOs render their field values out of the 
box — matching
+how Juneau's own marshalling is comfortable with public-field beans elsewhere. 
For example:
+
+```java
+public class Coordinate {
+    public double lat;
+    public double lon;
+}
+```
+
+```html
+<p>Lat/Lon: ${coord.lat}, ${coord.lon}</p>
+```
+
+renders the actual field values with **no getters required** and no extra 
configuration.
+
+Two builder knobs let you opt out or take full control, both scoped to the 
**bridge-default**
+`Configuration` only (a user-supplied `@Bean Configuration` is used as-is, 
un-modified):
+
+```java
+@Bean
+FreemarkerMixin freemarker() {
+    return FreemarkerMixin.create()
+        .basePath("/templates/")
+        .templateSuffix(".ftlh")
+        .exposeFields(false)   // restore FreeMarker's own getter-only default
+        .build();
+}
+```
+
+```java
+@Bean
+FreemarkerMixin freemarker() {
+    return FreemarkerMixin.create()
+        .basePath("/templates/")
+        .objectWrapper(myCustomBeansWrapper)   // full control; overrides 
exposeFields(...) entirely
+        .build();
+}
+```
+
 ## Hello-world
 
 ### Maven
@@ -147,10 +197,26 @@ data model, and asks the resolved `Template` to render 
`/templates/hello.ftlh` d
 the response writer. The `.ftlh` suffix is appended idempotently because the 
builder
 declared it.
 
+> **Why does the bare `mixins=FreemarkerMixin.class` shorthand render the 
host's own
+> `FreemarkerView` returns?** By default a mixin's 
`@Rest(responseProcessors=...)` declaration
+> applies only to the *mixin's own* endpoints (here, the `/freemarker/*` 
raw-template mount) — a
+> host's own `@RestOp` methods see only the host's own response-processor 
chain. `FreemarkerMixin`
+> opts out of that default: it declares 
`@Rest(mergeResponseProcessorsIntoHost=true)` on its own
+> class, so a plain `@Rest(mixins=FreemarkerMixin.class)` folds 
`FreemarkerViewRenderer` into the
+> host's own chain automatically and the `hello(...)` method above renders 
instead of being
+> bean-serialized. The opt-in is **per-mixin, non-silent, and 
response-processor-scoped**: only a
+> mixin that declares it changes behavior, and only its renderer is folded — 
never `guards`,
+> `serializers`, or any other list-shaped attribute. If you want to fold *all* 
of a mixin's
+> list-shaped `@Rest` attributes (not just the renderer), the host-side
+> `mixinDefs=@Mixin(type=FreemarkerMixin.class, mergeIntoHost=true)` form 
still does that. See
+> [REST Server — Composition](/docs/topics/RestServerComposition) for the full 
`@Mixin` /
+> `mixinDefs` / opt-in model.
+
 ### Typed handler integration
 
-To use `FreemarkerView` from a host-class `@RestGet` *without* adopting the 
full mixin, add
-`FreemarkerViewRenderer.class` directly to the host's `responseProcessors`:
+A fully explicit alternative — useful when you'd rather not rely on the 
mixin's auto-fold opt-in,
+or when the host doesn't declare the mixin at all — is to list 
`FreemarkerViewRenderer.class`
+directly in the host's own `responseProcessors`:
 
 ```java
 @Rest(responseProcessors={FreemarkerViewRenderer.class})
@@ -162,10 +228,12 @@ public class AppResource extends BasicRestServlet {
 }
 ```
 
-The `ResponseProcessorList` partition pass (added in 9.5.0) automatically 
repositions
-`FreemarkerViewRenderer` to run before `SerializedPojoProcessor`.  Because 
FreeMarker renders
-directly to a `Writer` with zero servlet-container dependencies, attribute 
interpolation
-(`${name}` → `"Alice"`) works under MockRest — verified end-to-end by
+Once `FreemarkerViewRenderer` is in a chain (whichever of the two ways above 
got it there), the
+`ResponseProcessorList` partition pass (added in 9.5.0) automatically 
repositions it to run
+before `SerializedPojoProcessor`, so the `FreemarkerView` return is dispatched 
to the FreeMarker
+engine rather than bean-serialized. Because FreeMarker renders directly to a 
`Writer` with zero
+servlet-container dependencies, attribute interpolation (`${name}` → 
`"Alice"`) works under
+MockRest — verified end-to-end by
 
`FreemarkerView_TypedHandler_Test#a04_renderInterpolatesAttributesFromTypedHandler`.
 
 ### REST resource — raw-template mount
@@ -254,10 +322,17 @@ is bypassed entirely when the starter is on the classpath.
 `FreemarkerViewRenderer` implements
 
[`ViewRenderer`](/site/apidocs/org/apache/juneau/rest/server/view/ViewRenderer.html)
 and is
 automatically positioned before `SerializedPojoProcessor` by the 
`ResponseProcessorList`
-partition pass.  A `@RestOp` method returning `FreemarkerView` reaches the 
renderer
-without any extra configuration — the mixin registers the renderer and the 
framework ensures
-ordering.  MockRest-level typed-handler integration is verified by
-`FreemarkerView_TypedHandler_Test` (attribute interpolation asserted 
end-to-end).
+partition pass, **once it's present in the relevant chain**. That's a distinct 
question from
+*whether* the renderer is present in the host's own chain in the first place. 
Because
+`FreemarkerMixin` declares `@Rest(mergeResponseProcessorsIntoHost=true)`, a 
bare
+`@Rest(mixins=FreemarkerMixin.class)` **does** now put the renderer into the 
host's own chain for
+the host's own `@RestOp` methods (see the "Why does the bare `mixins=` 
shorthand render..." callout
+above). The host-side `mixinDefs=@Mixin(type=FreemarkerMixin.class, 
mergeIntoHost=true)` form and
+an explicit `@Rest(responseProcessors={FreemarkerViewRenderer.class})` on the 
host remain
+supported. In every case, once the renderer is in the host's chain, the 
partition pass handles
+ordering automatically — no further configuration needed. MockRest-level 
typed-handler integration
+(renderer-vs-serializer dispatch) is verified by 
`FreemarkerView_TypedHandler_Test` (attribute
+interpolation asserted end-to-end).
 
 ## Multiple base paths
 
@@ -306,9 +381,10 @@ 
anyEngineBuilder.basePath("/templates/").cacheTemplates(false);
 ## Limitations and out-of-scope
 
 - **No bridge-default `Configuration` mutation for user beans.** The
-  `cacheTemplates(boolean)` builder knob only configures the *bridge-default*
-  `Configuration`. If you provide your own `@Bean Configuration` (Spring Boot 
autoconfig
-  counts), configure caching directly on that bean — the bridge does not 
mutate it.
+  `cacheTemplates(boolean)`, `exposeFields(boolean)`, and 
`objectWrapper(ObjectWrapper)`
+  builder knobs only configure the *bridge-default* `Configuration`. If you 
provide your own
+  `@Bean Configuration` (Spring Boot autoconfig counts), configure field 
exposure / caching
+  directly on that bean — the bridge does not mutate it.
 - **`.ftlh` is the recommended HTML default.** FreeMarker's auto-escape 
selection is by
   file extension. For HTML responses prefer `.ftlh`; using `.ftl` for HTML 
leaves variable
   references un-escaped and risks XSS regressions when an attribute binding is 
later

Reply via email to