2.3.28 - 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.28

Release date: 2018-04-04

## Changes on the FTL side

- Added new special variable, `get_optional_template` (FREEMARKER-84). It can be used when you need to include or import a template that's possibly missing, and you need to handle that case on some special way. See the details here...

- Added new special variable, `caller_template_name` (FREEMARKER-83), which returns the name (path) of the template from which the current macro or function was called. It's mostly useful if you want to resolve paths relative to the caller template.

- Added new built-in, `templateName?absolute_template_name` or `templateName?absolute_template_name(baseName)`, which can be used to convert a relative template name to an absolute template name. See more here...

- Added new built-ins: `sequence?min` and `sequence?max` (FREEMARKER-86), which return the smallest and greatest item from a list of numbers or date/time/date-times. See more here...

- The template language can now be configured to use `[=expression]` instead of `${expression}` and `#{expression}`, which is very useful if you have a lot of `${...}` or `#{...}` in the text that you are generating, and so they should be static text. See more about the square bracket interpolation syntax here. The template language can also be configured to only use `${expression}`, and treat `#{expression}` as static text. (See the `interpolation_syntax` configuration setting, or the `Configuration.setInterpolationSyntax(int)` method.)

- In string literals, `\=` is now a valid escape sequence, resulting in a `=`. This is useful when you are using the new `[=exp]` interpolation syntax, which can be escaped in a string literal like `"Literal [\=x]"`.

- Bug fixed (FREEMARKER-83); this fix is only active when `incomplatible_improvements` is set to 2.3.28 (or higher). When calling a macro or function (things defined in a template, not directly in Java) and the argument list contains `.current_template_name`, now it will correctly evaluate to the template that contains the call, rather than to the template that contains the macro or function definition. (Of course, the parameter default value expression is still evaluated in the context of the called macro or function.)

- Bug fixed: When `string?split(separator)` is called with `""` as the argument, the string will be split to characters now. Earlier it has thrown an `IllegalArgumentException` (unless the `r` flag was specified).

## Changes on the Java side

- Added new `ParserConfiguration` (such as `Configuration` and `TemplateConfiguration`) setting, `interpolation_syntax`. It has 3 possible values:

  - `legacy` (the default): Interpolations look like `${...}` or `#{...}`. Note that `#{...}` is deprecated for a long time now.

  - `dollar`: Interpolations look like `${...}`. With this syntax, `#{...}` will be just static text.

  - `square_bracket`: Interpolations look like `[=...]`. With this syntax `${...}` and `#{...}` will be just static text. So it's useful if you generate output in a format where those (typically `${...}`) are already used, such as to generate JSP pages, or to generate FreeMarker templates that use the default syntax.

- When specifying the `output_format` configuration setting with `String`-`String` key-value pairs (like with `Configuration.setSetting(String, String)` or in a `.properties` file), it's now possible to specify the standard output formats by short name (like `output_format=HTML`) rather than by class name. (Custom formats still has to be referred by class name, as FreeMarker can't discover what their names are, since it's not aware of the custom classes.)

- Added a new `Configuration.removeTemplateFromCache` overload that has a `Object customLookupCondition` parameter. This is useful to manually evacuate a template from the cache that was get with a non-`null` custom lookup condition.

- Added new property to `BeansWrapper.MethodAppearanceDecision`: `replaceExistingProperty`. This is useful when a method like `size()` is exposed as a JavaBean property via `MethodAppearanceDecision.exposeAsProperty`, but there's also a "real" JavaBean property (like `getSize()`) with identical name. By default the real property isn't replaced, but now with `replaceExistingProperty` it can be.

- `DirectiveCallPlace` now has a `Template getTemplate()` method, so you can query if from which template was your `TemplateDirectiveModel` called. (This has similar role as `.caller_template_name` for macros/functions.)

- Added `Environment.rootBasedToAbsoluteTemplateName(String)`, which converts the root based names typically used for the FreeMarker Java API-s (such as `Configuration.getTemplate(name)`) to an absolute path, which can be safely passed to `<#include path>` and such, as it won't be misinterpreted to be relative to the directory of the template.

- Fixes in exception handling when calling JSP tags:

  - Bug fixed (FREEMARKER-88): If a `TemplateException` that's not a `TemplateModelExceptoin` has occurred in the body (nested content) of a JSP `SimpleTag` (typically, an `InvalidReferenceException`), that has caused a `ClassCastException` in the exception handling code, thus the template processing has thrown that instead of the original exception.

  - Bug fixed: For JSP Tag based custom tags, if an exception has occurred in the body (nested content), an `IndexOutOfBoundsException` might have occurred, replacing the original exception.

  - Wrapping of non-`TemplateModelException` `TemplateException`-s (typically `InvalidReferenceException`-s) into `TemplateModelException`-s is now avoided when the `TemplateException` occurs in the body of a JSP tag.

- The default arithmetic engine (`ArithmeticEngine.BIGDECIMAL_ENGINE`) can now compare infinite (both positive and negative) to any other standard numerical type. Earlier, since `BigDecimal` can't represent infinite, it was only working in certain special cases. Also there were some performance optimizations to slightly decrease the impact and number of conversions to `BigDecimal`.

- Avoided possible performance bottleneck when executing templates on many threads, caused by that `java.beans.PropertyDescriptor.getReadMethod()` is synchronized (FREEMARKER-80).

- Added `TemplateModelUtils.getKeyValuePairIterator(TemplateHashModelEx)` static utility class, which can be used to get a `TemplateHashModelEx2.KeyValuePairIterator` even for a non-`TemplateHashModelEx2` object. This simplifies Java code that iterates through key-value pairs.

- `freemarker.template.utility.DeepUnwrap` (a rarely used utility) now utilizes when the unwrapped `TemplateModel` implements `TemplateHashModelEx2.getKeyValuePairIterator()`, and thus can unwrap such a hash value even if it has non-string keys. Also, it nows keeps the iteration order of the hashes, as it unwraps into a `LinkedHashMap` instead of into a plain `HashMap`.

- `freemarker.ext.beans.HashAdapter.size()` was overridden for better performance.

- When the `incompatible_improvements` setting is set to 2.3.28 (or greater): Fixed legacy parser glitch where a tag can be closed with an illegal `]` (when it's not part of an expression) despite that the tag syntax is set to angle brackets. For example `<#if x]` worked just like `<#if x>`. Note that this legacy glitch didn't affect the legal usage of `]`, like `<#if x[0]>` has always worked correctly.

- Fixed parser bug that disallowed using `>` as the top-level expression inside an interpolation (`${...}`). It had the same reason why `<#if x > y>` doesn't work as naively expected, but there's no real ambiguity in `${x > y}`, so now it's allowed. Note that `${(x > y)?c}` and `${(x > y)?string('y', 'n')}`, which are how booleans are commonly printed, have always worked, as the `>` operation is not on the top-level inside the interpolation.

- Fixed incorrect listing of valid `roundingMode`-s in extended Java decimal format parsing error message

## Other changes

- FreeMarker has graduated from the Apache Incubator (as of 2018-03-21), and now is a normal top-level project at Apache. Therefore, the version number doesn't contain "-incubating" anymore.

Previous Next