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 0fc04931a2 docs: 9.5.0 release notes for TODO-99/TODO-101 (SVL
op-paths + mixin retrofit) + JSP View Support topic page (TODO-78)
0fc04931a2 is described below
commit 0fc04931a2feac4361f8400f29879052b9405d85
Author: James Bognar <[email protected]>
AuthorDate: Mon May 25 17:47:08 2026 -0400
docs: 9.5.0 release notes for TODO-99/TODO-101 (SVL op-paths + mixin
retrofit) + JSP View Support topic page (TODO-78)
- pages/release-notes/9.5.0.md: TODO-99 (SVL ${...} resolution in
@RestOp/@RestGet path)
and TODO-101 (mixin op-paths collapsed to single SVL-configurable mount
with migration
callout for /htdocs/* alias removal).
- pages/topics/10.14d.JspViewSupport.md: new topic page covering the
juneau-rest-server-view-jsp
module, View SPI, JspView/JspViewRenderer, BasicJspResource mixin, and
configurable mount path.
- sidebars.ts: register 10.14d JSP View Support under the mixin section.
Co-authored-by: Cursor <[email protected]>
---
pages/release-notes/9.5.0.md | 163 +++++++++++++++++++++++
pages/topics/10.14d.JspViewSupport.md | 237 ++++++++++++++++++++++++++++++++++
sidebars.ts | 5 +
3 files changed, 405 insertions(+)
diff --git a/pages/release-notes/9.5.0.md b/pages/release-notes/9.5.0.md
index a5cbdfde0e..5a9b3663c3 100644
--- a/pages/release-notes/9.5.0.md
+++ b/pages/release-notes/9.5.0.md
@@ -2238,6 +2238,103 @@ literals continue to behave exactly as they did under
FINISHED-72 (the annotatio
on its own, element-for-element). Pre-9.5.0 users who already adopted
`@Rest(paths=...)` see no
behavior change unless they introduce an SVL marker or an embedded comma in an
element.
+#### SVL `${...}` resolution in `@RestOp(path)` / `@RestGet(path)` /
`@RestOp(value)` (TODO-99)
+
+SVL variables (`${var:default}`, `$S{key,default}`, `$E{NAME,default}`,
`$C{key}`, etc.) are now
+resolved in op-level path declarations — `@RestOp(path)`, `@RestGet(path)`,
`@RestPost(path)`,
+`@RestPut(path)`, `@RestDelete(path)`, and the `@RestOp(value="METHOD path")`
verb-on-value form
+— closing the asymmetry with class-level `@Rest(path)` / `@Rest(paths)`, which
were already
+SVL-resolved.
+
+This enables configurable mount paths for mixin-style resources without
subclassing:
+
+```java
+@Rest(responseProcessors=JspViewRenderer.class)
+public static class BasicJspResource {
+ // Mounts at "/jsp/*" by default; deployers can override at runtime via
system property,
+ // env var (after Settings normalization), or a registered Config bean.
+ @RestGet(path="/${jsp.path:jsp}/*")
+ public View hello() { return new JspView("hello.jsp"); }
+}
+```
+
+The shorthand `${name:default}` uses Juneau's dollar-brace shortcut
(registered as `PropertyVar`,
+which reads from `Settings.get()`); the longer SVL forms — `$S{key,default}`,
`$E{NAME,default}`,
+`$C{key}` — also work and are preferred when the source is explicit. SVL
resolution happens at
+`RestContext` construction time, so deployer overrides must be in place before
the resource
+context is built.
+
+The auto-detected fallback path (derived from the Java method name when no
`path()` / `value()`
+is declared) is intentionally **not** SVL-resolved — it is framework-derived,
not user input.
+Path strings whose SVL resolution yields an empty string are dropped (matches
how class-level
+`@Rest(paths)` drops empty pieces in the post-comma-split pipeline).
Unresolved variables with
+no default pass through to `UrlPathMatcher.of(...)` as the literal `${...}`
placeholder, which
+then fails predictably at routing time without crashing at startup.
+
+This change is purely additive — annotation strings that contain no SVL
markers are passed
+through unchanged.
+
+#### Bundled mixin op-paths now SVL-configurable (TODO-101)
+
+Building on TODO-99 (SVL resolution in op-level `path` declarations), every
Juneau-bundled
+mixin resource whose mount path is a Juneau organizational/conventional
default — not fixed by an
+external specification — now declares its op-level `path` as
`/${juneau.<role>.path:<default>}`
+so deployers can relocate the mount via system property, environment variable,
or `Config` key
+without subclassing.
+
+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/*` |
+
+Example — relocate the Swagger UI mount to `/docs/swagger-ui`:
+
+```bash
+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`
+ (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
+ security.txt).
+
+**Migration note — multi-path collapse:** four mixins that previously declared
multiple paths
+in a single op annotation's `path={...}` array — historical "convenience
alias" defaults from
+before the SVL mechanism existed — have been collapsed to a single
SVL-configurable path. The
+secondary aliases are now reached by overriding the SVL variable instead of
being mounted by
+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` |
+
+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
+search root still walks both the `static/` and `htdocs/` directories at the
JAR-resource layer
+— only the URL-side mount alias has been removed.
+
+SVL resolution happens once at `RestContext` construction time (see TODO-99
above for the full
+resolution chain). Each configurable mixin ships with a
`*_SvlPathOverride_Test` in
+`juneau-utest` that exercises the override end-to-end via `MockRestClient`.
+
#### OpenAPI 3.1 Emission + API-docs Mixin Pack (TODO-63 + TODO-74)
`juneau-rest-server` now ships first-class OpenAPI 3.1 document generation
alongside the existing Swagger v2 path, with the public surface composed via
four small `@Rest(mixins=...)` mixins instead of a `apiFormat` string knob:
@@ -2931,6 +3028,18 @@ microservices that never call `.configurations(...)`
behave identically to pre-9
See <a href="/docs/topics/MicroserviceCoreInject">Inject-Aware
Microservice</a> for the full guide.
+#### `View` interface — engine-agnostic server-side render contract
+
+- New `org.apache.juneau.rest.view.View` interface. Carries the data a
templating engine needs to render a response: `String getTemplateName()`,
`Map<String, Object> getAttributes()`, and a `default Map<String, String>
getResponseHeaders()` seam. Engine-agnostic — concrete implementations live in
per-engine bridge modules (`juneau-rest-server-view-jsp` ships in 9.5.0;
Thymeleaf / Mustache / FreeMarker bridges are queued behind it).
+- Designed as the stable extension point for the new view-module family. New
methods will be added as `default`-bodied where possible to preserve backward
compatibility with downstream view impls.
+
+```java
+@RestGet("/hello/{name}")
+public View hello(@Path String name) {
+ return JspView.of("hello.jsp").attr("name", name); // JspView implements
View
+}
+```
+
### juneau-rest-server-springboot
#### Spring `Environment` bridge — `@Value` reads `application.yaml` (TODO-79)
@@ -3429,6 +3538,60 @@ Requests without an `id` are treated as JSON-RPC
notifications: handlers run, ex
See [juneau-rest-server-mcp](/docs/topics/JuneauRestServerMcpBasics) for the
full topic.
+### juneau-rest-server-view-jsp (new module)
+
+A new opt-in REST module, `juneau-rest-server-view-jsp`, adds JSP
view-rendering to `juneau-rest-server` without bleeding the JSP-engine
dependency (Apache Jasper) into the core. The new `View` interface (see
[juneau-rest-server](#juneau-rest-server)) lives in core; this module ships the
JSP-specific implementation. Engine-agnostic POM stance: the bridge module
declares the JSP API + JSTL impl in `provided` scope only — consumers add the
engine matching their container (Jetty 12 EE11's ` [...]
+
+#### New Classes
+
+- **`org.apache.juneau.rest.view.jsp.BasicJspResource`** — REST mixin
attachable via `@Rest(mixins=BasicJspResource.class)`. Adds a default `/jsp/*`
mount that forwards raw `.jsp` requests to the container's JSP engine, and
contributes `JspViewRenderer` to the mixin's response-processor chain. Builder
API: `BasicJspResource.create().basePath("/WEB-INF/views/").build()`.
+- **`org.apache.juneau.rest.view.jsp.JspView`** — `View` implementation.
Immutable value class; fluent builder: `JspView.of("hello.jsp").attr("name",
name).header("Cache-Control", "no-store")`. `attr(...)` rejects `null` values
because Servlet-spec `setAttribute(name, null)` deletes the binding rather than
setting it.
+- **`org.apache.juneau.rest.view.jsp.JspViewRenderer`** — `ResponseProcessor`
that detects `JspView`-typed return values and dispatches via
`ServletContext.getRequestDispatcher(...).forward(...)`. When no JSP engine is
on the classpath, surfaces `NO_ENGINE_DIAGNOSTIC` naming the missing dependency.
+
+#### Dependency
+
+```xml
+<dependency>
+ <groupId>org.apache.juneau</groupId>
+ <artifactId>juneau-rest-server-view-jsp</artifactId>
+ <version>9.5.0</version>
+</dependency>
+<!-- pick ONE of these (engine-agnostic stance): -->
+<dependency>
+ <groupId>org.eclipse.jetty.ee11</groupId>
+ <artifactId>jetty-ee11-apache-jsp</artifactId>
+ <version>12.1.8</version> <!-- Jetty 12 EE11 -->
+</dependency>
+<!-- OR -->
+<dependency>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-jasper</artifactId>
+ <version>10.1.34</version> <!-- embedded Tomcat / Spring Boot
default -->
+</dependency>
+```
+
+#### Composition example
+
+```java
+@Rest(path="/app", mixins=BasicJspResource.class)
+public class AppResource extends RestServlet {
+
+ @Bean
+ BasicJspResource jsp() {
+ return BasicJspResource.create()
+ .basePath("/WEB-INF/views/")
+ .build();
+ }
+
+ @RestGet("/hello/{name}")
+ public View hello(@Path String name) {
+ return JspView.of("hello.jsp").attr("name", name);
+ }
+}
+```
+
+See [JSP View Support](/docs/topics/JspViewSupport) for the full topic —
engine-selection matrix, Spring Boot fat-jar caveats, and known limitations.
+
### juneau-bean-rfc7807 (new module)
A new bean module, `juneau-bean-rfc7807`, provides typed beans for [RFC 7807 —
Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc7807)
(`application/problem+json`). RFC 7807 was obsoleted by [RFC
9457](https://www.rfc-editor.org/rfc/rfc9457) in July 2023, but the data model
and the IANA media-type registration are unchanged.
diff --git a/pages/topics/10.14d.JspViewSupport.md
b/pages/topics/10.14d.JspViewSupport.md
new file mode 100644
index 0000000000..44331e313d
--- /dev/null
+++ b/pages/topics/10.14d.JspViewSupport.md
@@ -0,0 +1,237 @@
+---
+title: "JSP View Support"
+slug: JspViewSupport
+---
+
+# JSP View Support
+
+The `juneau-rest-server-view-jsp` module adds JSP (JavaServer Pages)
view-rendering to
+`juneau-rest-server` without bleeding the JSP-engine dependency (Apache
Jasper) into the core.
+
+> This page covers the JSP-specific bridge. For the engine-agnostic
+> [`View`](/site/apidocs/org/apache/juneau/rest/view/View.html) interface
itself, see the
+> [9.5.0 release notes](/docs/release-notes/9.5.0) under the
`juneau-rest-server` section.
+> Sibling view modules (Thymeleaf, Mustache, FreeMarker) are tracked behind
this one and
+> ship the same shape.
+
+## Why JSP?
+
+JSP is niche but real for legacy migrations into Juneau — particularly
internal admin
+consoles and reporting tools that already have a tested `.jsp` template
library and don't
+want to rewrite to React / Thymeleaf. Before `juneau-rest-server-view-jsp`,
integrating a
+`JspServlet` alongside Juneau's `RestServlet` meant fighting servlet-mapping
precedence;
+the mixin packaging makes this clean.
+
+## Module contents
+
+| Class | Role |
+|---|---|
+| [`View`](/site/apidocs/org/apache/juneau/rest/view/View.html) (in
`juneau-rest-server` core) | Engine-agnostic contract: `getTemplateName()`,
`getAttributes()`, `getResponseHeaders()`. |
+|
[`BasicJspResource`](/site/apidocs/org/apache/juneau/rest/view/jsp/BasicJspResource.html)
| Mixin. Mounts `/jsp/*` for raw `.jsp` requests; registers `JspViewRenderer`
on the response-processor chain. Builder: `basePath(String)` (default `/`). |
+| [`JspView`](/site/apidocs/org/apache/juneau/rest/view/jsp/JspView.html) |
`View` implementation. Immutable; fluent: `JspView.of("hello.jsp").attr("name",
name).header("Cache-Control", "no-store")`. |
+|
[`JspViewRenderer`](/site/apidocs/org/apache/juneau/rest/view/jsp/JspViewRenderer.html)
| `ResponseProcessor` that detects `JspView` returns and dispatches via
`ServletContext.getRequestDispatcher(...).forward(...)`. |
+
+## Engine-agnostic packaging
+
+`juneau-rest-server-view-jsp` ships **only the JSP API + JSTL impl in
`provided` scope**.
+No JSP engine is bundled with the bridge module. Consumers add the engine
matching their
+deployment container.
+
+### Choosing a JSP engine
+
+| Container | Recommended engine | Maven coordinates |
+|---|---|---|
+| **Jetty 12 EE11** — `juneau-microservice-jetty`, Spring Boot embedded Jetty
| Eclipse Jetty's repackaged Jasper bundle |
`org.eclipse.jetty.ee11:jetty-ee11-apache-jsp` |
+| **Embedded Tomcat** — Spring Boot default | Apache Tomcat's embedded Jasper
| `org.apache.tomcat.embed:tomcat-embed-jasper` |
+| **External WAR deploy** — Tomcat / JBoss / WildFly / etc. |
Container-supplied | _no additional dependency_ |
+
+When no JSP engine is on the classpath, the renderer surfaces a clear
diagnostic naming
+the missing dependency:
+
+```text
+No JSP engine is available on the classpath. Add one of:
+ - org.eclipse.jetty.ee11:jetty-ee11-apache-jsp (Jetty 12 EE11)
+ - org.apache.tomcat.embed:tomcat-embed-jasper (embedded Tomcat / Spring
Boot default)
+ - Or rely on the deployment container's bundled engine (Tomcat / JBoss /
WildFly / ...)
+See https://juneau.apache.org/docs/topics/JspViewSupport for the full matrix.
+```
+
+The underlying JSP engine in all cases is Apache Jasper (the Tomcat
project's); Jetty's
+artifact is just a repackaged Jasper bundle aligned with a specific Jakarta EE
generation.
+
+## Hello-world
+
+### Maven
+
+```xml
+<dependency>
+ <groupId>org.apache.juneau</groupId>
+ <artifactId>juneau-rest-server-view-jsp</artifactId>
+ <version>9.5.0</version>
+</dependency>
+<!-- pick ONE engine -->
+<dependency>
+ <groupId>org.eclipse.jetty.ee11</groupId>
+ <artifactId>jetty-ee11-apache-jsp</artifactId>
+ <version>12.1.8</version>
+</dependency>
+```
+
+### Resource layout
+
+```text
+src/main/resources/
+ META-INF/resources/WEB-INF/views/
+ hello.jsp
+```
+
+The `META-INF/resources/` prefix is the Servlet 3.0 convention that lets
embedded
+containers (Jetty, Spring-Boot-embedded-Tomcat) discover servlet resources
from a JAR.
+The same layout works under microservice deployments and Spring Boot fat-jar
deployments.
+
+### JSP template (`hello.jsp`)
+
+```jsp
+<%@ page contentType="text/html; charset=UTF-8" %>
+Hello, ${name}!
+```
+
+### REST resource — `View`-return dispatch
+
+```java
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.servlet.*;
+import org.apache.juneau.rest.view.*;
+import org.apache.juneau.rest.view.jsp.*;
+import org.apache.juneau.http.annotation.*;
+
+@Rest(path="/app", mixins=BasicJspResource.class)
+public class AppResource extends RestServlet {
+
+ @Bean
+ BasicJspResource jsp() {
+ return BasicJspResource.create()
+ .basePath("/WEB-INF/views/")
+ .build();
+ }
+
+ @RestGet("/hello/{name}")
+ public View hello(@Path String name) {
+ return JspView.of("hello.jsp").attr("name", name);
+ }
+}
+```
+
+`GET /app/hello/world` returns `Hello, world!` — `JspViewRenderer` intercepts
the
+`JspView` return, copies the `name` attribute onto the request, and forwards
to the JSP
+engine at `/WEB-INF/views/hello.jsp`.
+
+### REST resource — raw-JSP mount
+
+The mixin also installs a default `/jsp/*` mount that forwards raw `.jsp`
requests under
+the configured base path. With `basePath("/WEB-INF/views/")`, a request for
+`GET /app/jsp/hello.jsp` renders `/WEB-INF/views/hello.jsp` directly — no Java
handler
+required.
+
+The greedy `/*` handler is excluded from the generated Swagger / OpenAPI spec
via
+`@OpSwagger(ignore=true)` since the path isn't API-meaningful.
+
+## Spring Boot caveats
+
+Spring Boot's reference docs explicitly recommend Thymeleaf / FreeMarker /
Mustache *over*
+JSP for embedded servlet containers — JSP works under embedded Tomcat / Jetty
but has
+notable sharp edges. Plan for the following:
+
+### Resource layout — fat-jar vs `spring-boot:run`
+
+- A Spring Boot fat jar (`spring-boot-maven-plugin` repackaged) does not place
`.jsp`
+ files where the embedded JSP engine expects them by default. Put `.jsp`
resources under
+ `src/main/resources/META-INF/resources/WEB-INF/views/...`.
+- `spring-boot:run` (Maven plugin) reads from `src/main/resources/` and
+ `src/main/webapp/` directly; the deployed jar reads from the classpath via
+ `META-INF/resources/`.
+- **Both modes must work.** The `META-INF/resources/WEB-INF/views/` layout is
the
+ canonical layout that works under both — use it everywhere.
+
+### `@Bean` registration
+
+```java
+@Configuration
+public class AppConfig {
+
+ @Bean
+ public BasicJspResource jsp() {
+ return BasicJspResource.create()
+ .basePath("/WEB-INF/views/")
+ .build();
+ }
+}
+```
+
+The Spring `BeanStore` adapter resolves the bean through
+`ApplicationContext.getBean(BasicJspResource.class)`; no additional plumbing
is required.
+
+### `@SpringBootTest` notes
+
+End-to-end integration tests for the bridge module under embedded Tomcat
surface two
+known constraints that aren't bridge-module bugs but worth documenting up
front:
+
+1. **Response-processor ordering.** Juneau's default response-processor chain
runs
+ `SerializedPojoProcessor` ahead of mixin-registered processors. When the
host class
+ has a method returning `JspView`, the host class needs to add
`JspViewRenderer` to its
+ *own* `responseProcessors` list to take precedence over the generic POJO
serializer.
+ Tracked as a framework enhancement to add a `prepend` mechanism for mixin
processors.
+2. **Servlet-mapping conflicts.** Juneau's `RestServlet` is mapped at `/*`,
which can
+ intercept `RequestDispatcher.forward(...)` calls intended for the
container's JSP
+ servlet. The Spring Boot integration tests for this scenario are deferred
until a
+ first-class story is in place.
+
+If your deployment hits either of these, file an issue rather than working
around it
+locally — see the follow-up tickets `TODO-96` (response-processor `prepend`)
and
+`TODO-97` (real-container integration tests) for status.
+
+## Multiple base paths
+
+Some apps want `/views/` for the public site and `/admin/views/` for the admin
console.
+Register two `BasicJspResource` beans, each in its own subclass with its own
`paths`
+override:
+
+```java
+@Rest(paths={"/views/*"})
+public class PublicViewsResource extends BasicJspResource {
+ public PublicViewsResource() {
+ super(BasicJspResource.create().basePath("/WEB-INF/views/public/"));
+ }
+}
+
+@Rest(paths={"/admin/views/*"})
+public class AdminViewsResource extends BasicJspResource {
+ public AdminViewsResource() {
+ super(BasicJspResource.create().basePath("/WEB-INF/views/admin/"));
+ }
+}
+```
+
+Both subclasses mount independently and each resolves templates against its own
+`basePath`.
+
+## Limitations and out-of-scope
+
+- **JSF / Facelets** — not planned. JSF is a separate concern; if ever
requested, ships
+ as a sibling `juneau-rest-server-view-jsf` module.
+- **Custom tag libraries beyond JSTL** — users supply their own taglibs via
classpath
+ dependencies; the bridge module doesn't bundle them.
+- **Server-side includes (SSI)** — separate concern, not commonly mixed with
JSP.
+- **Pre-compiled JSP classfile loading** — bypassing the JSP engine entirely
is a
+ performance optimization deferred to a future release.
+- **`RequestDispatcher.forward()` resets the response output stream.** A
+ `@RestPreCall`-hook that has already written response headers/body before
the renderer
+ runs may break the forward. The renderer runs at response-resolution time so
this is
+ rarely hit by accident; document it for any caller relying on `RestPreCall`.
+
+## See also
+
+- [REST Server — Composition (mixins,
paths)](/docs/topics/RestServerComposition)
+- [REST Server — Static-Files Mixin](/docs/topics/StaticFilesMixin)
+- [Response Processors](/docs/topics/ResponseProcessors)
+- [9.5.0 release notes — `juneau-rest-server-view-jsp` (new
module)](/docs/release-notes/9.5.0)
diff --git a/sidebars.ts b/sidebars.ts
index 6a2c2111a3..2e9ccc1f1f 100644
--- a/sidebars.ts
+++ b/sidebars.ts
@@ -1392,6 +1392,11 @@ const sidebars: SidebarsConfig = {
id:
'topics/10.14c.OpsIntrospectionMixins',
label: '10.14c. Ops /
Introspection Mixin Pack',
},
+ {
+ type: 'doc',
+ id:
'topics/10.14d.JspViewSupport',
+ label: '10.14d. JSP
View Support',
+ },
{
type: 'doc',
id:
'topics/10.15.ClientVersioning',