I recently moved my current web front-end project from rendering views with the Velocity templating engine to use FreeMarker. This entry describes some of the reasons why I chose to make this move.

The main reason I find Velocity annoying is that it does not address – within its core functionality – the most common tasks faced by a template author. This does not mean that these tasks cannot be achieved but it does mean that they are often difficult to achieve, require work-arounds or extra tools or are simply overly verbose for such common tasks. Some specific examples include:

Formatting dates

Formatting numbers

Formatting currency

Detecting whether a variable exists in the template model (in other words, that it is not null)

Providing the value of a template variable if it exists, or a specified default value if it doesn’t.
This is simply an ‘if/else’ statement but one that is performed so often in templates – freemarker achieves this using the syntax ${myVar?default('default text')}

URL and HTML escaping

The first three formatting issues are interesting since processing text for human consumption will, particularly in a business environment, often involve dates, numbers and currency (web pages for an online shop and their confirmation emails, stock reports etc.) Not having built in support for detecting and dealing with null values is just plain weird. A related gotcha that has fooled me a number of times is that assignments in Velocity are completely ignored if the right hand side evaluates to null – which can produce havoc in loops, as the variable on the left hand side remains at the value used in the previous iteration.

Template Language Syntax

I also find that the FreeMarker syntax is far more appealing. Every statement is properly delimited – and therefore works predictably. I seem to be constantly tracking down odd parsing errors with Velocity. Consider the following fragment in Velocity:

#if( $variableIsTrue )something#elsesomething else#end

This layout is often required due to white-space handling, however not only is it difficult to read, but it will not work as expected either. The Velocity documentation says that the following should be allowed:

#if( $variableIsTrue )something#{else}something else#{end}

But whenever I try it, I get a parse-error for that too. In FreeMarker you can write the following – and it always works as expected:

<#if variableIsTrue>something<#else>something else</#if>

Array Support

Within templates, one often needs to iterate through the contents of a list of some sort. This may be an array or an ArrayList for example. The template author doesn’t necessarily know or care what the underlying implementation of the list is. In Velocity, if it is an ArrayList then you may find out how many elements are contained within using $myList.size() – however you cannot determine the length of an array without installing extra tools. If you’re using Freemarker then whether it’s an ArrayList or an array you can still access the number of elements consistently using myList?size.

Name Spaces

Both Velocity and FreeMarker support the notion of macros. These are extremely handy for defining chunks of text that will be reused multiple times making templates more maintainable and easier to read. FreeMarker supports name spaces for macro libraries so that variables and macro names do not interfere with each other. Whilst using Spring Framework and Velocity, the variable $status often contains Spring macro related values – so I can’t use this variable name for other purposes or worse still if I do, it will have unpredictable results. However, in FreeMarker I import the Spring macro library under the name-space ‘spring’ so that the variable spring.status is completely different from the variable status outside of the Spring macro definitions.

FreeMarker Problems

FreeMarker has proved to be much more suited than Velocity to its role of text processing. FreeMarker is not without its own problems, though I have only found one so far. When putting a HashMap object into the template model, it is not possible to pull out objects from it if the key is not a string. The Spring framework macros that create drop-down lists (HTML <select> elements) use a HashMap for the entries in the list – it is often useful to have numeric keys for these entries, especially when having a database generated list where the primary-keys can be used to index the HashMap.

Non-Java Templating Technologies

As an aside, two non-Java related templating systems that I think are excellent are Template Toolkit for Perl and Smarty for PHP.

4 Responses

I’ve just started using Smarty for our new blog project. I do say it’s excellent, only problem is it uses strftime() for date formatting, which means I can’t use ordinal suffixes (st, nd, rd) on dates.

If you’re using the BeansWrapper, you can use the method invocation syntax to retrieve non-string keyed objects from maps. I.e. if variable “nonString” contains a – well – non-string object, then${map(nonString)}