Apache Groovy is a powerful multi-faceted programming language for the JVM platform
—
Comprehensive templating system with multiple engines for generating dynamic text output. Includes SimpleTemplateEngine for basic templating, GStringTemplateEngine for GString-based templates, and specialized engines for XML/HTML generation with streaming support.
Basic templating engine using GString syntax for variable substitution and simple expressions.
/**
* Simple template engine using GString syntax for basic templating
*/
class SimpleTemplateEngine extends TemplateEngine {
/**
* Create template engine with default configuration
*/
SimpleTemplateEngine();
/**
* Create template engine with custom ClassLoader
*/
SimpleTemplateEngine(ClassLoader parentLoader);
/**
* Create template from string
*/
Template createTemplate(String templateText) throws CompilationFailedException;
/**
* Create template from Reader
*/
Template createTemplate(Reader reader) throws CompilationFailedException;
/**
* Create template from File
*/
Template createTemplate(File file) throws CompilationFailedException;
/**
* Create template from URL
*/
Template createTemplate(URL url) throws CompilationFailedException;
}
/**
* Compiled template that can be applied to binding data
*/
interface Template {
/**
* Apply template with binding data
*/
Writable make(Map binding);
/**
* Apply template with empty binding
*/
Writable make();
}
/**
* Template output that can be written to various destinations
*/
interface Writable {
/**
* Write template output to Writer
*/
Writer writeTo(Writer out) throws IOException;
/**
* Get template output as String
*/
String toString();
}Usage Examples:
import groovy.text.SimpleTemplateEngine
def engine = new SimpleTemplateEngine()
// Basic variable substitution
def template = engine.createTemplate('Hello $name, welcome to $location!')
def binding = [name: 'John', location: 'New York']
def result = template.make(binding)
println result.toString()
// Output: Hello John, welcome to New York!
// Template with expressions
def emailTemplate = engine.createTemplate('''
Dear $customer.name,
Your order #${order.id} for $${order.total} has been ${order.status.toLowerCase()}.
Order Details:
<% order.items.each { item -> %>
- ${item.name}: $${item.price} x ${item.quantity}
<% } %>
Total: $${order.total}
Thank you for your business!
''')
def orderData = [
customer: [name: 'Alice Johnson'],
order: [
id: 12345,
total: 89.97,
status: 'SHIPPED',
items: [
[name: 'Widget A', price: 29.99, quantity: 2],
[name: 'Widget B', price: 29.99, quantity: 1]
]
]
]
def email = emailTemplate.make(orderData)
println email.toString()
// Template from file
def fileTemplate = engine.createTemplate(new File('invoice.template'))
def invoice = fileTemplate.make([
invoiceNumber: 'INV-2023-001',
date: new Date(),
customer: 'ACME Corp',
items: [
[description: 'Consulting', hours: 40, rate: 150],
[description: 'Development', hours: 80, rate: 125]
]
])
// Write to file
new File('invoice.html').withWriter { writer ->
invoice.writeTo(writer)
}Template engine that treats the entire template as a GString for more natural Groovy syntax.
/**
* Template engine using GString evaluation for natural Groovy syntax
*/
class GStringTemplateEngine extends TemplateEngine {
/**
* Create GString template engine
*/
GStringTemplateEngine();
/**
* Create GString template engine with custom ClassLoader
*/
GStringTemplateEngine(ClassLoader parentLoader);
/**
* Create template from string
*/
Template createTemplate(String templateText) throws CompilationFailedException;
/**
* Create template from Reader
*/
Template createTemplate(Reader reader) throws CompilationFailedException;
}Usage Examples:
import groovy.text.GStringTemplateEngine
def engine = new GStringTemplateEngine()
// More flexible expression syntax
def template = engine.createTemplate('''
Report Generated: ${new Date().format('yyyy-MM-dd HH:mm')}
Summary for ${period}:
- Total Users: ${stats.totalUsers}
- Active Users: ${stats.activeUsers} (${(stats.activeUsers/stats.totalUsers*100).round(1)}%)
- Revenue: $${stats.revenue.round(2)}
Top Products:
${products.take(5).collect { "- ${it.name}: ${it.sales} sales" }.join('\\n')}
''')
def reportData = [
period: 'Q4 2023',
stats: [
totalUsers: 10000,
activeUsers: 7500,
revenue: 125000.50
],
products: [
[name: 'Product A', sales: 450],
[name: 'Product B', sales: 380],
[name: 'Product C', sales: 295],
[name: 'Product D', sales: 210],
[name: 'Product E', sales: 185]
]
]
def report = template.make(reportData)
println report.toString()Memory-efficient template engine for generating large documents without loading everything into memory.
/**
* Memory-efficient streaming template engine for large documents
*/
class StreamingTemplateEngine extends TemplateEngine {
/**
* Create streaming template engine
*/
StreamingTemplateEngine();
/**
* Create streaming template engine with custom ClassLoader
*/
StreamingTemplateEngine(ClassLoader parentLoader);
/**
* Create template from string
*/
Template createTemplate(String templateText) throws CompilationFailedException;
/**
* Create template from Reader
*/
Template createTemplate(Reader reader) throws CompilationFailedException;
}Usage Examples:
import groovy.text.StreamingTemplateEngine
def engine = new StreamingTemplateEngine()
// Large report template
def template = engine.createTemplate('''
<html>
<head><title>Large Data Report</title></head>
<body>
<h1>Data Export - ${title}</h1>
<table>
<tr><th>ID</th><th>Name</th><th>Value</th><th>Status</th></tr>
<% data.each { row -> %>
<tr>
<td>${row.id}</td>
<td>${row.name}</td>
<td>${row.value}</td>
<td>${row.status}</td>
</tr>
<% } %>
</table>
</body>
</html>
''')
// Generate large dataset
def largeDataset = (1..100000).collect { id ->
[
id: id,
name: "Item $id",
value: Math.random() * 1000,
status: ['Active', 'Inactive', 'Pending'][id % 3]
]
}
def binding = [
title: 'Complete Data Export',
data: largeDataset
]
// Stream directly to file to avoid memory issues
new File('large_report.html').withWriter { writer ->
def result = template.make(binding)
result.writeTo(writer) // Streams output without loading all in memory
}Specialized template engine for generating well-formed XML with namespace support and XML-aware features.
/**
* XML-aware template engine with namespace and validation support
*/
class XmlTemplateEngine extends TemplateEngine {
/**
* Create XML template engine
*/
XmlTemplateEngine();
/**
* Create XML template engine with custom ClassLoader
*/
XmlTemplateEngine(ClassLoader parentLoader);
/**
* Create XML template engine with validation
*/
XmlTemplateEngine(boolean validating);
/**
* Create template from string
*/
Template createTemplate(String templateText) throws CompilationFailedException;
}Usage Examples:
import groovy.text.XmlTemplateEngine
def engine = new XmlTemplateEngine()
// XML configuration template
def template = engine.createTemplate('''
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://example.com/config" version="${version}">
<database>
<host>${db.host}</host>
<port>${db.port}</port>
<name>${db.name}</name>
</database>
<features>
<% features.each { feature -> %>
<feature name="${feature.name}" enabled="${feature.enabled}" />
<% } %>
</features>
<users>
<% users.each { user -> %>
<user id="${user.id}">
<name>${user.name}</name>
<email>${user.email}</email>
<roles>
<% user.roles.each { role -> %>
<role>${role}</role>
<% } %>
</roles>
</user>
<% } %>
</users>
</configuration>
''')
def configData = [
version: '2.1',
db: [
host: 'localhost',
port: 5432,
name: 'production'
],
features: [
[name: 'caching', enabled: true],
[name: 'logging', enabled: true],
[name: 'debugging', enabled: false]
],
users: [
[id: 1, name: 'Admin', email: 'admin@example.com', roles: ['admin', 'user']],
[id: 2, name: 'John', email: 'john@example.com', roles: ['user']]
]
]
def xmlConfig = template.make(configData)
println xmlConfig.toString()Type-safe template engine for generating HTML/XML with compile-time validation and IDE support.
/**
* Type-safe markup template engine with compile-time validation
*/
class MarkupTemplateEngine extends TemplateEngine {
/**
* Create markup template engine with configuration
*/
MarkupTemplateEngine(TemplateConfiguration configuration);
/**
* Create template from string
*/
Template createTemplate(String templateText) throws CompilationFailedException;
/**
* Create template from File
*/
Template createTemplate(File templateFile) throws CompilationFailedException;
/**
* Create type-checked template
*/
Template createTypeCheckedTemplate(String templateText) throws CompilationFailedException;
}
/**
* Configuration for markup template engine
*/
class TemplateConfiguration {
/**
* Set whether to cache templates
*/
void setCacheTemplates(boolean cache);
/**
* Set auto-indent for generated markup
*/
void setAutoIndent(boolean autoIndent);
/**
* Set auto-newline for generated markup
*/
void setAutoNewLine(boolean autoNewLine);
/**
* Set locale for template
*/
void setLocale(Locale locale);
/**
* Set base template class
*/
void setBaseTemplateClass(Class<?> baseTemplateClass);
}Usage Examples:
import groovy.text.markup.MarkupTemplateEngine
import groovy.text.markup.TemplateConfiguration
// Configure template engine
def config = new TemplateConfiguration()
config.autoIndent = true
config.autoNewLine = true
config.cacheTemplates = true
def engine = new MarkupTemplateEngine(config)
// Type-safe HTML template
def template = engine.createTemplate('''
html {
head {
title(pageTitle)
meta(charset: 'UTF-8')
link(rel: 'stylesheet', href: '/css/main.css')
}
body {
header {
h1(pageTitle)
nav {
ul {
menuItems.each { item ->
li {
a(href: item.url, item.text)
}
}
}
}
}
main {
articles.each { article ->
article {
h2(article.title)
p(class: 'meta', "Published: ${article.date}")
div(class: 'content') {
yieldUnescaped article.content
}
}
}
}
footer {
p("© ${new Date().year + 1900} My Website")
}
}
}
''')
def pageData = [
pageTitle: 'My Blog',
menuItems: [
[url: '/', text: 'Home'],
[url: '/about', text: 'About'],
[url: '/contact', text: 'Contact']
],
articles: [
[
title: 'First Post',
date: '2023-01-15',
content: '<p>This is my first blog post!</p>'
],
[
title: 'Second Post',
date: '2023-01-20',
content: '<p>Here is another post with <strong>bold text</strong>.</p>'
]
]
]
def html = template.make(pageData)
println html.toString()
// Email template with type checking
def emailTemplate = engine.createTypeCheckedTemplate('''
html {
body {
h1("Welcome ${user.name}!")
p("Thank you for signing up for our service.")
div(style: 'border: 1px solid #ccc; padding: 20px; margin: 20px 0;') {
h3("Account Details:")
ul {
li("Username: ${user.username}")
li("Email: ${user.email}")
li("Member since: ${user.joinDate}")
}
}
p {
yield "Click "
a(href: "${baseUrl}/activate?token=${user.activationToken}", "here")
yield " to activate your account."
}
hr()
p(style: 'color: #666; font-size: 12px;') {
yield "If you have any questions, contact us at "
a(href: "mailto:support@example.com", "support@example.com")
}
}
}
''')Optimize template performance with caching and compilation strategies.
Usage Examples:
import groovy.text.SimpleTemplateEngine
import java.util.concurrent.ConcurrentHashMap
class CachedTemplateEngine {
private final SimpleTemplateEngine engine = new SimpleTemplateEngine()
private final Map<String, Template> templateCache = new ConcurrentHashMap<>()
Template getTemplate(String name, String templateText) {
return templateCache.computeIfAbsent(name) { key ->
engine.createTemplate(templateText)
}
}
Template getTemplate(String name, File templateFile) {
def lastModified = templateFile.lastModified()
def cacheKey = "${name}_${lastModified}"
return templateCache.computeIfAbsent(cacheKey) { key ->
// Remove old versions
templateCache.entrySet().removeIf { entry ->
entry.key.startsWith("${name}_") && entry.key != cacheKey
}
engine.createTemplate(templateFile)
}
}
void clearCache() {
templateCache.clear()
}
}
// Usage
def cachedEngine = new CachedTemplateEngine()
// Templates are compiled once and cached
def welcome = cachedEngine.getTemplate('welcome', 'Hello $name!')
def result1 = welcome.make([name: 'Alice'])
def result2 = welcome.make([name: 'Bob']) // Uses cached template
// File-based templates with modification checking
def fileTemplate = cachedEngine.getTemplate('invoice', new File('invoice.template'))/**
* Base class for all template engines
*/
abstract class TemplateEngine {
/**
* Create template from string content
*/
abstract Template createTemplate(String templateText) throws CompilationFailedException;
/**
* Create template from Reader
*/
abstract Template createTemplate(Reader reader) throws CompilationFailedException;
}
/**
* Compiled template ready for execution
*/
interface Template {
/**
* Execute template with binding data
*/
Writable make(Map binding);
/**
* Execute template with empty binding
*/
Writable make();
}
/**
* Template output that can be written to various destinations
*/
interface Writable {
/**
* Write content to Writer
*/
Writer writeTo(Writer out) throws IOException;
/**
* Get content as String
*/
String toString();
}/**
* Configuration options for markup template engine
*/
class TemplateConfiguration {
/**
* Enable/disable template caching
*/
boolean isCacheTemplates();
void setCacheTemplates(boolean cache);
/**
* Enable/disable automatic indentation
*/
boolean isAutoIndent();
void setAutoIndent(boolean autoIndent);
/**
* Enable/disable automatic newlines
*/
boolean isAutoNewLine();
void setAutoNewLine(boolean autoNewLine);
/**
* Get/set locale for templates
*/
Locale getLocale();
void setLocale(Locale locale);
/**
* Get/set base template class
*/
Class<?> getBaseTemplateClass();
void setBaseTemplateClass(Class<?> baseClass);
}
/**
* Exception thrown when template compilation fails
*/
class CompilationFailedException extends Exception {
CompilationFailedException(String message);
CompilationFailedException(String message, Throwable cause);
}Install with Tessl CLI
npx tessl i tessl/maven-org-codehaus-groovy--groovy