Exposing Java Methods to a Template

The TemplateMethodModel interface defines FreeMarker's way of implementing methods within a TemplateModel. The signature of a TemplateMethodModel is below:

public TemplateModel exec(java.util.List arguments)
                   throws TemplateModelException;
        

The argument list that FreeMarker supplies is a list of String objects, each one corresponding with an argument supplied to the method, in the order that they were specified. If a method is called with no arguments, the list will be empty, rather than null.

Note: Unlike other languages, such as Perl, FreeMarker does not flatten complex variables by default. If an object is passed that does not support the TemplateScalarModel FreeMarker will issue an error message.

Starting from FreeMarker 2.0, there is also a subinterface of TemplateMethodModel named TemplateMethodModelEx. This interface defines no new methods, rather it instructs the template engine that it should not pass it Strings as arguments, but rather TemplateModels to which the arguments evaluate in the template. This allows for more versatile method implementations that can take advantage of the ability to operate on models. In this case, arguments can be arbitrary TemplateModels, and not only TemplateScalarModels.

Like most other models, TemplateMethodModel returns a TemplateModel. This allows method calls to be very flexible, and allows methods to be chained together similarly to the way other TemplateModels can be chained.

Note that TemplateMethodModel implements a call to only one method. To provide many methods, wrap up lots of TemplateMethodModels inside a TemplateHashModel, one for each method you want to provide. To automatically gain access to all methods of an arbitrary Java object, wrap it using the freemarker.ext.beans.BeansWrapper - it will do exactly as previously described and create a hash model that has a TemplateMethodModelEx for every method on the object.

Methods are first-class objects in FreeMarker

If you have a hash named myBall that has a method named getColor, you can quite intuitively write

${myBall.getColor()}
	

in the template to invoke the method and retrieve the color of the ball. However, what is less obvious is that you can assign the method to a variable, and use it on its own, like in:

<assign getColorOfMyBall = myBall.getColor>
${getColorOfMyBall()}
	

By omitting the parentheses in the assign instruction, you didn't execute the method, rather you assigned the method itself to a variable, and then you have called it separately. This ability is found in several programming languages (Python and Lisp come to mind) and has several applications. Instead of writing

<if cond1>
  ${obj1.method1(arg1, arg2, arg3, arg4, arg5, arg6)}
<elseif cond2>
  ${obj2.method2(arg1, arg2, arg3, arg4, arg5, arg6)}
<else>
  ${obj3.method3(arg1, arg2, arg3, arg4, arg5, arg6)}
</if>
	

you can write instead:

<if cond1>
  <assign method = obj1.method1>
<elseif cond2>
  <assign method = obj2.method2>
<else>
  <assign method = obj3.method3>
</if>
${method(arg1, arg2, arg3, arg4, arg5, arg6)}
	

Thus sparing yourself from duplicating the argument list three times. Other applications include the ability to pass a method as an argument to another method (we won't explore this into depth now, but it is a very powerful feature).