StreamingTemplateEngine (Groovy 5.1.0)
Description: declaration: package: groovy.text, class: StreamingTemplateEngine

Package groovy.text

# Class StreamingTemplateEngine

java.lang.Object
groovy.text.TemplateEngine
groovy.text.StreamingTemplateEngine

public class StreamingTemplateEngine extends TemplateEngine
Processes template source files substituting variables and expressions into placeholders in a template source text to produce the desired output using a closure based approach. This engine has equivalent functionality to the `SimpleTemplateEngine` but creates the template using writable closures making it more scalable for large templates.

Specifically this template engine can handle strings larger than 64k which still causes problems for the other groovy template engines.

The template engine uses JSP style <% %> script and <%= %> expression syntax or GString style expressions. The variable '`out`' is bound to the writer that the template is being written to.

Frequently, the template source will be in a file but here is a simple example providing the template as a string:

     def binding = [
       firstname : "Grace",
       lastname  : "Hopper",
       accepted  : true,
       title     : 'Groovy for COBOL programmers'
     ]
     def text = '''\
     Dear <% out.print firstname %> ${lastname},

     We <% if (accepted) out.print 'are pleased' else out.print 'regret' %> \
     to inform you that your paper entitled
     '$title' was ${ accepted ? 'accepted' : 'rejected' }.

     The conference committee.
     '''

     def template = new groovy.text.StreamingTemplateEngine().createTemplate(text)

     print template.make(binding)

This example uses a mix of the JSP style and GString style placeholders but you can typically use just one style if you wish. Running this example will produce this output:

     Dear Grace Hopper,

     We are pleased to inform you that your paper entitled
     'Groovy for COBOL programmers' was accepted.

     The conference committee.

### StreamingTemplateEngine as a servlet engine

The template engine can also be used as the engine for `groovy.servlet.TemplateServlet` by placing the following in your `web.xml` file (plus a corresponding servlet-mapping element):

     <servlet>
       <servlet-name>StreamingTemplate</servlet-name>
       <servlet-class>groovy.servlet.TemplateServlet</servlet-class>
       <init-param>
         <param-name>template.engine</param-name>
         <param-value>groovy.text.StreamingTemplateEngine</param-value>
       </init-param>
     </servlet>

In this case, your template source file should be HTML with the appropriate embedded placeholders.

### Debugging Template Code

The template engine makes an effort to throw descriptive exceptions with context lines, ie:

      groovy.text.TemplateExecutionException: Template parse error at line 4:
               3: We <% if (accepted) out.print 'are pleased' else out.print 'regret' %> to inform you that your paper entitled
           --> 4: '$txitle' was ${ accepted ? 'accepted' : 'rejected' }.
               5:
     at test.run(test.groovy:18)

     Caused by: groovy.lang.MissingPropertyException: No such property: txitle for class: groovy.tmp.templates.StreamingTemplateScript1
     ... 1 more

and sanitize the exceptions to make things readable.

When the exceptions are not enough, it might sometimes be useful to view the actual script source generated by the template engine. This would conceptually be equivalent to viewing the .java file generated for a jsp page. The source is not currently very readable and until we get a built in groovy code pretty printer, we will probably continue to opt for compactness rather than readability.

With that being said, viewing the source might still have some value. For this reason the script source is accessible via the template.scriptSource property, i.e.:

         println template.scriptSource

In the above example.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `StreamingTemplateEngine()`
  Create a streaming template engine instance using the default class loader
  `StreamingTemplateEngine(ClassLoader parentLoader)`
  Create a streaming template engine instance using a custom class loader

- ## Method Summary

  Modifier and Type
  Method
  Description
  `Template`
  `createTemplate(Reader reader)`
  Creates a template instance using the template source from the provided Reader.

  ### Methods inherited from class groovy.text.TemplateEngine

  `createTemplate, createTemplate, createTemplate, createTemplate, createTemplate`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Constructor Details

  - ### StreamingTemplateEngine

    public StreamingTemplateEngine()
    Create a streaming template engine instance using the default class loader

  - ### StreamingTemplateEngine

    public StreamingTemplateEngine(ClassLoader parentLoader)
    Create a streaming template engine instance using a custom class loader

    The custom loader is used when parsing the template code

    Parameters:
      `parentLoader` - The class loader to use when parsing the template code.

- ## Method Details

  - ### createTemplate

    public Template createTemplate(Reader reader) throws CompilationFailedException, ClassNotFoundException, IOException
    Creates a template instance using the template source from the provided Reader.

    The template can be applied repeatedly on different bindings to produce custom output. Technical detail
    Under the hood the returned template is represented as a four argument closure where the three first arguments are `curried` in while generating the template.
    In essence we start with a closure on the form:

           { parentClass, stringSectionList, binding, out ->
              //code generated by parsing the template data
           }

    We then curry in the parentClass and stringSectionList arguments so that the StreamingTemplate instance returned from 'createTemplate' internally contains a template closure on the form:

           { binding, out ->
              //code generated by parsing the template data
           }

    Calling `template.make(binding)`, curries in the 'binding' argument:

           public Writable make(final Map map) {
             final Closure template = this.template.curry(new Object[]{map});
             return (Writable) template;
           }

    This only leaves the 'out' argument unbound. The only method on the `writable` interface is `writeTo(Writer out)` so groovy rules about casting a closure to a one-method-interface apply and the above works. I.e. we return the now one argument closure as the Writable which can be serialized to System.out, a file, etc according to the Writable interface contract.

    Specified by:
      `createTemplate` in class `TemplateEngine`
    Throws:
      `CompilationFailedException`
      `ClassNotFoundException`
      `IOException`
    See Also:
      - `TemplateEngine.createTemplate(java.io.Reader)`