or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

caching.mdindex.mdmail.mdscheduling.mdtemplates.md

templates.mddocs/

0

# FreeMarker Templates

1

2

Spring Context Support provides comprehensive FreeMarker template engine integration for server-side rendering. It offers factory beans for configuration, utilities for template processing, and Spring Resource-based template loading for both web and non-web contexts.

3

4

## Capabilities

5

6

### FreeMarker Configuration Factory

7

8

Factory for creating and configuring FreeMarker Configuration instances with Spring integration.

9

10

```java { .api }

11

/**

12

* Factory for creating FreeMarker Configuration instances with Spring integration

13

*/

14

public class FreeMarkerConfigurationFactory {

15

16

/**

17

* Set the location of the FreeMarker config file

18

* @param resource the config file resource

19

*/

20

public void setConfigLocation(Resource resource);

21

22

/**

23

* Set FreeMarker settings as Properties

24

* @param settings the FreeMarker settings

25

*/

26

public void setFreemarkerSettings(Properties settings);

27

28

/**

29

* Set FreeMarker variables (objects available in all templates)

30

* @param variables map of variable names to objects

31

*/

32

public void setFreemarkerVariables(Map<String, Object> variables);

33

34

/**

35

* Set the default encoding for templates

36

* @param defaultEncoding the default encoding (e.g., "UTF-8")

37

*/

38

public void setDefaultEncoding(String defaultEncoding);

39

40

/**

41

* Set the default charset for templates

42

* @param defaultCharset the default charset

43

*/

44

public void setDefaultCharset(Charset defaultCharset);

45

46

/**

47

* Set template loaders that will be used before default loaders

48

* @param preTemplateLoaders template loaders to register first

49

*/

50

public void setPreTemplateLoaders(TemplateLoader... preTemplateLoaders);

51

52

/**

53

* Set template loaders that will be used after default loaders

54

* @param postTemplateLoaders template loaders to register last

55

*/

56

public void setPostTemplateLoaders(TemplateLoader... postTemplateLoaders);

57

58

/**

59

* Set the template loader path (single path)

60

* @param templateLoaderPath the template loader path

61

*/

62

public void setTemplateLoaderPath(String templateLoaderPath);

63

64

/**

65

* Set multiple template loader paths

66

* @param templateLoaderPaths array of template loader paths

67

*/

68

public void setTemplateLoaderPaths(String... templateLoaderPaths);

69

70

/**

71

* Set the ResourceLoader for template loading

72

* @param resourceLoader the ResourceLoader to use

73

*/

74

public void setResourceLoader(ResourceLoader resourceLoader);

75

76

/**

77

* Set whether to prefer file system access for template loading

78

* @param preferFileSystemAccess whether to prefer file system access

79

*/

80

public void setPreferFileSystemAccess(boolean preferFileSystemAccess);

81

82

/**

83

* Create the FreeMarker Configuration instance

84

* @return the configured Configuration

85

* @throws IOException if configuration fails

86

* @throws TemplateException if template configuration fails

87

*/

88

public Configuration createConfiguration() throws IOException, TemplateException;

89

90

/**

91

* Get the ResourceLoader (available after ApplicationContext injection)

92

* @return the ResourceLoader

93

*/

94

protected ResourceLoader getResourceLoader();

95

}

96

```

97

98

**Usage Examples:**

99

100

```java

101

@Configuration

102

public class FreeMarkerConfig {

103

104

@Bean

105

public FreeMarkerConfigurationFactory freeMarkerConfigurationFactory() {

106

FreeMarkerConfigurationFactory factory = new FreeMarkerConfigurationFactory();

107

factory.setTemplateLoaderPaths(

108

"classpath:/templates/",

109

"file:/opt/app/templates/"

110

);

111

factory.setDefaultEncoding("UTF-8");

112

113

Properties settings = new Properties();

114

settings.setProperty("number_format", "0.##");

115

settings.setProperty("date_format", "yyyy-MM-dd");

116

settings.setProperty("time_format", "HH:mm:ss");

117

settings.setProperty("datetime_format", "yyyy-MM-dd HH:mm:ss");

118

factory.setFreemarkerSettings(settings);

119

120

// Global variables available in all templates

121

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

122

variables.put("app", applicationProperties);

123

variables.put("utils", templateUtils);

124

factory.setFreemarkerVariables(variables);

125

126

return factory;

127

}

128

129

@Bean

130

public Configuration freeMarkerConfiguration() throws Exception {

131

return freeMarkerConfigurationFactory().createConfiguration();

132

}

133

}

134

```

135

136

### FreeMarker Configuration Factory Bean

137

138

FactoryBean wrapper around FreeMarkerConfigurationFactory for easier Spring integration.

139

140

```java { .api }

141

/**

142

* FactoryBean wrapper around FreeMarkerConfigurationFactory

143

*/

144

public class FreeMarkerConfigurationFactoryBean extends FreeMarkerConfigurationFactory

145

implements FactoryBean<Configuration>, InitializingBean, ResourceLoaderAware {

146

147

/**

148

* Get the FreeMarker Configuration instance

149

* @return the Configuration instance

150

* @throws Exception if creation fails

151

*/

152

@Override

153

public Configuration getObject() throws Exception;

154

155

/**

156

* Get the object type

157

* @return Configuration.class

158

*/

159

@Override

160

public Class<Configuration> getObjectType();

161

162

/**

163

* Check if this factory returns singletons

164

* @return true (singleton)

165

*/

166

@Override

167

public boolean isSingleton();

168

169

/**

170

* Initialize the factory bean

171

* @throws IOException if initialization fails

172

* @throws TemplateException if template configuration fails

173

*/

174

@Override

175

public void afterPropertiesSet() throws IOException, TemplateException;

176

177

/**

178

* Set the ResourceLoader for template loading

179

* @param resourceLoader the ResourceLoader

180

*/

181

@Override

182

public void setResourceLoader(ResourceLoader resourceLoader);

183

}

184

```

185

186

**Usage Examples:**

187

188

```java

189

@Configuration

190

public class FreeMarkerFactoryBeanConfig {

191

192

@Bean

193

public FreeMarkerConfigurationFactoryBean freeMarkerConfigurationFactoryBean() {

194

FreeMarkerConfigurationFactoryBean factoryBean = new FreeMarkerConfigurationFactoryBean();

195

factoryBean.setTemplateLoaderPath("classpath:/templates/");

196

factoryBean.setDefaultEncoding("UTF-8");

197

198

Properties settings = new Properties();

199

settings.setProperty("template_update_delay", "0"); // Development setting

200

settings.setProperty("default_encoding", "UTF-8");

201

settings.setProperty("output_encoding", "UTF-8");

202

settings.setProperty("locale", "en_US");

203

factoryBean.setFreemarkerSettings(settings);

204

205

return factoryBean;

206

}

207

}

208

```

209

210

### Template Processing Utilities

211

212

Utility methods for processing FreeMarker templates in various contexts.

213

214

```java { .api }

215

/**

216

* Utility methods for processing FreeMarker templates

217

*/

218

public abstract class FreeMarkerTemplateUtils {

219

220

/**

221

* Process a FreeMarker template into a String

222

* @param template the FreeMarker Template

223

* @param model the template model (data)

224

* @return the processed template as String

225

* @throws IOException if template processing fails

226

* @throws TemplateException if template has errors

227

*/

228

public static String processTemplateIntoString(Template template, Object model)

229

throws IOException, TemplateException;

230

}

231

```

232

233

**Usage Examples:**

234

235

```java

236

@Service

237

public class ReportService {

238

239

@Autowired

240

private Configuration freeMarkerConfiguration;

241

242

public String generateReport(String templateName, Map<String, Object> data) {

243

try {

244

Template template = freeMarkerConfiguration.getTemplate(templateName + ".ftl");

245

return FreeMarkerTemplateUtils.processTemplateIntoString(template, data);

246

} catch (IOException | TemplateException e) {

247

throw new RuntimeException("Failed to generate report", e);

248

}

249

}

250

251

public String generateLocalizedReport(String templateName, Map<String, Object> data, Locale locale) {

252

try {

253

Template template = freeMarkerConfiguration.getTemplate(templateName + ".ftl", locale);

254

return FreeMarkerTemplateUtils.processTemplateIntoString(template, data);

255

} catch (IOException | TemplateException e) {

256

throw new RuntimeException("Failed to generate localized report", e);

257

}

258

}

259

}

260

261

@RestController

262

public class TemplateController {

263

264

@Autowired

265

private ReportService reportService;

266

267

@GetMapping("/reports/{type}")

268

public ResponseEntity<String> generateReport(@PathVariable String type) {

269

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

270

data.put("reportDate", new Date());

271

data.put("title", "Monthly Report");

272

data.put("items", getReportItems());

273

274

String html = reportService.generateReport(type, data);

275

276

return ResponseEntity.ok()

277

.contentType(MediaType.TEXT_HTML)

278

.body(html);

279

}

280

}

281

```

282

283

### Spring Template Loader

284

285

FreeMarker TemplateLoader implementation that loads templates from Spring Resource locations.

286

287

```java { .api }

288

/**

289

* FreeMarker TemplateLoader that loads templates from Spring Resource locations

290

*/

291

public class SpringTemplateLoader implements TemplateLoader {

292

293

/**

294

* Create a SpringTemplateLoader with a ResourceLoader and template path

295

* @param resourceLoader the ResourceLoader to use

296

* @param templateLoaderPath the base path for templates

297

*/

298

public SpringTemplateLoader(ResourceLoader resourceLoader, String templateLoaderPath);

299

300

/**

301

* Find a template source

302

* @param name the template name

303

* @return the template source object

304

* @throws IOException if template loading fails

305

*/

306

@Override

307

public Object findTemplateSource(String name) throws IOException;

308

309

/**

310

* Get the last modified time of a template

311

* @param templateSource the template source

312

* @return the last modified time

313

*/

314

@Override

315

public long getLastModified(Object templateSource);

316

317

/**

318

* Get a Reader for the template content

319

* @param templateSource the template source

320

* @param encoding the character encoding

321

* @return a Reader for the template

322

* @throws IOException if reading fails

323

*/

324

@Override

325

public Reader getReader(Object templateSource, String encoding) throws IOException;

326

327

/**

328

* Close a template source

329

* @param templateSource the template source to close

330

* @throws IOException if closing fails

331

*/

332

@Override

333

public void closeTemplateSource(Object templateSource) throws IOException;

334

}

335

```

336

337

### Advanced Configuration Examples

338

339

Complete configuration examples for different use cases.

340

341

```java

342

@Configuration

343

public class AdvancedFreeMarkerConfig {

344

345

/**

346

* Configuration for web applications with multiple template locations

347

*/

348

@Bean

349

@Profile("web")

350

public FreeMarkerConfigurationFactoryBean webFreeMarkerConfig() {

351

FreeMarkerConfigurationFactoryBean factoryBean = new FreeMarkerConfigurationFactoryBean();

352

353

// Multiple template locations

354

factoryBean.setTemplateLoaderPaths(

355

"classpath:/templates/", // Built-in templates

356

"classpath:/templates/mail/", // Email templates

357

"file:/opt/app/custom-templates/" // Custom templates

358

);

359

360

factoryBean.setDefaultEncoding("UTF-8");

361

factoryBean.setPreferFileSystemAccess(false); // For WAR deployment

362

363

Properties settings = new Properties();

364

// Development settings

365

settings.setProperty("template_update_delay", "0");

366

settings.setProperty("template_exception_handler", "html_debug");

367

// Production settings would use:

368

// settings.setProperty("template_update_delay", "60000");

369

// settings.setProperty("template_exception_handler", "ignore");

370

371

settings.setProperty("default_encoding", "UTF-8");

372

settings.setProperty("output_encoding", "UTF-8");

373

settings.setProperty("auto_flush", "true");

374

settings.setProperty("url_escaping_charset", "UTF-8");

375

376

factoryBean.setFreemarkerSettings(settings);

377

378

// Global variables

379

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

380

variables.put("contextPath", "${request.contextPath}");

381

variables.put("springMacroRequestContext", new RequestContextHashModel());

382

factoryBean.setFreemarkerVariables(variables);

383

384

return factoryBean;

385

}

386

387

/**

388

* Configuration for standalone/batch applications

389

*/

390

@Bean

391

@Profile("batch")

392

public FreeMarkerConfigurationFactoryBean batchFreeMarkerConfig() {

393

FreeMarkerConfigurationFactoryBean factoryBean = new FreeMarkerConfigurationFactoryBean();

394

395

factoryBean.setTemplateLoaderPaths(

396

"classpath:/batch-templates/",

397

"file:/data/templates/"

398

);

399

400

factoryBean.setDefaultEncoding("UTF-8");

401

factoryBean.setPreferFileSystemAccess(true); // Better performance for file system

402

403

Properties settings = new Properties();

404

settings.setProperty("template_update_delay", "300000"); // 5 minutes

405

settings.setProperty("template_exception_handler", "rethrow");

406

settings.setProperty("arithmetic_engine", "bigdecimal");

407

settings.setProperty("number_format", "0.####");

408

settings.setProperty("boolean_format", "yes,no");

409

410

factoryBean.setFreemarkerSettings(settings);

411

412

return factoryBean;

413

}

414

415

/**

416

* Service for template-based document generation

417

*/

418

@Service

419

public static class DocumentGenerationService {

420

421

@Autowired

422

private Configuration freeMarkerConfiguration;

423

424

public void generateDocument(String templateName, Map<String, Object> data, OutputStream output)

425

throws IOException, TemplateException {

426

427

Template template = freeMarkerConfiguration.getTemplate(templateName);

428

429

try (Writer writer = new OutputStreamWriter(output, StandardCharsets.UTF_8)) {

430

template.process(data, writer);

431

writer.flush();

432

}

433

}

434

435

public void generatePdfReport(String templateName, Map<String, Object> data, String outputPath)

436

throws IOException, TemplateException {

437

438

// Generate HTML from template

439

String html = generateHtmlFromTemplate(templateName, data);

440

441

// Convert to PDF (using a library like Flying Saucer or similar)

442

convertHtmlToPdf(html, outputPath);

443

}

444

445

private String generateHtmlFromTemplate(String templateName, Map<String, Object> data)

446

throws IOException, TemplateException {

447

448

Template template = freeMarkerConfiguration.getTemplate(templateName);

449

return FreeMarkerTemplateUtils.processTemplateIntoString(template, data);

450

}

451

}

452

}

453

```

454

455

### Template Context Integration

456

457

Integration with Spring's web context and request handling.

458

459

```java { .api }

460

/**

461

* Utility methods for integrating FreeMarker with Spring web contexts

462

*/

463

public abstract class RequestContextUtils {

464

465

/**

466

* Get the current request context for use in templates

467

* @param request the HTTP request

468

* @param response the HTTP response

469

* @param servletContext the servlet context

470

* @return RequestContext for template use

471

*/

472

public static RequestContext getRequestContext(HttpServletRequest request,

473

HttpServletResponse response, ServletContext servletContext);

474

}

475

476

/**

477

* Hash model for exposing Spring RequestContext in FreeMarker templates

478

*/

479

public class RequestContextHashModel implements TemplateHashModel {

480

481

/**

482

* Create a RequestContextHashModel for the current request

483

*/

484

public RequestContextHashModel();

485

486

/**

487

* Create a RequestContextHashModel for a specific request

488

* @param request the HTTP request

489

* @param response the HTTP response

490

*/

491

public RequestContextHashModel(HttpServletRequest request, HttpServletResponse response);

492

493

@Override

494

public TemplateModel get(String key) throws TemplateModelException;

495

496

@Override

497

public boolean isEmpty() throws TemplateModelException;

498

}

499

```

500

501

## Integration with Spring Boot

502

503

For Spring Boot applications, FreeMarker auto-configuration is available:

504

505

```yaml

506

spring:

507

freemarker:

508

template-loader-path: classpath:/templates/

509

suffix: .ftl

510

cache: true

511

charset: UTF-8

512

check-template-location: true

513

content-type: text/html

514

expose-request-attributes: false

515

expose-session-attributes: false

516

expose-spring-macro-helpers: true

517

prefer-file-system-access: true

518

settings:

519

template_update_delay: 0

520

default_encoding: UTF-8

521

output_encoding: UTF-8

522

locale: en_US

523

date_format: yyyy-MM-dd

524

time_format: HH:mm:ss

525

datetime_format: yyyy-MM-dd HH:mm:ss

526

```

527

528

The Spring Context Support FreeMarker integration provides the foundation for this auto-configuration and can be used directly in non-Boot applications or for advanced customization scenarios.