Hello World

public static void main(String[] args) throws IOException, TemplateException {
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);

        StringTemplateLoader tl = new StringTemplateLoader();
        tl.putTemplate("bla", "blabla ${test} blabla");
        Template template = cfg.getTemplate("bla");

        // Build the data-model
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("test", "Hello World!");

        // Console output
        Writer out = new OutputStreamWriter(System.out);
        template.process(data, out);
loading templates from the classpath
TemplateLoader ctl = new ClassTemplateLoader(getClass(), "/freemarker");
loading templates from the filesystem
TemplateLoader ftl = new FileTemplateLoader(new File(templatePath));
chaining multiple template loaders
TemplateLoader mtl = new MultiTemplateLoader(new TemplateLoader[] { ftl, ctl });
storing the result in a String
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer writer = new OutputStreamWriter(baos);
cfg.getTemplate(template).process(data, writer);
return baos.toString("UTF-8");

escaping output

filename extension for auto escape html special chars
filename extension for auto escape xml special chars
force escaping for a specific output format regardless of filename (inludes not affected)
<#ftl output_format="HTML">
print raw value (no escaping)


assign variable
<#assign x = 1>
different kind of null checks
?? -> not null
?has_content -> not empty
![fallback] -> fallback if null
(user.price)! handles all missing variable errors thrown during the evaluation of the ()
optional value
default value if null
section depending on optional value
<#if log??>



string comparison
<#if someString == someOtherString>
<#if someString != someOtherString>


string to number
compare 2 numbers
${[number] lt [number]}
${[number] gt [number]}
${[number] lte [number]}
${[number] gte [number]}
print variable without readability characters (numbers without commas, etc)


logical or
logical and
logical not


create a simple map
{'[key]': '[value]'}
read a value from a map
iterate keys
<#list map?keys as key>${key} = ${map[key]}</#list>


defining a sequence
<#assign values = ["a", "b"]>
<#list seq[1..3] as i>${i}</#list>
accessing a value from a sequence
collection is empty?
?size = 0
collection contains value?


date with format
${aDateTime?string["dd.MM.yyyy, HH:mm"]}


include another template
<#include "layout/bottom.tpl"/>
simple macro
<#macro header title>
macro usage
<@header title='blabla' />
macro with optional value
<#macro [name] [param]="[preset]" >
macro with optional value and check
<#macro [name] [param]="" >
	<#if ([param]?has_content)>
macro with nested content
<#macro wrap>
	before <#nested> after
calling a macro with nested content

control flow

ternary operator
${result.incorrect ? then ('incorrect', 'visible')}
${( == 0) ? then ('a', 'b')}
if else
<#if condition>
<#elseif condition>
iterating a sequence
<#list values as value>
for each loop
<#list someList as entry>
iterating with index
<#list 0..variable?size-1 as index>

Tree structures

navigating a tree structure
<#macro tree nodes>
  <#list nodes.getChildren() as node>
        <#if node.hasChildren()>
          <@tree nodes=node />
to call
<@tree nodes=root/>
sample tree node
public class TreeNode {
	private List<TreeNode> children = new ArrayList<>();
	private String name;

	public TreeNode(String name) { = name;

	public List<TreeNode> getChildren() {
		return children;

	public String getName() {
		return name;

	public boolean hasChildren() {
		return !children.isEmpty();


try freemarker code online