2.3.29 - Apache FreeMarker Manual

Unsupported web browser - Use a modern browser to view this website!

- Home
- Manual
- Java API

- Contribute
- Report a Bug
- Download

Manual
Previous Next

# 2.3.29

Release date: 2019-08-17

## Changes on the FTL side

- Added new built-ins: `?filter(predicate)`, `?map(mapper)`, `?take_while(predicate)`, `?drop_while(predicate)`. These allow using lambda expressions, like `users?filter(user -> user.superuser)` or `users?map(user -> user.name)`, or accept a function/method as parameter. Lambda expressions are also new in this release, but they can only be used in said built-ins, so they aren't like in Java for example, and also, unlike the similar Java methods, these built-ins aren't lazy in general, only in specific cases (see more here). The main goal of adding these built-ins was to allow conditionally skipping elements in the `list` directive without nested `if`-s that interfere with the `sep` directive, and the loop variable built-ins (see examples here).

- Added new built-ins for truncating text. `string?truncate(length)` truncates the text to the given length, and by default adds `[...]` at the end if truncation has happened. Truncation happens at word boundaries, unless the result is too short that way, in which case it falls back to truncation mid word. There's also `?truncate_w` to force Word Boundary truncation, and `?truncate_c` (for Character Boundary) that doesn't care about word boundaries. The truncation algorithm is pluggable in the FreeMarker configuration. See the reference for more details.

- `?sequence` now collaborates with `seq?size`, `seq[index]`, `seq[range]`, and with some other built-ins (`filter`, `map`, `join`, etc.) to spare collecting all the elements into the memory when possible. For example `anIterator?sequence[1]` will now just fetch the first 2 items, while earlier it has built a sequence that contains all the elements, only to get the 2nd element from that. Or, `anIterator?sequence?size` will now just count the elements, without collecting them into the memory. See the reference for more details.

- Extended decimal format parameter "multiplier" was incorrectly written as "multipier". Now both words are recognized.

- `?min` and `?max` will now immediately stop with error when applied on a right unbounded numerical range (like `1..`), as that would run forever anyway.

## Changes on the Java side

- FREEMARKER-109: In JSP TLD-s, line breaks inside function parameter lists have caused `IllegalArgumentException` "Invalid function signature".

- FREEMARKER-104: More helpful log and error messages (especially, no `NullPointerException` cause exception logged during FreeMarker XPath support initialization) if no XPath implementation is available because Java 9 modules don't allow accessing the internal Xalan that's stored under `com.sun` packages. (The messages now recommend adding Apache Xalan or Jaxen as dependency if you need XPath support.)

- The `boolean_format` configuration setting now can be set to `"c"`. Then `${aBoolean}` will behave as `${aBoolean?c}`. This should only be used if you are generating output for non-human (computer) consumption only. If your output has pieces for human audience too, it's still recommended to use `${aBoolean?c}` where `true`/`false` output is needed, and either not set the `boolean_format` at all, or set it to something that's appropriate for everyday users (like `"yes,no"`).

- New configuration setting, `fallback_on_null_loop_variable`: Specifies the behavior when reading a loop variable (like `i` in `<#list items as i>`, or in `<@myMacro items; i>`) that's `null` (missing); if `true`, FreeMarker will look for a variable with the same name in higher variable scopes, or if `false` the variable will be simply `null` (missing). For backward compatibility the default is `true`. The recommended value for new projects is `false`, as otherwise adding new variables to higher scopes (typically to the data-model) can unintentionally change the behavior of templates.

- If the result of `seq?size` is compared to an integer literal in a template, like in `seq?size != 0`, or `seq?size < 1`, and to decide the answer it's enough to know if `seq` is empty or not (i.e., the exact size isn't needed), and `seq` implements `TemplateCollectionModelEx`, FreeMarker will call `TemplateCollectionModelEx.isEmpty()` instead of `size()`. Furthermore, if `seq` is the result of `?filter`, or of a similar built-ins that can provide lazily generated result, it will do counting to figure out the size (rather than constructing the whole sequence in memory), and will limit how far it counts based on what literal the result of `?size` is compared with.

- Added `TemplateModelUtils.wrapAsHashUnion(ObjectWrapper, List<?>)` and `wrapAsHashUnion(ObjectWrapper, Object...)`, which is useful when you want to compose the data-model from multiple objects in a way so that their entries (`Map` key-value pairs, bean properties, etc.) appear together on the top level of the data-model.

- `HTMLOutputFormat`, `XMLOutputFormat`, `XHTMLOutputFormat` aren't final classes anymore, furthermore `XHTMLOutputFormat` now extends `XMLOutputFormat`. Same applies to the respective `TemplateOutputModel`-s (`TemplateHTMLOutputModel` is not final anymore, etc.). This allows defining new custom markup output format classes that will work with program logic that's only prepared for the standard markup output formats, because `instanceof SomeStandardOutputFromat` will return `true` for them.

- When configuring FreeMarker with string values (like with a `.properties` file), in the settings that support the "object builder" syntax, now you can create a `TemplateMarkupOutputModel` value with the new `markup` function, like `markup(HTMLOutputFormat(), "<p>Example</p>")`.

- `BeansWrapper.clearClassIntrospecitonCache` was deprecated as there's a typo in the method name; use `clearClassIntrospectionCache` instead.

Previous Next