Apache Groovy - A powerful multi-faceted programming language for the JVM platform with comprehensive module support
—
Groovy provides multiple template engines for generating dynamic content with variable substitution, embedded code execution, and flexible output formatting.
Basic template engine with GString-style variable substitution and embedded code support.
class SimpleTemplateEngine extends TemplateEngine {
SimpleTemplateEngine()
SimpleTemplateEngine(ClassLoader parentLoader)
Template createTemplate(String templateText)
Template createTemplate(File templateFile)
Template createTemplate(URL templateURL)
Template createTemplate(Reader reader)
}Usage examples:
import groovy.text.SimpleTemplateEngine
def engine = new SimpleTemplateEngine()
// Simple variable substitution
def template = engine.createTemplate('Hello $name, you are $age years old.')
def binding = [name: 'John', age: 30]
def result = template.make(binding)
println result.toString() // "Hello John, you are 30 years old."
// Embedded expressions
def template2 = engine.createTemplate('''
Dear $name,
Your account balance is $${balance}.
${balance > 1000 ? 'You qualify for premium services.' : 'Consider upgrading your account.'}
Best regards,
The System
''')
def result2 = template2.make([name: 'Alice', balance: 1500])
println result2.toString()
// Embedded code blocks
def template3 = engine.createTemplate('''
<html>
<body>
<h1>User List</h1>
<ul>
<% users.each { user -> %>
<li>${user.name} (${user.email})</li>
<% } %>
</ul>
</body>
</html>
''')
def users = [
[name: 'John', email: 'john@example.com'],
[name: 'Jane', email: 'jane@example.com']
]
def html = template3.make([users: users])
println html.toString()Template engine that treats the entire template as a GString for more flexible processing.
class GStringTemplateEngine extends TemplateEngine {
GStringTemplateEngine()
GStringTemplateEngine(ClassLoader parentLoader)
Template createTemplate(String templateText)
Template createTemplate(File templateFile)
Template createTemplate(URL templateURL)
Template createTemplate(Reader reader)
}Usage example:
import groovy.text.GStringTemplateEngine
def engine = new GStringTemplateEngine()
def template = engine.createTemplate('''
Report for $title
Generated on ${new Date().format('yyyy-MM-dd')}
Summary:
- Total items: ${items.size()}
- Average value: ${items.sum { it.value } / items.size()}
- Maximum value: ${items.max { it.value }.value}
Details:
${items.collect { "- ${it.name}: ${it.value}" }.join('\\n')}
''')
def data = [
title: 'Monthly Sales',
items: [
[name: 'Product A', value: 100],
[name: 'Product B', value: 250],
[name: 'Product C', value: 175]
]
]
def report = template.make(data)
println report.toString()Template engine specifically designed for XML generation with proper escaping.
class XmlTemplateEngine extends TemplateEngine {
XmlTemplateEngine()
XmlTemplateEngine(ClassLoader parentLoader)
Template createTemplate(String templateText)
Template createTemplate(File templateFile)
Template createTemplate(URL templateURL)
Template createTemplate(Reader reader)
}Usage example:
import groovy.text.XmlTemplateEngine
def engine = new XmlTemplateEngine()
def template = engine.createTemplate('''
<catalog>
<title>$title</title>
<books>
<% books.each { book -> %>
<book id="$book.id">
<title>$book.title</title>
<author>$book.author</author>
<price currency="USD">$book.price</price>
<description>$book.description</description>
</book>
<% } %>
</books>
</catalog>
''')
def catalog = [
title: 'Programming Books',
books: [
[
id: 1,
title: 'Groovy in Action',
author: 'Dierk König',
price: 49.99,
description: 'Comprehensive guide to Groovy & dynamic languages'
],
[
id: 2,
title: 'Programming Groovy 2',
author: 'Venkat Subramaniam',
price: 44.99,
description: 'Practical guide with examples & best practices'
]
]
]
def xml = template.make(catalog)
println xml.toString()Memory-efficient template engine for generating large output using streaming.
class StreamingTemplateEngine extends TemplateEngine {
StreamingTemplateEngine()
StreamingTemplateEngine(String staticText, String expressionText)
StreamingTemplateEngine(ClassLoader parentLoader)
Template createTemplate(String templateText)
Template createTemplate(File templateFile)
Template createTemplate(URL templateURL)
Template createTemplate(Reader reader)
}Usage example:
import groovy.text.StreamingTemplateEngine
def engine = new StreamingTemplateEngine()
def template = engine.createTemplate('''
<html>
<head><title>Large Report</title></head>
<body>
<h1>Data Report</h1>
<table>
<tr><th>ID</th><th>Name</th><th>Value</th></tr>
<% data.each { item -> %>
<tr><td>$item.id</td><td>$item.name</td><td>$item.value</td></tr>
<% } %>
</table>
</body>
</html>
''')
// Generate large dataset
def largeData = (1..10000).collect { i ->
[id: i, name: "Item $i", value: Math.random() * 1000]
}
// Stream output to file
new File('report.html').withWriter { writer ->
def result = template.make([data: largeData])
result.writeTo(writer)
}Base interface for all template implementations.
interface Template {
Writable make()
Writable make(Map binding)
}Interface for objects that can write themselves to a Writer.
interface Writable {
Writer writeTo(Writer out)
}Usage example:
def template = engine.createTemplate('Hello $name!')
def writable = template.make([name: 'World'])
// Write to different outputs
println writable.toString() // To string
writable.writeTo(System.out) // To console
new File('output.txt').withWriter { writer ->
writable.writeTo(writer) // To file
}import groovy.text.SimpleTemplateEngine
// Custom template with different delimiters
def engine = new SimpleTemplateEngine()
def customTemplate = '''
Report: <%=title%>
Date: <%=new Date().format('yyyy-MM-dd')%>
<% items.each { item -> %>
Item: <%=item.name%> - <%=item.value%>
<% } %>
'''
// Note: Use StreamingTemplateEngine for custom delimiters
def streamingEngine = new StreamingTemplateEngine('<%', '%>')
def template = streamingEngine.createTemplate(customTemplate)
def result = template.make([
title: 'Custom Report',
items: [[name: 'A', value: 100], [name: 'B', value: 200]]
])
println result.toString()import groovy.text.SimpleTemplateEngine
class CachedTemplateEngine {
private final SimpleTemplateEngine engine = new SimpleTemplateEngine()
private final Map<String, Template> cache = [:]
Template getTemplate(String templateText) {
return cache.computeIfAbsent(templateText) { text ->
engine.createTemplate(text)
}
}
String process(String templateText, Map binding) {
return getTemplate(templateText).make(binding).toString()
}
}
def cachedEngine = new CachedTemplateEngine()
// Templates are cached for reuse
def template1 = 'Hello $name, today is ${new Date().format("yyyy-MM-dd")}'
println cachedEngine.process(template1, [name: 'Alice'])
println cachedEngine.process(template1, [name: 'Bob']) // Uses cached templateimport groovy.text.SimpleTemplateEngine
// Base template
def baseTemplate = '''
<html>
<head>
<title>$title</title>
<style>
body { font-family: Arial, sans-serif; }
.content { margin: 20px; }
</style>
</head>
<body>
<div class="content">
$content
</div>
</body>
</html>
'''
// Content template
def contentTemplate = '''
<h1>$pageTitle</h1>
<p>$message</p>
<ul>
<% items.each { item -> %>
<li>$item</li>
<% } %>
</ul>
'''
def engine = new SimpleTemplateEngine()
// Generate content first
def content = engine.createTemplate(contentTemplate).make([
pageTitle: 'Welcome',
message: 'This is the main content.',
items: ['Feature 1', 'Feature 2', 'Feature 3']
]).toString()
// Apply to base template
def finalPage = engine.createTemplate(baseTemplate).make([
title: 'My Website',
content: content
]).toString()
println finalPageimport groovy.text.SimpleTemplateEngine
class TemplateManager {
private final SimpleTemplateEngine engine = new SimpleTemplateEngine()
private final Map<String, String> templates = [:]
void defineTemplate(String name, String content) {
templates[name] = content
}
String include(String templateName, Map binding = [:]) {
def templateContent = templates[templateName]
if (!templateContent) {
throw new IllegalArgumentException("Template '$templateName' not found")
}
return engine.createTemplate(templateContent).make(binding).toString()
}
String process(String templateContent, Map binding) {
// Add include function to binding
binding.include = this.&include
return engine.createTemplate(templateContent).make(binding).toString()
}
}
def manager = new TemplateManager()
// Define reusable templates
manager.defineTemplate('header', '''
<header>
<h1>$title</h1>
<nav>
<a href="/home">Home</a>
<a href="/about">About</a>
</nav>
</header>
''')
manager.defineTemplate('footer', '''
<footer>
<p>© $year $company. All rights reserved.</p>
</footer>
''')
// Main template using includes
def mainTemplate = '''
<html>
<body>
${include('header', [title: pageTitle])}
<main>
<h2>$contentTitle</h2>
<p>$content</p>
</main>
${include('footer', [year: year, company: company])}
</body>
</html>
'''
def result = manager.process(mainTemplate, [
pageTitle: 'My Website',
contentTitle: 'Welcome',
content: 'This is the main content of the page.',
year: 2023,
company: 'My Company'
])
println resultimport groovy.text.SimpleTemplateEngine
try {
def engine = new SimpleTemplateEngine()
// Invalid template syntax
def template = engine.createTemplate('Hello $name, <% invalid groovy code %>')
} catch (Exception e) {
println "Template compilation error: ${e.message}"
// Handle compilation errors
}try {
def engine = new SimpleTemplateEngine()
def template = engine.createTemplate('Hello $name.toUpperCase()!')
// This will fail if name is null
def result = template.make([name: null])
println result.toString()
} catch (Exception e) {
println "Template execution error: ${e.message}"
// Provide default values or error handling
def safeTemplate = engine.createTemplate('Hello ${name?.toUpperCase() ?: "Guest"}!')
def safeResult = safeTemplate.make([name: null])
println safeResult.toString() // "Hello Guest!"
}import groovy.text.SimpleTemplateEngine
import groovy.servlet.TemplateServlet
// Example servlet integration
class MyTemplateServlet extends TemplateServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) {
def engine = new SimpleTemplateEngine()
def template = engine.createTemplate(getTemplate('user-profile'))
def user = getUserFromSession(request)
def binding = [
user: user,
currentDate: new Date(),
contextPath: request.contextPath
]
response.contentType = 'text/html'
template.make(binding).writeTo(response.writer)
}
}import groovy.text.SimpleTemplateEngine
class FileTemplateSystem {
private final File templateDir
private final SimpleTemplateEngine engine = new SimpleTemplateEngine()
FileTemplateSystem(String templateDirectory) {
this.templateDir = new File(templateDirectory)
}
String render(String templateName, Map binding = [:]) {
def templateFile = new File(templateDir, "${templateName}.gtpl")
if (!templateFile.exists()) {
throw new FileNotFoundException("Template not found: $templateName")
}
def template = engine.createTemplate(templateFile)
return template.make(binding).toString()
}
void renderToFile(String templateName, String outputPath, Map binding = [:]) {
def content = render(templateName, binding)
new File(outputPath).text = content
}
}
// Usage
def templateSystem = new FileTemplateSystem('src/main/templates')
def emailContent = templateSystem.render('welcome-email', [
userName: 'John Doe',
activationLink: 'https://example.com/activate/123'
])
templateSystem.renderToFile('report', 'output/monthly-report.html', [
reportDate: new Date(),
data: getReportData()
])Install with Tessl CLI
npx tessl i tessl/maven-org-codehaus-groovy--groovy-all