or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

caching-loading.mdcore-processing.mdexception-handling.mdextensions.mdindex.mdobject-wrapping.mdoutput-formats.mdtemplate-models.md

caching-loading.mddocs/

0

# Template Caching and Loading

1

2

FreeMarker provides a flexible system for loading templates from various sources and caching them for optimal performance. The template loading and caching system consists of template loaders, cache storage, and lookup strategies.

3

4

## Template Loader Interface

5

6

The core interface for loading template sources:

7

8

```java { .api }

9

interface TemplateLoader {

10

Object findTemplateSource(String name) throws IOException;

11

long getLastModified(Object templateSource);

12

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

13

void closeTemplateSource(Object templateSource) throws IOException;

14

}

15

16

// Enhanced template loader with state information

17

interface StatefulTemplateLoader extends TemplateLoader {

18

void resetState();

19

}

20

```

21

22

## Built-in Template Loaders

23

24

### File Template Loader

25

26

Loads templates from the file system:

27

28

```java { .api }

29

class FileTemplateLoader implements TemplateLoader {

30

// Constructors

31

FileTemplateLoader(File baseDir) throws IOException;

32

FileTemplateLoader(File baseDir, boolean disableCanonicalization) throws IOException;

33

34

// TemplateLoader methods

35

Object findTemplateSource(String name) throws IOException;

36

long getLastModified(Object templateSource);

37

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

38

void closeTemplateSource(Object templateSource) throws IOException;

39

40

// Configuration methods

41

File getBaseDirectory();

42

boolean getEagerCanonicalization();

43

}

44

```

45

46

Usage example:

47

```java

48

// Load templates from /path/to/templates directory

49

Configuration cfg = new Configuration(Configuration.VERSION_2_3_34);

50

cfg.setTemplateLoader(new FileTemplateLoader(new File("/path/to/templates")));

51

52

// Or use the convenience method

53

cfg.setDirectoryForTemplateLoading(new File("/path/to/templates"));

54

```

55

56

### Class Template Loader

57

58

Loads templates from the classpath:

59

60

```java { .api }

61

class ClassTemplateLoader extends URLTemplateLoader {

62

// Constructors

63

ClassTemplateLoader(Class resourceLoaderClass, String basePackagePath);

64

65

// URLTemplateLoader methods

66

URL getURL(String name);

67

}

68

```

69

70

Usage example:

71

```java

72

// Load templates from classpath under /templates package

73

Configuration cfg = new Configuration(Configuration.VERSION_2_3_34);

74

cfg.setTemplateLoader(new ClassTemplateLoader(MyClass.class, "/templates"));

75

76

// Or use the convenience method

77

cfg.setClassForTemplateLoading(MyClass.class, "/templates");

78

```

79

80

### String Template Loader

81

82

Loads templates from strings stored in memory:

83

84

```java { .api }

85

class StringTemplateLoader implements TemplateLoader {

86

// Constructor

87

StringTemplateLoader();

88

89

// Template management

90

void putTemplate(String name, String templateSource);

91

void putTemplate(String name, String templateSource, long lastModified);

92

void removeTemplate(String name);

93

void closeTemplateSource(Object templateSource) throws IOException;

94

95

// TemplateLoader methods

96

Object findTemplateSource(String name) throws IOException;

97

long getLastModified(Object templateSource);

98

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

99

}

100

```

101

102

Usage example:

103

```java

104

StringTemplateLoader loader = new StringTemplateLoader();

105

loader.putTemplate("hello.ftl", "<html><body>Hello ${name}!</body></html>");

106

loader.putTemplate("email.ftl", "Dear ${recipient}, Your order #${orderNumber} is ready.");

107

108

Configuration cfg = new Configuration(Configuration.VERSION_2_3_34);

109

cfg.setTemplateLoader(loader);

110

```

111

112

### Multi Template Loader

113

114

Combines multiple template loaders:

115

116

```java { .api }

117

class MultiTemplateLoader implements StatefulTemplateLoader {

118

// Constructor

119

MultiTemplateLoader(TemplateLoader[] loaders);

120

121

// StatefulTemplateLoader methods

122

Object findTemplateSource(String name) throws IOException;

123

long getLastModified(Object templateSource);

124

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

125

void closeTemplateSource(Object templateSource) throws IOException;

126

void resetState();

127

128

// Configuration methods

129

TemplateLoader[] getTemplateLoaders();

130

}

131

```

132

133

Usage example:

134

```java

135

// Combine file system and classpath loading

136

TemplateLoader[] loaders = {

137

new FileTemplateLoader(new File("/custom/templates")),

138

new ClassTemplateLoader(MyClass.class, "/default/templates")

139

};

140

141

Configuration cfg = new Configuration(Configuration.VERSION_2_3_34);

142

cfg.setTemplateLoader(new MultiTemplateLoader(loaders));

143

```

144

145

### URL Template Loader

146

147

Abstract base class for URL-based template loading:

148

149

```java { .api }

150

abstract class URLTemplateLoader implements TemplateLoader {

151

// Abstract method to be implemented by subclasses

152

protected abstract URL getURL(String name);

153

154

// TemplateLoader implementation

155

Object findTemplateSource(String name) throws IOException;

156

long getLastModified(Object templateSource);

157

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

158

void closeTemplateSource(Object templateSource) throws IOException;

159

160

// Configuration methods

161

void setURLConnectionUsesCaches(Boolean urlConnectionUsesCaches);

162

Boolean getURLConnectionUsesCaches();

163

}

164

```

165

166

### Webapp Template Loader

167

168

Loads templates from servlet context:

169

170

```java { .api }

171

class WebappTemplateLoader implements TemplateLoader {

172

// Constructors

173

WebappTemplateLoader(ServletContext servletContext);

174

WebappTemplateLoader(ServletContext servletContext, String subdirPath);

175

176

// TemplateLoader methods

177

Object findTemplateSource(String name) throws IOException;

178

long getLastModified(Object templateSource);

179

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

180

void closeTemplateSource(Object templateSource) throws IOException;

181

}

182

```

183

184

Usage example:

185

```java

186

// In a servlet context

187

Configuration cfg = new Configuration(Configuration.VERSION_2_3_34);

188

cfg.setTemplateLoader(new WebappTemplateLoader(servletContext, "/WEB-INF/templates"));

189

```

190

191

## Cache Storage

192

193

### Cache Storage Interface

194

195

```java { .api }

196

interface CacheStorage {

197

Object get(Object key);

198

void put(Object key, Object value);

199

void remove(Object key);

200

void clear();

201

}

202

203

// Enhanced cache storage with size information

204

interface CacheStorageWithGetSize extends CacheStorage {

205

int getSize();

206

}

207

208

// Thread-safe cache storage

209

interface ConcurrentCacheStorage extends CacheStorage {

210

// Marker interface for thread-safe implementations

211

}

212

```

213

214

### Built-in Cache Storage Implementations

215

216

#### MRU Cache Storage

217

218

Most Recently Used cache with configurable size limits:

219

220

```java { .api }

221

class MruCacheStorage implements CacheStorageWithGetSize {

222

// Constructors

223

MruCacheStorage(int maxStrongSize);

224

MruCacheStorage(int maxStrongSize, int maxSoftSize);

225

226

// CacheStorage methods

227

Object get(Object key);

228

void put(Object key, Object value);

229

void remove(Object key);

230

void clear();

231

int getSize();

232

233

// Configuration methods

234

int getMaxStrongSize();

235

int getMaxSoftSize();

236

}

237

```

238

239

Usage example:

240

```java

241

// Cache up to 100 templates with strong references, 1000 with soft references

242

Configuration cfg = new Configuration(Configuration.VERSION_2_3_34);

243

cfg.setCacheStorage(new MruCacheStorage(100, 1000));

244

```

245

246

#### Soft Cache Storage

247

248

Uses soft references for automatic memory management:

249

250

```java { .api }

251

class SoftCacheStorage implements ConcurrentCacheStorage, CacheStorageWithGetSize {

252

// Constructor

253

SoftCacheStorage();

254

255

// CacheStorage methods

256

Object get(Object key);

257

void put(Object key, Object value);

258

void remove(Object key);

259

void clear();

260

int getSize();

261

}

262

```

263

264

#### Strong Cache Storage

265

266

No automatic eviction - cached items remain until explicitly removed:

267

268

```java { .api }

269

class StrongCacheStorage implements ConcurrentCacheStorage, CacheStorageWithGetSize {

270

// Constructor

271

StrongCacheStorage();

272

273

// CacheStorage methods

274

Object get(Object key);

275

void put(Object key, Object value);

276

void remove(Object key);

277

void clear();

278

int getSize();

279

}

280

```

281

282

#### Null Cache Storage

283

284

Disables caching completely:

285

286

```java { .api }

287

class NullCacheStorage implements ConcurrentCacheStorage, CacheStorageWithGetSize {

288

// Singleton instance

289

static final NullCacheStorage INSTANCE = new NullCacheStorage();

290

291

// Constructor

292

NullCacheStorage();

293

294

// CacheStorage methods (all no-ops)

295

Object get(Object key);

296

void put(Object key, Object value);

297

void remove(Object key);

298

void clear();

299

int getSize();

300

}

301

```

302

303

### Cache Configuration Examples

304

305

```java

306

// Default cache (MRU with reasonable limits)

307

Configuration cfg = new Configuration(Configuration.VERSION_2_3_34);

308

// Uses default MruCacheStorage

309

310

// Custom MRU cache

311

cfg.setCacheStorage(new MruCacheStorage(50, 200));

312

313

// Soft references cache (good for memory-constrained environments)

314

cfg.setCacheStorage(new SoftCacheStorage());

315

316

// Strong cache (never evicts, good for small template sets)

317

cfg.setCacheStorage(new StrongCacheStorage());

318

319

// Disable caching (useful for development)

320

cfg.setCacheStorage(NullCacheStorage.INSTANCE);

321

```

322

323

## Template Lookup Strategy

324

325

Controls how templates are resolved and loaded:

326

327

```java { .api }

328

abstract class TemplateLookupStrategy {

329

// Main lookup method

330

abstract TemplateLookupResult lookup(TemplateLookupContext ctx) throws IOException;

331

332

// Default strategy constants

333

static final TemplateLookupStrategy DEFAULT_2_3_0 = DefaultTemplateLookupStrategy.INSTANCE;

334

}

335

336

// Lookup context

337

class TemplateLookupContext {

338

String getTemplateName();

339

Locale getTemplateLocale();

340

String getCustomLookupCondition();

341

TemplateLoader getTemplateLoader();

342

}

343

344

// Lookup result

345

abstract class TemplateLookupResult {

346

abstract boolean isPositive();

347

}

348

```

349

350

## Template Name Format

351

352

Controls template name formatting and normalization:

353

354

```java { .api }

355

abstract class TemplateNameFormat {

356

// Name formatting methods

357

abstract String normalizeAbsoluteName(String name) throws MalformedTemplateNameException;

358

abstract String normalizeName(String name) throws MalformedTemplateNameException;

359

abstract String toAbsoluteName(String baseName, String targetName) throws MalformedTemplateNameException;

360

abstract String toRootBasedName(String baseName, String targetName) throws MalformedTemplateNameException;

361

362

// Default format constants

363

static final TemplateNameFormat DEFAULT_2_3_0 = DefaultTemplateNameFormat.INSTANCE_2_3_0;

364

static final TemplateNameFormat DEFAULT_2_4_0 = DefaultTemplateNameFormat.INSTANCE_2_4_0;

365

}

366

```

367

368

## Template Configuration

369

370

Per-template configuration using matchers:

371

372

```java { .api }

373

abstract class TemplateConfigurationFactory {

374

abstract TemplateConfiguration get(String sourceName, Object templateSource) throws IOException, TemplateConfigurationFactory.TemplateConfigurationFactoryException;

375

}

376

377

class ConditionalTemplateConfigurationFactory extends TemplateConfigurationFactory {

378

// Constructor

379

ConditionalTemplateConfigurationFactory(TemplateSourceMatcher matcher, TemplateConfigurationFactory factory);

380

381

TemplateConfiguration get(String sourceName, Object templateSource) throws IOException, TemplateConfigurationFactoryException;

382

}

383

384

// Template-specific configuration

385

class TemplateConfiguration extends Configurable implements ParserConfiguration {

386

TemplateConfiguration();

387

388

// Apply configuration to parent configurable

389

void apply(Configurable configurable);

390

}

391

```

392

393

## Template Source Matchers

394

395

Match templates based on various criteria:

396

397

```java { .api }

398

abstract class TemplateSourceMatcher {

399

abstract boolean matches(String sourceName, Object templateSource) throws IOException;

400

}

401

402

// Path glob matching

403

class PathGlobMatcher extends TemplateSourceMatcher {

404

PathGlobMatcher(String glob);

405

PathGlobMatcher(String glob, boolean caseSensitive);

406

boolean matches(String sourceName, Object templateSource) throws IOException;

407

}

408

409

// File extension matching

410

class FileExtensionMatcher extends TemplateSourceMatcher {

411

FileExtensionMatcher(String extension);

412

FileExtensionMatcher(String extension, boolean caseSensitive);

413

boolean matches(String sourceName, Object templateSource) throws IOException;

414

}

415

416

// OR matcher - matches if any submatcher matches

417

class OrMatcher extends TemplateSourceMatcher {

418

OrMatcher(TemplateSourceMatcher... matchers);

419

boolean matches(String sourceName, Object templateSource) throws IOException;

420

}

421

```

422

423

### Template Configuration Examples

424

425

```java

426

Configuration cfg = new Configuration(Configuration.VERSION_2_3_34);

427

428

// Configure specific output format for HTML templates

429

TemplateConfiguration htmlConfig = new TemplateConfiguration();

430

htmlConfig.setOutputFormat(HTMLOutputFormat.INSTANCE);

431

htmlConfig.setAutoEscapingPolicy(Configuration.ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY);

432

433

cfg.setTemplateConfigurations(

434

new ConditionalTemplateConfigurationFactory(

435

new FileExtensionMatcher("html"),

436

new FirstMatchTemplateConfigurationFactory(htmlConfig)

437

)

438

);

439

440

// Configure different settings for email templates

441

TemplateConfiguration emailConfig = new TemplateConfiguration();

442

emailConfig.setOutputFormat(PlainTextOutputFormat.INSTANCE);

443

emailConfig.setWhitespaceStripping(true);

444

445

cfg.setTemplateConfigurations(

446

new ConditionalTemplateConfigurationFactory(

447

new PathGlobMatcher("email/**"),

448

new FirstMatchTemplateConfigurationFactory(emailConfig)

449

)

450

);

451

```

452

453

## Cache Management

454

455

### Cache Control Methods

456

457

```java { .api }

458

// In Configuration class

459

void clearTemplateCache();

460

void removeTemplateFromCache(String name);

461

void removeTemplateFromCache(String name, Locale locale);

462

void removeTemplateFromCache(String name, Locale locale, String encoding);

463

void removeTemplateFromCache(String name, Locale locale, String encoding, boolean parseAsFTL);

464

465

// Cache statistics (if supported by cache storage)

466

CacheStorage getCacheStorage();

467

```

468

469

### Cache Monitoring Example

470

471

```java

472

Configuration cfg = new Configuration(Configuration.VERSION_2_3_34);

473

MruCacheStorage cache = new MruCacheStorage(100, 500);

474

cfg.setCacheStorage(cache);

475

476

// Monitor cache size

477

System.out.println("Cache size: " + cache.getSize());

478

System.out.println("Max strong size: " + cache.getMaxStrongSize());

479

480

// Clear specific templates from cache

481

cfg.removeTemplateFromCache("outdated-template.ftl");

482

483

// Clear entire cache

484

cfg.clearTemplateCache();

485

```

486

487

## Performance Optimization

488

489

### Template Loading Best Practices

490

491

1. **Use appropriate cache storage**: Choose based on memory constraints and template count

492

2. **Configure cache size limits**: Set limits based on your application's template usage patterns

493

3. **Use template pre-loading**: Load frequently used templates at startup

494

4. **Monitor cache hit rates**: Adjust cache size based on actual usage patterns

495

496

### Example: High-Performance Configuration

497

498

```java

499

Configuration cfg = new Configuration(Configuration.VERSION_2_3_34);

500

501

// Optimized for high-throughput applications

502

cfg.setTemplateLoader(new FileTemplateLoader(new File("templates")));

503

cfg.setCacheStorage(new MruCacheStorage(500, 2000)); // Large cache

504

cfg.setDefaultEncoding("UTF-8");

505

cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

506

cfg.setLogTemplateExceptions(false); // Reduce logging overhead

507

cfg.setWrapUncheckedExceptions(true);

508

509

// Pre-load critical templates

510

cfg.getTemplate("header.ftl");

511

cfg.getTemplate("footer.ftl");

512

cfg.getTemplate("main-layout.ftl");

513

```

514

515

### Custom Template Loader Example

516

517

```java

518

public class DatabaseTemplateLoader implements TemplateLoader {

519

private final DataSource dataSource;

520

521

public DatabaseTemplateLoader(DataSource dataSource) {

522

this.dataSource = dataSource;

523

}

524

525

@Override

526

public Object findTemplateSource(String name) throws IOException {

527

try (Connection conn = dataSource.getConnection();

528

PreparedStatement stmt = conn.prepareStatement(

529

"SELECT content, last_modified FROM templates WHERE name = ?")) {

530

531

stmt.setString(1, name);

532

ResultSet rs = stmt.executeQuery();

533

534

if (rs.next()) {

535

return new DatabaseTemplateSource(

536

name,

537

rs.getString("content"),

538

rs.getTimestamp("last_modified").getTime()

539

);

540

}

541

return null;

542

} catch (SQLException e) {

543

throw new IOException("Failed to load template: " + name, e);

544

}

545

}

546

547

@Override

548

public long getLastModified(Object templateSource) {

549

return ((DatabaseTemplateSource) templateSource).getLastModified();

550

}

551

552

@Override

553

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

554

String content = ((DatabaseTemplateSource) templateSource).getContent();

555

return new StringReader(content);

556

}

557

558

@Override

559

public void closeTemplateSource(Object templateSource) throws IOException {

560

// Nothing to close for database templates

561

}

562

563

private static class DatabaseTemplateSource {

564

private final String name;

565

private final String content;

566

private final long lastModified;

567

568

DatabaseTemplateSource(String name, String content, long lastModified) {

569

this.name = name;

570

this.content = content;

571

this.lastModified = lastModified;

572

}

573

574

String getContent() { return content; }

575

long getLastModified() { return lastModified; }

576

}

577

}

578

```