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");


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
read a value from a map
print variable without readability characters (numbers without commas, etc)
defining a sequence
<#assign values = ["a", "b"]>
<#list seq[1..3] as i>${i}</#list>
accessing a value from a sequence
date with format
${lastUpdated?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)>

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