# Creating a Custom Magnolia CMS Templating Function

# Introduction

Magnolia CMS templating functions allow you to provide Java functionality to FreeMarker templates. This guide will teach you how to create a custom templating function.

See magnolia-cms-templating-function-demo for a fully functional Maven module based on this guide.

# Prerequisites

This guide assumes the following:

# Step 1—Creating the Module

Follow the Magnolia instructions to create a Magnolia Maven module with the Magnolia Maven archetype. Your module parameters should look something like:

groupId: com.ryanbrookepayne.magnolia
artifactId: magnolia-templating-functions
version: 1.0-SNAPSHOT
package: com.ryanbrookepayne.magnolia
magnolia-bundle-version: 6.1
module-class-name: MagnoliaTemplatingFunctionsModule
module-name: magnolia-templating-functions

# Step 2—Creating the Templating Functions Class

Open your newly created module with your IDEA and create a templating.functions package in the main directory.

Create a HelloWorldTemplatingFunctions class in the templating.functions package.

package com.ryanbrookepayne.magnolia.templating.functions;

public class HelloWorldTemplatingFunctions {
}

# Step 3—Creating the Functions

In the HelloWorldTemplatingFunctions class, create a FUNCTION_NAME field. Once installed, this name (hellofn) will be globally available in all FreeMarker template scripts. While not functional, Magnolia follows the {function_name}fn convention.

package com.ryanbrookepayne.magnolia.templating.functions;

public class HelloWorldTemplatingFunctions {

  public static final String FUNCTION_NAME = "hellofn";

}

Next, add two simple Java methods:

package com.ryanbrookepayne.magnolia.templating.functions;

public class HelloWorldTemplatingFunctions {

  public static final String FUNCTION_NAME = "hellofn";

  public String sayHello() {
    return "Hello world!";
  }

  public String sayHello(int headingLevel) {
    return String.format("<h%1$s>Hello world!</h%1$s>", headingLevel);
  }
}

Once the templating function is installed, these methods will be available in FreeMarker template scripts. For example:

${hellofn.sayHello()}

# Step 4—Installing the Functions

In Magnolia, templating functions are known as context attributes and are instantiated via dependency injection-using Google Guice. Because of this, they must be configured as both components and renderers.

# Adding the Component

Add the reference to the HelloWorldTemplatingFunctions class to the magnolia-templating-functions module descriptor.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module SYSTEM "module.dtd">
<module>
    ...
    <components>
        <id>main</id>
        <component>
            <type>com.ryanbrookepayne.magnolia.templating.functions.HelloWorldTemplatingFunctions</type>
            <implementation>com.ryanbrookepayne.magnolia.templating.functions.HelloWorldTemplatingFunctions</implementation>
            <scope>singleton</scope>
        </component>
    </components>
    ...
</module>

# Installing the Renderer

First, add the magnolia-rendering dependency to the main pom.xml file:

<dependencies>
    ...
    <dependency>
        <groupId>info.magnolia</groupId>
        <artifactId>magnolia-rendering</artifactId>
    </dependency>
    ...
</dependencies>

Next, add the required renderer tasks to the MagnoliaTemplatingFunctionModuleVersionHandler class:

package com.ryanbrookepayne.magnolia.setup;

import ...

public class MagnoliaTemplatingFunctionsModuleVersionHandler extends DefaultModuleVersionHandler {

  @Override
  protected List<Task> getStartupTasks(InstallContext installContext) {
    List<Task> tasks = new ArrayList<>();
    tasks.add(
        new InstallRendererContextAttributeTask(
            "rendering",
            "freemarker",
            HelloWorldTemplatingFunctions.FUNCTION_NAME,
            HelloWorldTemplatingFunctions.class.getName()));
    tasks.add(
        new InstallRendererContextAttributeTask(
            "site",
            "site",
            HelloWorldTemplatingFunctions.FUNCTION_NAME,
            HelloWorldTemplatingFunctions.class.getName()));
    return tasks;
  }
}

❗️ IMPORTANT: The official documentation example uses the getExtraInstallTasks method to install the renderer context attributes. However, this method DOES NOT install the attributes. Use the getStartupTasks method instead.

# Step 5—Using the Functions

In the dummy-component.ftl template script, implement the templating functions:

${hellofn.sayHello()}
${hellofn.sayHello(2)}

Follow the Magnolia instructions to install your module then start up Magnolia. Create a page and use the "dummy-component". Your page should look like:


Feedback

Thanks to the following folks for providing feedback on this guide: