or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

gstring-templates.mdindex.mdmarkup-templates.mdsimple-templates.mdstreaming-templates.mdxml-templates.md

gstring-templates.mddocs/

0

# GString Templates

1

2

The GStringTemplateEngine provides template processing using GString closures stored as writable templates. It's designed for streaming scenarios and offers efficient template storage and execution through closure-based architecture.

3

4

## Capabilities

5

6

### GString Template Engine Class

7

8

Creates templates using GString closures with efficient storage and streaming support.

9

10

```java { .api }

11

/**

12

* Template engine using GString and JSP-style syntax, storing templates as writable closures.

13

* Optimized for streaming scenarios and efficient template reuse.

14

*/

15

public class GStringTemplateEngine extends TemplateEngine {

16

/**

17

* Creates a new GStringTemplateEngine with default class loader

18

*/

19

public GStringTemplateEngine();

20

21

/**

22

* Creates a new GStringTemplateEngine with custom class loader

23

* @param parentLoader ClassLoader used for template compilation

24

*/

25

public GStringTemplateEngine(ClassLoader parentLoader);

26

}

27

```

28

29

**Usage Examples:**

30

31

```java

32

import groovy.text.GStringTemplateEngine;

33

import groovy.text.Template;

34

import java.util.Map;

35

import java.util.HashMap;

36

37

// Create GString template engine

38

GStringTemplateEngine engine = new GStringTemplateEngine();

39

40

// Template with mixed JSP and GString syntax

41

String templateText = """

42

Dear <%= firstname %> $lastname,

43

44

We <% if (accepted) print 'are pleased' else print 'regret' %>

45

to inform you that your paper entitled

46

'$title' was ${ accepted ? 'accepted' : 'rejected' }.

47

48

The conference committee.

49

""";

50

51

Template template = engine.createTemplate(templateText);

52

53

Map<String, Object> binding = new HashMap<>();

54

binding.put("firstname", "Grace");

55

binding.put("lastname", "Hopper");

56

binding.put("accepted", true);

57

binding.put("title", "Groovy for COBOL programmers");

58

59

String result = template.make(binding).toString();

60

```

61

62

### Template Syntax Support

63

64

GStringTemplateEngine supports the same template syntax as SimpleTemplateEngine and StreamingTemplateEngine:

65

66

#### JSP-Style Scriptlets

67

Use `<% %>` blocks for executing Groovy code:

68

69

```java

70

String template = """

71

<%

72

def items = ['apple', 'banana', 'orange']

73

for (item in items) {

74

print "- " + item + "\\n"

75

}

76

%>

77

""";

78

```

79

80

#### JSP-Style Expressions

81

Use `<%= %>` blocks for outputting expression results:

82

83

```java

84

String template = """

85

Today is <%= new Date().format('yyyy-MM-dd') %>

86

Temperature: <%= temperature %>°C

87

""";

88

```

89

90

#### GString Expressions

91

Use `${expression}` or `$variable` for variable substitution:

92

93

```java

94

String template = """

95

Welcome ${user.name}!

96

You have ${messages.size()} new messages.

97

Your account balance is $balance.

98

""";

99

```

100

101

### Closure-Based Architecture

102

103

GStringTemplateEngine internally converts templates to closure-based representations:

104

105

```java

106

// The engine converts template text like this:

107

String template = "Hello ${name}! Today is <%= new Date() %>";

108

109

// Into closure-based code similar to:

110

// { out -> out << "Hello ${name}! Today is "; out << new Date(); }

111

```

112

113

This architecture provides several benefits:

114

- **Efficient reuse**: Templates are compiled once and can be applied multiple times

115

- **Memory efficiency**: Closure-based storage reduces memory overhead

116

- **Thread safety**: Each template execution gets its own closure instance

117

118

### Streaming Support

119

120

GStringTemplateEngine is particularly well-suited for streaming scenarios:

121

122

```java

123

import groovy.text.GStringTemplateEngine;

124

import groovy.text.Template;

125

import groovy.lang.Writable;

126

import java.io.FileWriter;

127

import java.io.Writer;

128

129

GStringTemplateEngine engine = new GStringTemplateEngine();

130

131

String reportTemplate = """

132

# User Report

133

134

<% users.each { user -> %>

135

## User: ${user.name}

136

- Email: ${user.email}

137

- Status: ${user.active ? 'Active' : 'Inactive'}

138

- Last Login: <%= user.lastLogin?.format('yyyy-MM-dd') ?: 'Never' %>

139

140

<% } %>

141

142

Total users: ${users.size()}

143

""";

144

145

Template template = engine.createTemplate(reportTemplate);

146

147

// Create large dataset

148

List<Map<String, Object>> users = new ArrayList<>();

149

for (int i = 1; i <= 10000; i++) {

150

Map<String, Object> user = new HashMap<>();

151

user.put("name", "User " + i);

152

user.put("email", "user" + i + "@example.com");

153

user.put("active", i % 3 == 0);

154

users.add(user);

155

}

156

157

Map<String, Object> binding = new HashMap<>();

158

binding.put("users", users);

159

160

// Stream directly to file

161

Writable result = template.make(binding);

162

try (Writer writer = new FileWriter("report.txt")) {

163

result.writeTo(writer);

164

}

165

```

166

167

### Template Reuse and Performance

168

169

GStringTemplateEngine excels at template reuse scenarios:

170

171

```java

172

GStringTemplateEngine engine = new GStringTemplateEngine();

173

174

// Compile template once

175

String emailTemplate = """

176

Subject: Welcome ${name}!

177

178

Dear ${name},

179

180

Thank you for joining ${company}. Your account has been created with username: ${username}

181

182

<% if (isPremium) { %>

183

As a premium member, you have access to:

184

- Priority support

185

- Advanced features

186

- Extended storage

187

<% } %>

188

189

Welcome aboard!

190

The ${company} Team

191

""";

192

193

Template template = engine.createTemplate(emailTemplate);

194

195

// Reuse template for multiple users

196

List<Map<String, Object>> newUsers = getNewUsers(); // Assume this method exists

197

198

for (Map<String, Object> user : newUsers) {

199

Map<String, Object> binding = new HashMap<>();

200

binding.put("name", user.get("name"));

201

binding.put("username", user.get("username"));

202

binding.put("company", "Acme Corp");

203

binding.put("isPremium", user.get("accountType").equals("premium"));

204

205

String email = template.make(binding).toString();

206

sendEmail(user.get("email"), email); // Assume this method exists

207

}

208

```

209

210

### Web Integration

211

212

GStringTemplateEngine can be used with servlet containers:

213

214

```xml

215

<servlet>

216

<servlet-name>GStringTemplate</servlet-name>

217

<servlet-class>groovy.servlet.TemplateServlet</servlet-class>

218

<init-param>

219

<param-name>template.engine</param-name>

220

<param-value>groovy.text.GStringTemplateEngine</param-value>

221

</init-param>

222

</servlet>

223

```

224

225

### Binding Resolution Strategy

226

227

GStringTemplateEngine uses `DELEGATE_FIRST` resolution strategy to ensure proper variable binding:

228

229

```java

230

// Template variables are resolved in this order:

231

// 1. Template binding (Map passed to make())

232

// 2. Template closure delegate

233

// 3. Template closure owner

234

235

String template = """

236

Value from binding: $bindingVar

237

<%

238

// This variable will be stored in the binding, not the script

239

localVar = "This goes to binding"

240

%>

241

Local variable: $localVar

242

""";

243

```

244

245

### Error Handling

246

247

GStringTemplateEngine provides standard Groovy error handling:

248

249

```java

250

try {

251

GStringTemplateEngine engine = new GStringTemplateEngine();

252

Template template = engine.createTemplate(templateText);

253

String result = template.make(binding).toString();

254

} catch (CompilationFailedException e) {

255

// Template compilation failed - syntax error in template

256

System.err.println("Compilation error: " + e.getMessage());

257

} catch (IOException e) {

258

// I/O error when reading template source

259

System.err.println("I/O error: " + e.getMessage());

260

} catch (ClassNotFoundException e) {

261

// Missing class dependencies

262

System.err.println("Class not found: " + e.getMessage());

263

} catch (Exception e) {

264

// Runtime errors during template execution

265

System.err.println("Runtime error: " + e.getMessage());

266

}

267

```

268

269

### Best Practices

270

271

1. **Template Reuse**: Compile templates once and reuse with different bindings

272

2. **Large Data**: Use streaming with `writeTo()` for large outputs

273

3. **Variable Scope**: Be aware that variables assigned in scriptlets go to the binding

274

4. **Thread Safety**: Create separate template instances for concurrent use

275

5. **Memory Management**: Let templates be garbage collected when no longer needed