Apache FreeMarker CLI Tools

Overview

The implementation of the Apache FreeMarker CLI 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 CLI Tool

  • The meta-data, e.g. class name, is read from freemarker-cli.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

Tool Description
CSVTool Process CSV files using Apache Commons CSV
DataFrameTool Bridge to nRo/DataFrame
ExecTool Execute command line tools using Apache Commons Exec
ExcelTool Process Excels files (XLS, XLSX) using Apache POI
FreeMarkerTool Expose useful FreeMarker classes
GrokTool Process text files using Grok instead of regular expressions
GsonTool Process JSON files using GSON
JsonPathTool Process JSON file using Java JSON Path
JsoupTool Processing HTML files using Jsoup
PropertiesTool Process JDK properties files
SystemTool System-related utility methods
UUIDTool Create UUIDs
XmlTool Process XML files using Apache FreeMarker
YamlTool Process 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.