Apache FreeMarker Generator Tools

Overview

The implementation of the Apache FreeMarker Generator Tools was inspired by Apache Velocity Tools - a tool is just a POJO (plain old Java object) that is “useful” in a template and is not meant to be rendered in the output.

Let's have a look at the anatomy and life-cycle of a Apache FreeMarker Generator Tool

  • The meta-data, e.g. class name, is read from freemarker-generator.properties
  • It provides a default constructor
  • Its toString methods prints a short description
  • It exposes public methods being used directly by the template
  • It is instantiated once and is multi-thread-safe

Available Tools

The following tools are currently implemented

ToolDescription
CSVToolProcess CSV files using Apache Commons CSV
DataFrameToolBridge to nRo/DataFrame
ExecToolExecute command line tools using Apache Commons Exec
ExcelToolProcess Excels files (XLS, XLSX) using Apache POI
FreeMarkerToolExpose useful FreeMarker classes
GrokToolProcess text files using Grok instead of regular expressions
GsonToolProcess JSON files using GSON
JsonPathToolProcess JSON file using Java JSON Path
JsoupToolProcessing HTML files using Jsoup
PropertiesToolProcess JDK properties files
SystemToolSystem-related utility methods
UUIDToolCreate UUIDs
XmlToolProcess XML files using Apache FreeMarker
YamlToolProcess YAML files using SnakeYAML

Advanced Topics

Auto-closing Resources

The user can create objects which need to be closed later on to avoid excessive resource usage. This is less of a concern for a short-lived CLI application but if many data sources are processed or the code is used in a different context the problem becomes more severe.

The Excel Tool provides the following code to keep track of Closables

package org.apache.freemarker.generator.tools.excel;

public class ExcelTool {

    public Workbook parse(DataSource dataSource) {
        try (InputStream is = dataSource.getUnsafeInputStream()) {
            final Workbook workbook = WorkbookFactory.create(is);
            // make sure that the workbook is closed together with the data source
            return dataSource.addClosable(workbook);
        } catch (IOException e) {
            throw new RuntimeException("Failed to parse Excel data source: " + dataSource, e);
        }
    }
}

So what is happening here

  • The Workbook is tracked by the originating DataSource
  • The DataSource implements the Closable interface
  • All DataSources are closed automatically when rendering is done.