loading table of contents...

4.3.4.2. Advanced Patterns for FreeMarker Templates

Working with Maps in FreeMarker Templates

FreeMarker supports variables of type hash, which are unordered mappings of strings to other models, and provide the built-in ?keys and ?values to expose the key and value sets as sequences. In order to support maps with key types other than strings, the CAE FreeMarker view engine does not map Java objects of type java.util.Map to FreeMarker hashes. Instead, java.util.Map methods will be available on such models. In order to access the entry, key, or value sets, call the respective methods on the model object. Any such set is a FreeMarker sequence and thus compatible with the #list directive.

<#list map.entrySet() as entry>
  ${entry.key} is mapped to ${entry.value}
</#list>

Example 4.8. Iterating over java.util.Map entries in FreeMarker templates


Using JSP Tag Libraries in FreeMarker Templates

FreeMarker templates can access functionality provided by a JSP tag library, assuming that the tag library is deployed in the web application as specified in JavaServer Pages 2.2 and up. Import the tags exposed by a JSP tag library into a named hash by using its URI as a key into the implicit JspTaglibs map. The imported tags will be available as custom directives in the named hash.

<#assign fmt=JspTaglibs["http://java.sun.com/jsp/jstl/fmt"]>
<@fmt.formatNumber value=self.someValue/>

JspTaglibs only exposes tags, not static methods exposed by a JSP tag library as functions.

Accessing Static Methods in Freemarker Templates

To give a FreeMarker template access to public static methods of a Java class, you have to implement a "facade" Java singleton that provides non-static methods that delegate to the static methods.

public final class FreemarkerFacaceExample {

  public static final FreemarkerFacaceExample INSTANCE = new FreemarkerFacaceExample();

  private FreemarkerFacaceExample() {
  }

  /**
   * Provides non-static access to static method.
   */
  public String nonStaticDefaultString(String text) {
    return StringUtils.defaultString(text);
  }

}

Then, add this singleton as a shared variable to the CAE's FreeMarker configuration, and access the methods using the singleton in any CAE FreeMarker template.

The following listing shows an example Spring configuration to add a custom shared FreeMarker variable, assuming the facade singleton class is called com.company.cae.MyFreemarkerFacade and the variable should be exposed as myFreemarkerFacade.

<import resource="classpath:/com/coremedia/cae/view-freemarker-services.xml"/>

<customize:append id="myFreemarkerSharedVariablesCustomizer"
                  bean="freemarkerSharedVariables">
  <map>
    <entry key="myFreemarkerFacade">
      <bean class="com.company.cae.MyFreemarkerFacade">
        <!-- inject services etc. here! -->
      </bean>
    </entry>
  </map>
</customize:append>
Auto-Import of Freemarker Functions and Macros

In order to expose functions, macros, or common configuration to all templates, you need to add the corresponding Freemarker file to the freemarkerConfigurer bean's property autoImports. The following listing shows an example Spring configuration that exposes all functions of custom-functions.ftl with the name cufu.

<import resource="classpath:/com/coremedia/cae/view-freemarker-services.xml"/>

<customize:append id="myFreemarkerAutoImportsCustomizer"
                  bean="freemarkerConfigurer" property="autoImports">
  <map>
    <entry key="cufu"
           value="/lib/custom/freemarker/custom-functions.ftl"/>
  </map>
</customize:append>

All functions are now available to your Freemarker templates. However, the IDE will most likely not recognize these functions and the name defined in your Spring configuration. Adding a freemarker_implict.ftl as shown in Example 4.9, “Code for Idea auto-completion” to src/main/resources/META-INF/resources/ within your Maven module's directory will add auto-completion to the IntelliJ IDEA development environment.

[#ftl]
[#-- @implicitly included --]
[#import "/lib/custom/freemarker/custom-functions.ftl" as cufu]

Example 4.9. Code for Idea auto-completion