Class FreemarkerView

java.lang.Object
org.apache.juneau.rest.server.view.freemarker.FreemarkerView
All Implemented Interfaces:
View

public final class FreemarkerView extends Object implements View
Immutable value class returned from @RestOp-annotated methods to ask the framework to render an Apache FreeMarker template.

Companion to FreemarkerMixin and FreemarkerViewRenderer: the mixin sets up the /freemarker/* mount and registers the renderer; the renderer detects FreemarkerView returns in the response-processor chain and asks the configured freemarker.template.Configuration to getTemplate(templateName) and then process(dataModel, writer) directly onto the response writer.

Usage:

@RestGet("/hello/{name}") public View hello(@Path String name) { return FreemarkerView.of("hello.ftlh") .attr("name", name) .attr("ts", Instant.now()); }

The template name is configuration-relative — the configured freemarker.template.Configuration template loader prepends its own resource root. With the bridge's default configuration + basePath("/templates/"), FreemarkerView.of("hello.ftlh") resolves to /templates/hello.ftlh on the classpath.

.ftl vs .ftlh auto-escape:

FreeMarker auto-selects HTML escaping by file extension: .ftlh templates emit HTML-escaped output (variable references are escaped automatically), while .ftl templates emit raw output. For HTML responses, prefer the .ftlh extension to avoid an XSS regression sneaking in via a future attribute-binding change.

Template suffix:

The templateSuffix(...) builder knob lets the bridge append a suffix (e.g. ".ftlh") to template names that don't already end with it, so callers can write FreemarkerView.of("hello") and have the bridge resolve it as "hello.ftlh" on the classpath (idempotent — explicit suffix is honored).

Immutability:

Each attr(...) / attrs(...) / header(...) call returns a new FreemarkerView carrying the additional binding; the original instance is unchanged. This keeps FreemarkerView a value type safe to share across requests (e.g. as a static singleton built once and returned from many handlers).

See Also:
Since:
10.0.0
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static interface 
    Marker for an attribute value that promises to be adopted during the render (unwrapped from the data model by some directive and applied to render-scoped state), and wants the render to fail if that never happens instead of silently behaving as if the attribute was absent.
  • Method Summary

    Modifier and Type
    Method
    Description
    attr(String key, Object value)
    Returns a copy of this view with the given attribute added (or replaced if a binding for key already exists).
    attrs(Map<String,?> values)
    Returns a copy of this view with all entries from the given map added (or replaced if a binding for any key already exists).
    The attributes to expose to the template.
    Optional response headers applied by the renderer before forwarding to the templating engine.
    The name of the template to render — typically a path relative to the mixin-configured base path.
    header(String name, String value)
    Returns a copy of this view with the given response header set on the rendered response.
    of(String templateName)
    Creates a new FreemarkerView carrying the given template name and no attributes.
     

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
  • Method Details

    • of

      public static FreemarkerView of(String templateName)
      Creates a new FreemarkerView carrying the given template name and no attributes.

      The template name is configuration-relative; the configured freemarker.template.Configuration template loader supplies the prefix (resource root). With the bridge's default configuration + basePath("/templates/"), the name "hello.ftlh" resolves to /templates/hello.ftlh on the classpath.

      Parameters:
      templateName - The template name (configuration-relative, suffix optional when the mixin's templateSuffix is configured). Must not be null or blank.
      Returns:
      A new FreemarkerView instance.
      Throws:
      IllegalArgumentException - If templateName is null or blank.
    • attr

      public FreemarkerView attr(String key, Object value)
      Returns a copy of this view with the given attribute added (or replaced if a binding for key already exists).

      The full attribute map is passed to FreeMarker as the data model, so each entry is accessible inside the template as ${key}. null values are rejected at build-time because FreeMarker's default null-handling renders missing/null bindings as an error or empty string depending on configuration, which typically masks what is a caller bug; rejecting up-front surfaces the mistake at the call site (matches the Thymeleaf / Mustache bridge precedents).

      Parameters:
      key - The attribute key (exposed inside the template as ${key}). Must not be null or blank.
      value - The attribute value. Must not be null.
      Returns:
      A new FreemarkerView carrying the additional attribute.
      Throws:
      IllegalArgumentException - If key is null or blank, or value is null.
    • attrs

      public FreemarkerView attrs(Map<String,?> values)
      Returns a copy of this view with all entries from the given map added (or replaced if a binding for any key already exists).
      Parameters:
      values - The attributes to add. null is treated as an empty map (the result is the same instance with no entries added).
      Returns:
      A new FreemarkerView carrying the additional attributes.
      Throws:
      IllegalArgumentException - If any entry has a null/blank key or a null value.
    • header

      public FreemarkerView header(String name, String value)
      Returns a copy of this view with the given response header set on the rendered response.

      Typical usage: .header("Content-Type", "text/html; charset=UTF-8") or .header("Cache-Control", "no-store"). The renderer applies these headers via HttpServletResponse.setHeader(...) before writing the rendered output.

      Parameters:
      name - The header name. Must not be null or blank.
      value - The header value. Must not be null.
      Returns:
      A new FreemarkerView carrying the additional response header.
      Throws:
      IllegalArgumentException - If name is null or blank, or value is null.
    • getTemplateName

      Description copied from interface: View
      The name of the template to render — typically a path relative to the mixin-configured base path.

      For example, "hello.jsp" with a JSP mixin basePath("/WEB-INF/views/") resolves to "/WEB-INF/views/hello.jsp" on the request dispatcher.

      Specified by:
      getTemplateName in interface View
      Returns:
      The template name. Never null.
    • getAttributes

      Description copied from interface: View
      The attributes to expose to the template.

      Each entry is forwarded to the templating engine as a named binding accessible from inside the template (e.g. ${name} in JSP / EL, th:text="${name}" in Thymeleaf).

      Specified by:
      getAttributes in interface View
      Returns:
      The attributes map. Never null; returns an immutable empty map when no attributes are bound.
    • getResponseHeaders

      Description copied from interface: View
      Optional response headers applied by the renderer before forwarding to the templating engine.

      Typical use cases: setting Content-Type (e.g. "text/html; charset=UTF-8") or Cache-Control on the rendered response. The default implementation returns an empty map so most View impls don't need to override it.

      Specified by:
      getResponseHeaders in interface View
      Returns:
      An immutable map of headers to apply. Never null; defaults to an empty map.
    • toString

      public String toString()
      Overrides:
      toString in class Object