Write HTML using FreeMarker Templates

Updated: Feb 21, 2022

This example shows you how to create an HTML file in Java via freemarker templates using the TemplateWriter class. FreeMarker is a "template engine"; a generic tool to generate text output based on templates.

The demo code creates some dummy records in memory and writes them to an HTML file. However, the HTML file may be created from other input sources like CSV,Excel, etc.

This example can easily be modified to show how to create an XML file via freemarker templates.

Java Code Listing

package com.northconcepts.datapipeline.examples.cookbook;

import java.io.File;
import java.io.FileWriter;

import com.northconcepts.datapipeline.core.Record;
import com.northconcepts.datapipeline.core.RecordList;
import com.northconcepts.datapipeline.job.Job;
import com.northconcepts.datapipeline.memory.MemoryReader;
import com.northconcepts.datapipeline.template.TemplateWriter;

public class WriteHtmlUsingFreeMarkerTemplates {

    /*
     * Produces the following HTML
     * 
     * 
     * 
     * 
stageName realName gender city balance
John Wayne Marion Robert Morrison male Winterset 156.35
SpidermanPeter Parker male New York -0.96
* */ public static void main(String[] args) throws Throwable { Record record1 = new Record(); record1.getField("stageName", true).setValue("John Wayne"); record1.getField("realName", true).setValue("Marion Robert Morrison"); record1.getField("gender", true).setValue("male"); record1.getField("city", true).setValue("Winterset"); record1.getField("balance", true).setValue(156.35); Record record2 = new Record(); record2.getField("stageName", true).setValue("Spiderman"); record2.getField("realName", true).setValue("Peter Parker"); record2.getField("gender", true).setValue("male"); record2.getField("city", true).setValue("New York"); record2.getField("balance", true).setValue(-0.96); MemoryReader reader = new MemoryReader(new RecordList(record1, record2)); TemplateWriter writer = new TemplateWriter(new FileWriter("example/data/output/credit-balance-04.html"), false); writer.setFieldNamesInFirstRow(false); writer.getConfiguration().setDirectoryForTemplateLoading(new File("example/data/input")); // writer.setHeaderTemplate("WriteHtmlUsingFreeMarkerTemplates-header.html"); // No header in this example writer.setFooterTemplate("WriteHtmlUsingFreeMarkerTemplates-footer.html"); writer.setDetailTemplate("WriteHtmlUsingFreeMarkerTemplates-detail.html"); Job.run(reader, writer); } }

Java Code Listing

  1. Two Record objects are created in memory with the fields stageName, realName,gender,city and balance set to some test values.
  2. These Record objects are added to a RecordList.
  3. A MemoryReader is created to read this RecordList.
  4. A TemplateWriter object is created corresponding to the output HTML file credit-balance-04.html.
  5. The Configuration.setDirectoryForTemplateLoading method is invoked which sets the file system directory from which to load templates.
  6. The header,footer and detail template are set using the setHeaderTemplate, setFooterTemplate and setDetailTemplate respectively.
  7. Data is transferred from memory to the output HTML file via JobTemplate.DEFAULT.transfer method.

MemoryReader

A MemoryReader is an input reader that reads data from memory. It is a sub-class of DataReader and is created using a RecordList. It has a method called getRecordList() which can be used to retrieve the underlying RecordList. RecordList is a data structure for storing Record objects. Record encapsulates a single line of information and is the basic unit of data transfer. Data transfers of all types occur as Record objects i.e. data from an input source is read as a Record object and written to the output source as a Record object.

TemplateWriter

A TemplateWriter class can be used to create an output file based on freemarker templates. It is a sub-class of TextWriter.html and overrides the open and close among other methods. Its setFieldNamesInFirstRow method can be used to specify whether the field names should be used in the first row or not. So if invoked with a true value, an additional row will be created in the output HTML with the field names.

The getConfiguration method returns a Configuration object from FreeMarker API which can be used to set the file system directory from which to load templates via Configuration.setDirectoryForTemplateLoading method. Setter methods are defined to set the file paths of the header, footer and detail freemarker templates. These templates are then used by the freemarker API to generate the Header, body and footer of the output HTML file as detailed below.

FreeMarker Templates

Two FreeMarker templates are used as follows:

Detail

The detail template i.e. WriteHtmlUsingFreeMarkerTemplates-detail.html contains the FreeMarker code to convert each record to HTML. Note that this template is invoked once for every record in the input.

<#if (writer.recordCount == 0)>
<table>
	<thead>
		<tr>
		<#list record.fieldNames as fieldName>
			<td>${fieldName}</td>
		</#list>		
		</tr>
	</thead>
	<tbody>
</#if>
		<tr>
			<#list record.values as value>
				<td>${value}</td>
			</#list>
		</tr>

This freemarker code first checks if the current record is the first record via writer.recordCount == 0 and if so the HTML table and thead tags are added. This is so that the table heading is added only once. A list directive then loops through all the field names and outputs them as table headings. Following the if directive is a freemarker list directive which loops through all the field values in a record and outputs the field value in each HTML table cell i.e. td. This code is invoked for each record and is responsible for displaying the values in a record.

Footer

The footer contains the HTML tags for closing the HTML table.

	</tbody>
</table>

Output HTML file

<table>
    <thead>
        <tr>
            <td>stageName</td>
            <td>realName</td>
            <td>gender</td>
            <td>city</td>
            <td>balance</td>
        </tr>
    </thead>
    <tbody>
        <tr>
                <td>John Wayne</td>
                <td>Marion Robert Morrison</td>
                <td>male</td>
                <td>Winterset</td>
                <td>156.35</td>
        </tr>
        <tr>
                <td>Spiderman</td>
                <td>Peter Parker</td>
                <td>male</td>
                <td>New York</td>
                <td>-0.96</td>
        </tr>
    </tbody>
</table>
The above HTML is displayed as follows in the browser:
stageName realName gender city balance 

John Wayne Marion Robert Morrison male Winterset 156.35 
Spiderman Peter Parker male New York -0.96 
Mobile Analytics