Freemarker Templating Engine

Freemarker is a very popular and mature templating engine. Its integration as a Quarkus extension provides developers ease of configuration, and offers support for native images. In this guide, you will learn how to easily render Freemarker templates in your application.

Hello World

If you want to use Freemarker you need to add the quarkiverse-freemarker extension first. In your pom.xml file, add:


We’ll start with a very simple template:

Hello ${name}! (1)
1 ${name} is a value expression that is evaluated when the template is rendered.

Now let’s inject the template in the resource class.
package org.acme.quarkus.sample;

import jakarta.inject.Inject;

import freemarker.template.Template;
import io.quarkiverse.freemarker.runtime.TemplatePath;

public class HelloResource {

    @TemplatePath("hello.ftl") (1)
    Template hello;

    public String hello(@QueryParam("name") String name) throws IOException, TemplateException {
        StringWriter stringWriter = new StringWriter();
        hello.process(Map.of("name", name), stringWriter); (2)
        return stringWriter.toString();
1 The @TemplatePath qualifier specifies the template name, found in either jar resource paths or external file paths.
2 Map.of("name", name) provides the model.

If your application is running, you can request the endpoint:

$ curl -w "\n" http://localhost:8080/hello?name=bob
Hello bob!


The application code can either directly inject a Freemarker Template bean as we saw above. In that case it must provide a TemplatePath qualifier annotation with the name of the template to select.

Or it can inject a Freemarker Configuration bean, from which templates can be obtained programmatically. The Configuration is a Singleton DefaultBean that can be replaced by an application provided implementation.

The default Configuration bean is configured from quarkus exposed properties. Among those, 2 are build time:

  • resource-paths is a list of resource paths contained in the classpath (e.g. typically in jars of the application). Each path is traversed recursively, and all files get added as native resources when building a native image.

  • directives is a map of directive alias to directive class name. Each directive class is added as a shared variable in the Configuration bean.

Here is an example of using a Configuration bean instead of a Template bean:

    Configuration configuration;

    public String hello(@QueryParam("name") String name, @QueryParam("ftl") String ftl) throws IOException, TemplateException {
        StringWriter stringWriter = new StringWriter();
        configuration.getTemplate(ftl).process(model, stringWriter);
        return stringWriter.toString();

The rest of the configuration properties can be provided at runtime, such as a list of external filesystem paths where to find additional templates, and optional properties that can be configured on the Freemarker Configuration class.


Freemarker can be extended using custom directives. For instance if we wanted to transform some text in base64, we could write:

package org.acme.quarkus.sample;

public class Base64Directive implements TemplateDirectiveModel {
    public void execute(Environment environment, Map map, TemplateModel[] templateModels, TemplateDirectiveBody body)
            throws TemplateException, IOException {
        StringWriter sw = new StringWriter();
        byte[] bytes = Base64.getEncoder().encode(sw.toString().getBytes(UTF_8));
        environment.getOut().write(new String(bytes, UTF_8));

Then we would have to configure the application with:


And finally, we would use it in templates such as:

Hello <@base64>$\{name}</@base64>!

This would be rendered as:

Hello Ym9i!

Data model

Freemarker supports Map or Object based data models. When using objects, it is important to configure quarkus.freemarker.object-wrapper-expose-fields=true if model classes do not have getters.

Additionnaly, they should be annotated with @RegisterForReflection to support native images.

Freemarker Configuration Reference

Configuration property fixed at build time - All other configuration properties are overridable at runtime

Configuration property



Comma-separated list of absolute resource paths to scan recursively for templates. All tree folder from 'resource-paths' will be added as a resource. Unprefixed locations or locations starting with classpath will be processed in the same way.

list of string


Comma-separated of file system paths where freemarker templates are located

list of string

Set the preferred charset template files are stored in.


Sets how errors will appear. rethrow, debug, html-debug, ignore.


If false, don’t log exceptions inside FreeMarker that it will be thrown at you anyway.


Wrap unchecked exceptions thrown during template processing into TemplateException-s.


If false, do not fall back to higher scopes when reading a null loop variable.


The string value for the boolean true and false values, usually intended for human consumption (not for a computer language), separated with comma.


Sets the default number format used to convert numbers to strings.


If true, the object wrapper will be configured to expose fields.


List of directives to register with format name=classname