Apache Groovy is a powerful, optionally typed and dynamic language, with static-typing and static compilation capabilities, for the Java platform aimed at improving developer productivity thanks to a concise, familiar and easy to learn syntax.
—
Template engines for code generation, text processing, and dynamic content creation with support for various template formats and streaming capabilities.
Basic template engine for string substitution and simple expression evaluation.
/**
* Simple template engine for string substitution
*/
class SimpleTemplateEngine {
/** Create simple template engine */
SimpleTemplateEngine()
/** Create template from string */
Template createTemplate(String text)
/** Create template from Reader */
Template createTemplate(Reader reader)
/** Create template from File */
Template createTemplate(File file)
/** Create template from URL */
Template createTemplate(URL url)
}
/**
* Template interface for rendering with bindings
*/
interface Template {
/** Render template with binding */
Writable make(Map binding)
/** Render template with empty binding */
Writable make()
}Usage Examples:
import groovy.text.SimpleTemplateEngine
// Basic template
def engine = new SimpleTemplateEngine()
def templateText = '''
Hello $name,
Welcome to $company! Your account has been created with the following details:
- Username: $username
- Email: $email
- Department: ${department.toUpperCase()}
Best regards,
The $company Team
'''
def template = engine.createTemplate(templateText)
def binding = [
name: "Alice Johnson",
company: "Acme Corp",
username: "ajohnson",
email: "alice@acme.com",
department: "engineering"
]
def result = template.make(binding)
println result.toString()
// Template with expressions
def reportTemplate = '''
Report Generated: ${new Date()}
Total Users: $userCount
${users.collect { "- $it.name ($it.email)" }.join('\\n')}
Average Age: ${users.sum { it.age } / users.size()}
'''
def template2 = engine.createTemplate(reportTemplate)
def binding2 = [
userCount: 3,
users: [
[name: "Alice", email: "alice@example.com", age: 30],
[name: "Bob", email: "bob@example.com", age: 25],
[name: "Charlie", email: "charlie@example.com", age: 35]
]
]
println template2.make(binding2)
// Template from file
def fileTemplate = engine.createTemplate(new File("email-template.txt"))
def email = fileTemplate.make([
recipient: "customer@example.com",
subject: "Order Confirmation",
orderNumber: "12345"
])Template engine optimized for large templates with streaming output.
/**
* Streaming template engine for large templates
*/
class StreamingTemplateEngine {
/** Create streaming template engine */
StreamingTemplateEngine()
/** Create template from string */
Template createTemplate(String text)
/** Create template from Reader */
Template createTemplate(Reader reader)
/** Create template from File */
Template createTemplate(File file)
/** Create template from URL */
Template createTemplate(URL url)
}Usage Examples:
import groovy.text.StreamingTemplateEngine
// Large data template
def engine = new StreamingTemplateEngine()
def csvTemplate = '''
"Name","Email","Department","Salary"
<% users.each { user -> %>
"${user.name}","${user.email}","${user.department}","${user.salary}"
<% } %>
'''
def template = engine.createTemplate(csvTemplate)
// Stream to file for large datasets
new File("users.csv").withWriter { writer ->
def result = template.make([users: largeUserList])
writer << result
}
// Stream to HTTP response
response.contentType = "text/csv"
response.setHeader("Content-Disposition", "attachment; filename=users.csv")
response.writer << template.make([users: userList])Template engine specifically designed for XML-based templates.
/**
* Template engine for XML-based templates
*/
class XmlTemplateEngine {
/** Create XML template engine */
XmlTemplateEngine()
/** Create template from string */
Template createTemplate(String text)
/** Create template from Reader */
Template createTemplate(Reader reader)
/** Create template from File */
Template createTemplate(File file)
/** Create template from URL */
Template createTemplate(URL url)
}Usage Examples:
import groovy.text.XmlTemplateEngine
def engine = new XmlTemplateEngine()
def xmlTemplate = '''
<?xml version="1.0" encoding="UTF-8"?>
<users>
<% users.each { user -> %>
<user id="${user.id}">
<name>${user.name}</name>
<email>${user.email}</email>
<% if (user.active) { %>
<status>active</status>
<% } else { %>
<status>inactive</status>
<% } %>
<departments>
<% user.departments.each { dept -> %>
<department>${dept}</department>
<% } %>
</departments>
</user>
<% } %>
</users>
'''
def template = engine.createTemplate(xmlTemplate)
def binding = [
users: [
[id: 1, name: "Alice", email: "alice@example.com", active: true, departments: ["Engineering", "Research"]],
[id: 2, name: "Bob", email: "bob@example.com", active: false, departments: ["Sales"]],
[id: 3, name: "Charlie", email: "charlie@example.com", active: true, departments: ["Marketing", "Support"]]
]
]
def xmlResult = template.make(binding)
println xmlResult.toString()Advanced template engine for creating structured markup with type checking.
/**
* Advanced markup template engine
*/
class MarkupTemplateEngine {
/** Create with default configuration */
MarkupTemplateEngine()
/** Create with custom configuration */
MarkupTemplateEngine(TemplateConfiguration config)
/** Create template from string */
Template createTemplate(String templateText)
/** Create template from Reader */
Template createTemplate(Reader templateReader)
/** Create template from File */
Template createTemplate(File templateFile)
/** Create template from URL */
Template createTemplate(URL templateURL)
/** Create typed template */
Template createTypeCheckedTemplate(String templateText, Map<String, String> modelTypes)
}
/**
* Configuration for markup template engine
*/
class TemplateConfiguration {
/** Set whether to auto-escape XML */
TemplateConfiguration autoEscape(boolean autoEscape)
/** Set whether to auto-format output */
TemplateConfiguration autoFormat(boolean autoFormat)
/** Set whether to auto-newline */
TemplateConfiguration autoNewLine(boolean autoNewLine)
/** Set whether to auto-indent */
TemplateConfiguration autoIndent(boolean autoIndent)
/** Set base template class */
TemplateConfiguration baseTemplateClass(Class<?> baseTemplateClass)
/** Set cache templates */
TemplateConfiguration cacheTemplates(boolean cacheTemplates)
}Usage Examples:
import groovy.text.markup.*
// Create configured engine
def config = new TemplateConfiguration()
.autoEscape(true)
.autoFormat(true)
.autoIndent(true)
def engine = new MarkupTemplateEngine(config)
// HTML template
def htmlTemplate = '''
html {
head {
title(pageTitle)
meta(charset: 'UTF-8')
}
body {
h1(pageTitle)
div(class: 'content') {
p("Welcome, $userName!")
if (showUserList) {
ul {
users.each { user ->
li {
a(href: "/user/$user.id", user.name)
span(" (${user.email})")
}
}
}
}
div(class: 'footer') {
p("Generated on ${new Date()}")
}
}
}
}
'''
def template = engine.createTemplate(htmlTemplate)
def binding = [
pageTitle: "User Dashboard",
userName: "Alice",
showUserList: true,
users: [
[id: 1, name: "Bob", email: "bob@example.com"],
[id: 2, name: "Charlie", email: "charlie@example.com"]
]
]
def html = template.make(binding)
println html.toString()
// Type-checked template
def typedTemplate = engine.createTypeCheckedTemplate('''
html {
body {
h1(title)
p("User count: $users.size()")
users.each { user ->
div {
yield "Name: $user.name, Age: $user.age"
}
}
}
}
''', [
title: 'String',
users: 'List<Map<String,Object>>'
])Exception classes for template processing errors.
/**
* Exception thrown during template execution
*/
class TemplateExecutionException extends RuntimeException {
TemplateExecutionException(String message)
TemplateExecutionException(String message, Throwable cause)
/** Get line number where error occurred */
int getLineNumber()
/** Get column number where error occurred */
int getColumnNumber()
/** Get template source name */
String getSourceName()
}
/**
* Exception thrown during template parsing
*/
class TemplateParseException extends RuntimeException {
TemplateParseException(String message)
TemplateParseException(String message, Throwable cause)
/** Get line number where error occurred */
int getLineNumber()
/** Get column number where error occurred */
int getColumnNumber()
}Usage Examples:
import groovy.text.*
def engine = new SimpleTemplateEngine()
try {
// Template with syntax error
def template = engine.createTemplate('Hello ${ invalid syntax }')
def result = template.make([:])
} catch (TemplateParseException e) {
println "Parse error at line ${e.lineNumber}, column ${e.columnNumber}: ${e.message}"
}
try {
// Template with runtime error
def template = engine.createTemplate('Hello $name.nonexistentMethod()')
def result = template.make([name: "Alice"])
println result.toString()
} catch (TemplateExecutionException e) {
println "Execution error: ${e.message}"
println "At line ${e.lineNumber} in ${e.sourceName}"
}Create custom base classes for templates with additional functionality.
// Custom base template class
abstract class CustomBaseTemplate extends Template {
// Helper methods available in all templates
String formatDate(Date date) {
return date.format('yyyy-MM-dd')
}
String formatCurrency(BigDecimal amount) {
return String.format('$%.2f', amount)
}
String truncate(String text, int length) {
return text.length() > length ? text[0..length-1] + '...' : text
}
}
// Use custom base class
def config = new TemplateConfiguration()
.baseTemplateClass(CustomBaseTemplate)
def engine = new MarkupTemplateEngine(config)
def template = engine.createTemplate('''
div {
p("Order Date: ${formatDate(order.date)}")
p("Total: ${formatCurrency(order.total)}")
p("Description: ${truncate(order.description, 50)}")
}
''')// Layout template
def layoutTemplate = '''
html {
head {
title(pageTitle)
meta(charset: 'UTF-8')
if (stylesheets) {
stylesheets.each { css ->
link(rel: 'stylesheet', href: css)
}
}
}
body {
header {
h1(pageTitle)
}
main {
yieldUnescaped content
}
footer {
p("© 2023 Company Name")
}
}
}
'''
// Content template
def contentTemplate = '''
div(class: 'user-profile') {
h2("User Profile")
p("Name: $user.name")
p("Email: $user.email")
if (user.projects) {
h3("Projects")
ul {
user.projects.each { project ->
li(project.name)
}
}
}
}
'''
// Render with layout
def layoutEngine = new MarkupTemplateEngine()
def layout = layoutEngine.createTemplate(layoutTemplate)
def contentEngine = new MarkupTemplateEngine()
def content = contentEngine.createTemplate(contentTemplate)
def contentResult = content.make([user: userData])
def finalResult = layout.make([
pageTitle: "User Profile",
stylesheets: ['/css/main.css', '/css/profile.css'],
content: contentResult.toString()
])Install with Tessl CLI
npx tessl i tessl/maven-org-apache-groovy--groovy