Class ThymeleafMixin

java.lang.Object
org.apache.juneau.rest.server.view.thymeleaf.ThymeleafMixin

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

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

  1. Gains a default mount at /thymeleaf/* that serves raw .html templates from the importer's classpath by asking the configured TemplateEngine to render them with the current request's locale and attributes available to the template.
  2. Routes the host's own @RestOp-method return values of type ThymeleafView through the Thymeleaf engine automatically. ThymeleafMixin declares @Rest(mergeResponseProcessorsIntoHost=true), so a plain @Rest(mixins=ThymeleafMixin.class) folds its ThymeleafViewRenderer into the host's own response-processor chain — no mergeIntoHost or explicit responseProcessors= on the host needed.
Composition example (microservice):

@Rest(path="/app", mixins=ThymeleafMixin.class) public class AppResource extends RestServlet { @Bean ThymeleafMixin thymeleaf() { return ThymeleafMixin.create() .basePath("/templates/") .build(); } @RestGet("/hello/{name}") public View hello(@Path String name) { return ThymeleafView.of("hello").attr("name", name); } }

Configurable mount path:

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

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.thymeleaf.path:thymeleaf}/*") 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).

Choosing a TemplateEngine:

The juneau-rest-server-view-thymeleaf module ships only the Thymeleaf core API in provided scope. No engine bean is bundled. The bridge resolves a TemplateEngine at first use from three sources, in order:

  • Spring Boot autoconfig: spring-boot-starter-thymeleaf contributes an autoconfigured SpringTemplateEngine (which extends TemplateEngine); the bridge picks it up via BeanStore.getBean(TemplateEngine.class). No further wiring needed.
  • User-supplied bean: register a @Bean TemplateEngine (Spring) or BasicBeanStore.put(TemplateEngine.class, engine) (microservice). Allows full control of resolvers, dialects, and template modes.
  • Bridge default: when nothing is registered, the bridge constructs a default TemplateEngine with a single ClassLoaderTemplateResolver configured with prefix=basePath, suffix=".html", templateMode=HTML, and cacheable=cacheTemplates (default true — production-safe; set cacheTemplates(false) on the builder for hot-reload during development).

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

Multiple base paths:

A host with /templates/ and /admin/templates/ template trees registers two ThymeleafMixin beans, each mounted via a subclass declaring its own op-level @RestGet(path=...) override and its own basePath. See the ThymeleafMixin_MockRest_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