Groovy templating engines providing JSP-style scripting, GString expressions, markup builders, and streaming template capabilities for generating dynamic content from templates with variable substitution and control flow
—
The StreamingTemplateEngine provides the same functionality as SimpleTemplateEngine but is optimized for large templates (>64k characters) using a closure-based approach. It offers better memory efficiency, superior error reporting with line numbers and context, and handles very large templates that cause problems for other engines.
class StreamingTemplateEngine extends TemplateEngine {
StreamingTemplateEngine();
StreamingTemplateEngine(ClassLoader parentLoader);
Template createTemplate(Reader reader) throws CompilationFailedException, ClassNotFoundException, IOException;
}Same as SimpleTemplateEngine and GStringTemplateEngine:
<% ... %> - Execute Groovy code<%= ... %> - Output expression result${...} and $variable - Variable interpolationout - Writer bound to template outputThe StreamingTemplateEngine can handle templates larger than 64k characters, while other Groovy template engines may fail with such large templates.
Provides descriptive exceptions with context lines showing exactly where errors occur:
groovy.text.TemplateExecutionException: Template execution 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:
Caused by: groovy.lang.MissingPropertyException: No such property: txitle for class: groovy.tmp.templates.StreamingTemplateScript1Uses a streaming closure-based approach that processes templates incrementally rather than building large strings in memory.
import groovy.text.StreamingTemplateEngine;
import groovy.text.Template;
import java.util.HashMap;
import java.util.Map;
StreamingTemplateEngine engine = new StreamingTemplateEngine();
String templateText = """
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.
""";
Template template = engine.createTemplate(templateText);
Map<String, Object> binding = new HashMap<>();
binding.put("firstname", "Grace");
binding.put("lastname", "Hopper");
binding.put("accepted", true);
binding.put("title", "Groovy for COBOL programmers");
String result = template.make(binding).toString();// Process a very large template (>64k characters)
StreamingTemplateEngine engine = new StreamingTemplateEngine();
// Read large template from file
File largeTemplateFile = new File("large-report-template.gsp");
Template template = engine.createTemplate(largeTemplateFile);
// Process with data
Map<String, Object> binding = new HashMap<>();
binding.put("records", largeDataSet); // Large dataset
binding.put("reportDate", new Date());
// Stream directly to file to avoid memory issues
try (FileWriter writer = new FileWriter("output-report.html");
BufferedWriter bufferedWriter = new BufferedWriter(writer)) {
template.make(binding).writeTo(bufferedWriter);
}ClassLoader customLoader = MyClass.class.getClassLoader();
StreamingTemplateEngine engine = new StreamingTemplateEngine(customLoader);
Template template = engine.createTemplate(templateSource);Access the generated script source for debugging:
StreamingTemplateEngine engine = new StreamingTemplateEngine();
Template template = engine.createTemplate(templateText);
// Access the generated script source (internal property)
// Note: This requires casting to internal implementation class
if (template instanceof groovy.text.StreamingTemplateEngine.StreamingTemplate) {
String scriptSource = ((groovy.text.StreamingTemplateEngine.StreamingTemplate) template).scriptSource;
System.out.println("Generated script:");
System.out.println(scriptSource);
}Template template = engine.createTemplate(templateText);
Writable writable = template.make(binding);
// Stream to string
String result = writable.toString();
// Stream to file
try (FileWriter fileWriter = new FileWriter("output.txt")) {
writable.writeTo(fileWriter);
}
// Stream to HTTP response
// response.setContentType("text/html");
// writable.writeTo(response.getWriter());
// Stream to any Writer
StringWriter stringWriter = new StringWriter();
writable.writeTo(stringWriter);String templateText = """
<html>
<head><title>$title</title></head>
<body>
<h1>$title</h1>
<% if (showSummary) { %>
<div class="summary">
<h2>Summary</h2>
<p>Total items: ${items.size()}</p>
<p>Total value: \\$${items.sum { it.price * it.quantity }}</p>
</div>
<% } %>
<div class="items">
<% items.eachWithIndex { item, index -> %>
<div class="item ${index % 2 == 0 ? 'even' : 'odd'}">
<h3>${item.name}</h3>
<p>Price: \\$${item.price}</p>
<p>Quantity: ${item.quantity}</p>
<% if (item.description) { %>
<p class="description">${item.description}</p>
<% } %>
</div>
<% } %>
</div>
<footer>
Generated on <%= new Date().format('yyyy-MM-dd HH:mm:ss') %>
</footer>
</body>
</html>
""";import groovy.text.TemplateExecutionException;
import groovy.text.TemplateParseException;
try {
StreamingTemplateEngine engine = new StreamingTemplateEngine();
Template template = engine.createTemplate(templateSource);
String result = template.make(binding).toString();
} catch (TemplateExecutionException e) {
// Enhanced error reporting with line numbers and context
System.err.println("Template execution failed:");
System.err.println(e.getMessage()); // Includes context lines
System.err.println("Error at line: " + e.getLineNumber());
} catch (TemplateParseException e) {
// Parse-time errors with line and column information
System.err.println("Template parse error at line " + e.getLineNumber() +
", column " + e.getColumn() + ": " + e.getMessage());
} catch (Exception e) {
System.err.println("Other template error: " + e.getMessage());
}<!-- web.xml -->
<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>| Feature | SimpleTemplateEngine | GStringTemplateEngine | StreamingTemplateEngine |
|---|---|---|---|
| Template size limit | ~64k | ~64k | Unlimited |
| Memory efficiency | Low | Medium | High |
| Error reporting | Basic | Basic | Detailed with context |
| Performance | Good | Better | Best for large templates |
| Debugging features | Verbose mode | None | Script source access |
writeTo(Writer) instead of toString() for large outputsInstall with Tessl CLI
npx tessl i tessl/maven-org-codehaus-groovy--groovy-templates