Class JspMixin

java.lang.Object
org.apache.juneau.rest.server.view.jsp.JspMixin

public class JspMixin extends Object
Mixin that wires JSP view-rendering onto any Juneau REST resource.

Compose into a host resource via @Rest(mixins=JspMixin.class); the host then:

  1. Gains a default mount at /jsp/* that serves raw .jsp resources from the importer's classpath via forward(...).
  2. Registers JspViewRenderer for the mixin's own endpoints (e.g. the /jsp/* route above) via the mixin's own @Rest(responseProcessors=...) declaration.
Auto-wiring the renderer into the host's own endpoints:

A bare @Rest(mixins=JspMixin.class) is enough — a host whose own @RestOp method returns JspView renders it through the JSP engine with no extra wiring. That works because JspMixin declares @Rest(mergeResponseProcessorsIntoHost=true) on its own class, so the framework folds JspMixin's JspViewRenderer into the host's own response-processor chain automatically.

This fold is per-mixin, opt-in, and response-processor-scoped: it happens only because JspMixin declares the opt-in (a mixin that does not is still scoped to its own endpoints, the standard @Rest(mixins=...) rule), and it folds only the renderer — never guards, serializers, or any other list-shaped attribute.

Two explicit wirings remain supported — useful when you want to be explicit, or to fold more than the renderer:

  1. @Mixin(mergeIntoHost=true) via the rich mixinDefs form — folds all of JspMixin's list-shaped @Rest attributes into the host's own chain, not just the renderer.
  2. List JspViewRenderer.class explicitly in the host's own @Rest(responseProcessors=...) — the fully manual equivalent.

The ResponseProcessorList partition pass repositions JspViewRenderer (a ViewRenderer) ahead of SerializedPojoProcessor in every case, so the JspView bean is dispatched to the JSP engine rather than bean-serialized.

Composition example (microservice):

@Rest(path="/app", mixins=JspMixin.class) public class AppResource extends RestServlet { @Bean JspMixin jsp() { return JspMixin.create() .basePath("/WEB-INF/views/") .build(); } @RestGet("/hello/{name}") public View hello(@Path String name) { return JspView.of("hello.jsp").attr("name", name); } }

Configurable mount path:

The default mount /jsp/* can be overridden via the SVL variable ${juneau.jsp.path:jsp} — set via system property (-Djuneau.jsp.path=views), environment variable (JUNEAU_JSP_PATH=views), or Config key (juneau.jsp.path = views) to change the runtime mount without subclassing. Resolution happens once at RestContext construction time (SVL resolution in @RestOp(path)).

Override accepts bare token (jsp), leading slash (/jsp), trailing slash (jsp/), or wildcard suffix (/jsp/*) — all resolve to the same mount.

Mixin-only deployment:

This resource is designed for composition via @Rest(mixins=...). The mount path is pinned at the op level by @RestGet(path="/{juneau.jsp.path:jsp}/*") on render(java.lang.String, org.apache.juneau.rest.server.RestRequest, org.apache.juneau.rest.server.RestResponse); a class-level @Rest(paths=...) declaration would be silently ignored under the mixin pattern (see @Rest(paths) Javadoc).

Engine-agnostic packaging:

The juneau-rest-server-view-jsp module 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 container:

  • Jetty 12 EE11 (microservice-jetty, Spring Boot embedded Jetty): org.eclipse.jetty.ee11:jetty-ee11-apache-jsp.
  • Embedded Tomcat (Spring Boot default): org.apache.tomcat.embed:tomcat-embed-jasper.
  • External-WAR deployments: container-supplied; no additional dependency.

When no engine is on the classpath, the renderer surfaces JspViewRenderer.NO_ENGINE_DIAGNOSTIC naming the missing dependency.

Spring Boot fat-jar caveat:

Spring Boot's repackaged fat jar does not place .jsp files where the embedded JSP engine looks by default. Place JSP resources under src/main/resources/META-INF/resources/WEB-INF/views/... (the META-INF/resources/ prefix is the Servlet 3.0 convention Spring Boot honors for embedded servlets). Both mvn spring-boot:run and the deployed jar pick the files up this way.

Multiple base paths:

A host with /views/ JSPs and /admin/views/ JSPs registers two JspMixin beans, each mounted via a subclass declaring its own op-level @RestGet(path=...) override and its own basePath. See the JspMixin_MultiBasePath_Test test in juneau-integration-tests for the canonical pattern.

OpenAPI surface:

The greedy /* handler is not API-meaningful and is excluded from generated Swagger / OpenAPI specs via @OpSwagger(ignore=true).

See Also:
Since:
10.0.0