2.0 RC2

FreeMarker 2.0 RC 2 was released on 4 April 2002. Here is a summary of changes wrt to the first release.

Changes to Template Language

  • Certain built-in functionality is provided via a new operator, '?'. Thus, myList?size provides the number of elements in a list. Similarly, myString?length provides the length of a string, myString?upper_case puts the string all in capital letters, and myHash?keys provides a sequence containing the keys in the hash. See Template Language Reference/Built-in Reference for list of all available built-ins.

  • Numerical comparisons can now be made using the "natural" operators < and > but there are also "web-safe" alternatives, such as \lt and \gt, since the use of these characters may confuse HTML editors and parsers. Note that these changed between rc1 and rc2, they now start with a backslash. A little asymmetry is the fact that if you use the natural greater-than or greater-than-or-equals operators (i.e. > or >=) the expression must be in parentheses. With any other operator, the parentheses are optional.

  • Within an iteration loop -- i.e. a foreach or a list block -- the current count in the loop is available as the special variable index_count. where index is the name of the variable in the iteration. A boolean variable called index_has_next is also defined that indicates whether there are any more items in the iteration after this one. Note that the index starts at zero, so you will often be adding one to it in practice.

  • The <#break> directive can now be used to break out of a <#foreach...> or a <list...> loop. (Prior to this version, it only worked within a switch-case block.) There is a new directive called <#stop> that, when encountered, simply halts processing of the template. This can be useful for debugging purposes.

  • When invoking java methods that have been exposed to the page, using the code in freemarker.ext.*, there are built-ins that allow you to indicate the numerical type that you wish to pass as the value. For instance, if you had two methods, one that takes an int and another that takes a long, and you wanted to pass in a value, you would have to specify which method. myMethod(1?int) or myMethod(1?long). This is unnecessary if there is only one method of the given name.

  • Ranges can be used to get the sublist from a list or the substring of a string. For example: myList[0..3] will return items 0 through 3 of the list in question. Or, for example, you could get all the elements of the list except for the first and last ones via: myList[1..(myList?size-2)]

  • Or we could get the first 6 characters of a string via myString[0..5]

  • Lists can be concatenated using the '+' operator. Previously, this overloading of '+' only applied to strings.

  • An attempt to compare a number to a string now throws an exception, since it is indicative of a coding error. Note that there is a backward compatibility mode that can be set (see below) that loosens this up in order to be able to process legacy templates.

API Changes

  • The TemplateSequenceModel interface now has a size() method for getting the number of elements in the sequence in question.

  • The TemplateModelIterator interface now has a hasNext() method.

  • The default sequence and hash implementations, freemarker.template.SimpleSequence and freemarker.template.SimpleHash are now unsynchronized. If you need the methods to be synchronized, you can get a synchronized wrapper via the synchronizedWrapper() in either class.

  • The freemarker.utility.ExtendedList and freemarker.utility.ExtendedHash classes were removed, since all of the extra keys that it defined are now available using the appropriate '?' built-in operation, i.e. myHash?keys or myList?size or myList?last.

  • There is a method in java.freemarker.Configuration named setDebugMode() which allows you to decide whether stack traces are simply output to the web client (the best situation in development) or thrown back to the caller to be handled more gracefully (the best situation in production).

  • There is a flag that can be set to turn on a processing mode that is more backward-compatible with FreeMarker Classic. This is off by default, but you can set it via Template.setClassicCompatibility(true). What this does is that it allows scalars to be treated as a single-item list in a list directive. Also, it allows somewhat more looseness about types. In FreeMarker 1.x, <#if x=="1"> and <#if x==1> were in fact equivalent. This meant that legacy templates might tend to be slack about this. If classic compatibility is not set, an attempt to compare the string "1" with the number 1 will result in an exception being thrown. (Note that it is preferable to get your templates working without the backward compatibility flag, since it usually will require only minor changes. However, for people with a lot of templates and no time to check over them, this flag may be of use.)