2.3.20 - 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.20

Date of release: 2013-06-27

If you are IDE/tools author, note these changes.

## Changes on the FTL side

- Error message quality improvements:

  - Many error messages are now more helpful, especially for users who are not experienced with FreeMarker. For example, some of the most common user mistakes are recognized and tips are shown to fix them, reducing support costs or the time employees spend to figure them out.

  - It's now ensured that the error location in the template is included in the message returned by `TemplateException.getMessage()`. The stack trace always showed this information anyway, but some users only see the "message", not the stack trace, and that often didn't contained the location.

  - The template language part of the stack trace is now more detailed, and easier to understand. This is especially helpful in applications that use a complex library of macros and functions.

  - Several smaller bugs were fixed that made the error information wrong or lacking.

  - The layout of the error messages is now more consistent, and generally easier to read.

- Changes regarding boolean to string conversions and formatting:

  - `?c` (computer-language formatting) now works with booleans too, always giving `"true"` or `"false"` regardless of the `boolean_format`. This way it's safe for generating JavaScript in a context where human-readable text is also rendered.

  - If the `boolean_format` setting is set to anything but the default `"true,false"` value, boolean values will be automatically converted to string where a string value is expected by the template language, instead of giving an error. This helps you spare those`?string`-s after boolean values. This is the same logic as with numbers and dates, which were always automatically converted to string, according the corresponding format setting. Except, the provided default boolean format is useless for automatic conversion (but it's still there for `?string`, for backward compatibility), hence it must be set manually. (We certainly couldn't come up with a sensible default anyway, as for booleans it depends too much on the application, not to mention the localisation issues.)

    Exactly like with numbers and dates, automatic conversion doesn't happen in these cases:

    - Comparisons, i.e., `someBoolean == 'true'` is still an error

    - Method calls where the declared type of the parameter is `String` but the actual value is a boolean; still an error

    - When the boolean value is used as key in `expr[key]`, it's still an error (there was no automatic conversion there for other types either, as numerical and string keys have different meaning)

    - The opposite direction, i.e., string to boolean conversion; won't happen

- New built-ins for numbers: `abs`, `is_nan`, `is_infinite`. Like `n?abs` will give the absolute value of `n`.

- New built-in for sequences: `join`. Like `[1, 2, 3]?join(", ")` will give the string `"1, 2, 3"`.

- If you set the `incompatible_improvements` setting (see here) to `2.3.20` or higher, `?html` will escape apostrophe-quotes just like `?xhtml` does. Utilizing this is highly recommended, because otherwise if interpolations are used inside attribute values that use apostrophe-quotation (`<foo bar='${val}'>`) instead of plain quotation mark (`<foo bar="${val}">`), they might produce HTML/XML that's not well-formed. Note that `?html` didn't do this because long ago there was no cross-browser way of doing this, but it's not a real concern anymore. Also note that this will be the default behavior starting from 2.4.

- Bug fix [390] (and other improvements): `?js_string` and `?json_string` didn't escape the `u2028`-`u2029` line terminators (problem for JavaScript) and the `u007F`-`u009F` control characters (maybe a problem in JSON, depending on implementation). Furthermore, the escaping of `\`, `<`, and `>` become safer in that now they are escaped whenever it can't be guaranteed that they won't be part of `<!`, `]]>` or `</`. Earlier they were only escaped when it was known that they are part of these patterns, thus it was possible to assemble these patterns from two adjacent interpolations. Additionally, from now on `<?` and `-->` also count as dangerous patterns, and will trigger `<` and `>` escaping.

- Bug fixed: The following string built-ins didn't coerce the numerical, date (and now the boolean) left-values to string, instead they threw a type error: contains, `index_of`, `last_index_of`, `left_pad`, `right_pad`, `matches`, `replace`, `split`, `new`. The other string built-ins already did this conversion for a long time; this was an accidental inconsistency.

- Bug fixed: With the default arithmetic engine, it's now supported to compare infinite (positive or negative) with 0, to decide its sign.

## Changes on the Java side

- `BeansWrapper` introspection cache improvements:

  - Added public API to `BeansWrapper` for clearing the class cache: `clearClassIntrospecitonCache()`, `removeFromClassIntrospectionCache(Class)`

  - Significantly improved multi-core performance:

    - Uses `ConcurrentHashMap` when running on Java 5 or later.

    - The cache won't block readers while introspecting a class after a cache miss

    - If multiple threads need to introspect the same class that's not in the cache yet, only one of them will do it, the others will wait for its results.

  - Bug fix [361]: There was a small chance of deadlock when class-reloading was detected. Locking was redesigned to prevent such oversights in the future.

  - The internal package-visible `freemarker.ext.beans` API was slightly changed as the result of internal cleanup. Nobody but the FreeMarker developers should define classes in that package, so it shouldn't break anything. But if somebody did some in-house hacks there, re-compile to see if it still works.

- Nameless templates (those directly created with `new Template(null, ...)` instead of loaded through `Configuration`) couldn't include or import other templates, and thrown a `NullPointerException` when they tried to. Now they resolve relative paths as if they were in the template root directory.

- Bug fix: Regular expression built-ins and some logger libraries (most importantly Log4J) were unavailable on the Google App Engine platform. This fix is only present in the GAE-compatible build, 2.3.20-gae.

- Added new method to `Configuration`: `CacheStorage getCacheStorage()`

- Added new methods to `Environment` to make comparisons among `TemplateModel`-s according the rules of the template language operators: `applyEqualsOperator`, `applyEqualsOperatorLenient`, `applyLessThanOperator`, `applyLessThanOrEqualsOperator`, `applyGreaterThanOperator`, `applyWithGreaterThanOrEqualsOperator`

- Added new method, `Environment.isInAttemptBlock()` to check if we are within an `#attempt` block. This can be useful for `TemplateExceptionHandler`-s, as then they don't need to print the error to the output since `#attempt` will roll it back anyway. This is already utilized by the built-in `TemplateExceptionHandler`-s (`DEBUG_HANDLER` and `HTML_DEBUG_HANDLER`).

- Added convenience constructor `Template(String name, String sourceCode, Configuration cfg)`.

- `TemplateException`-s and `TemplateModelExcepton`-s now can have `Throwable` cause, not just `Exception` (it was an old oversight that somehow wasn't fixed so far).

- Parsing error messages under the JBoss Tools FreeMarker IDE now doesn't contain the usual location line, so that the actual error description is immediately visible in the Eclipse "Problems" view. (It's a "hack" in FreeMarler itself; it tries to detect if it runs under the plugin and then changes its behavior.)

- Mostly concerning tool (like IDE plugin) authors:

  - The error message formats (what `Throwable.getMessage()` returns) were heavily changed for `TemplateException`-s, and somewhat for `ParseException`-s. It's unlikely that anybody depends on these, but if you tried to parse these messages, be aware of this.

  - Fixed bug where `ParseException` has contained 0 as line and column number for lexical errors. Now it contains the correct information.

  - Added `ParseException.getEditorMessage()`: As in IDE-s the error markers show the error location to the user already, the location should not be repeated in the error message. So in IDE-s you should use this method instead of `getMessage()`. (Under JBoss Tools: FreeMarker now tries to detect that it runs under the plugin, and then it already does this, except that it still shows the column number as that's missing from the error marker location.)

  - Added `ParseException.getTemplateName()`

  - Added `Configuration.getSupportedBuiltInNames()`. As new built-ins (`expr?builtin_name`) are very often added to new FreeMarker versions, auto-completion or syntax highlighting should use this set instead of a fixed set of a names.

  - The format returned by `TemplateElement.getDescription()` was heavily changed. It's what FTL stack traces and maybe some outline views (tree-views) show. It was always for human reading (and till now was too inconsistent for anything else), so it's unlikely that this breaks anything.

  - There were some smaller changes in `freemarker.debug`, and it's expected that there will be more, so it was marked as experimental. As far as we know, nobody used it, so it shouldn't break anything.

- In experimental status only, but `freemarker.jar` is now an OSGi bundle (see `freemarker.jar/META-INF/MANIFEST.MF`). Depending on user feedback, the bundle description may change in the future. So please give feedback, especially if you are an OSGi expert!

- Improved the HTML generated by `HTML_DEBUG_HANDLER` (the red-on-yellow-background error message). Most importantly, now it will word-wrap. Other changes are minor, like now it can break out of CDATA sections, or now it has less intense colors.

- New `Template` method, `getActualTagSyntax()`: Tells if the template is using traditional or square-bracket syntax. As the syntax can be overridden in the template, also it's possibly decided by auto-detection, it wasn't trivial to it tell till now.

- Added some utility methods that are useful for generating error messages in custom directives: `ClassUtil.getFTLTypeDescription(TemplateModel)`, `getShortClassName`, `getShortClassNameOfObject`

- Bug fix [364]: `freemarker.template.EmptyMap` (which is passed to `TemplateDirectiveModel`-s if there are no parameters) now allows `remove(key)`, `clear()` and `putAll(anyEmptyMap)` as these do nothing anyway.

- Bug fix [375]: `NullPointerException` on IBM J9 VM (not on the Sun/Oracle implementation) in `BeansWrapper` when the Java implementation legally returns `null` for some `BeanInfo` getters.

- Bug fix: Cloning a `Configuration` didn't deep-clone the data structures storing the `auto_imports` and `auto_includes` settings, hence possibly leading to aliasing problems.

- Bug fix [377]: After a failed method call the exception handler could fail in the rare occasion when `targetObject.toString()` fails, raising a runtime exception that not even the `attempt` directive will catch.

- Bug fix [391]: If a template name has contained `*` that was not the only character in the path step, it threw `NegativeArraySizeException` instead of `FileNotFoundException`.

- With the default arithmetic engine, performance optimizations of comparison operations when some of the numbers is 0, and when the sign of the numbers differ.

- Some smaller fixes in `TemplateElement.getCanonicalForm()`, also some quality improvements there.

- Bug fixes in `classic_compatible` mode (this mode is to help migrating from FreeMarker 1), thanks to Information Mosaic:

  - When a macro was called with a `null`/missing parameter value, it has caused error like in FreeMarker 2.3

  - When a hash literal contained reference to a `null`/missing variable, like in `{ 'a': missingVar }`, it has caused an error like in 2.3

  - When a sequence literal contained reference to a `null`/missing variable, like in `[1, missingVar]`, it has caused an error like in 2.3

  - When a the left-side of the `.` (dot) or `[key]` operator was `null` or missing variable, like in `missingVar.subVar`, it has caused an error like in 2.3

  - When `BeanModel`-s are tried to be treated as strings, for most subclasses it has failed with type error, like in 2.3. In FreeMarker 1 all `BeanModel`-s were `TemplateScalarModel`-s, so it should succeed. The fix for this only works where FreeMarker coerces to string (string built-ins on the left-side and concatenation (`+`) and interpolation (`${...}`) do that), otherwise unfortunately it will still fail.

  - The `classic_compatible` setting now accepts value `2` along `true` (alias `1`) and `false` (alias `0`). `2` means `true` but with emulating bugs in early 2.x classic-compatibility mode. Currently this only affects how booleans are converted to string; with `1` it's always `"true"`/`""`, but with `2` it's `"true"/"false"` for values wrapped by `BeansWrapper` as then `Boolean.toString()` prevails. Note that `someBoolean?string` will always consistently format the boolean according the `boolean_format` setting, just like in FreeMarker 2.3.

- Bug fix [394]: When trying to access the optional Jython (or W3C DOM) classes has failed in `DefaultObjectWrapper` with an `Error`, rather than with an `Exception`, loading the `DefaultObjectWrapper` class itself has failed, instead of the Jython (or W3C DOM) support being disabled. From now in, it will survive any kind of `Throwable` there, and if the `Throwable` is not an `ClassNotFoundException`, it will also log the `Throwable`.

- Improved the performance of `(thisVarIsMissing.foo)!default` and similar parenthetical existence operators and existence built-ins in the case when the `null`/missing variable is not the last step inside the parenthesis. In that case it's about 30 times faster now, measured on Java 6. In other cases (when all variables exists, or the the last step is missing) the performance is about the same (relatively fast) as before.

- Added interface `freemarker.cache.CacheStorageWithGetSize` which allows querying the current number of cache entries in a `CacheStorage` that implements it. It's implemented by all out-of-the-box `CacheStorage` implementations. Also added `getStrongSize()` and `getSoftSize()` to `MRUCacheStorage`.

- Version and build information changes:

  - The form of the nightly build version numbers has changed to be Maven/JSR 277 compliant. What earlier was `2.3.19mod` is now something like `2.3.20-nightly_20130605T130506Z` (note how the last points to the target release version instead of the last release version).

  - The form of the Release Candidate and Preview version numbers where changed to be Maven/JSP 277 compliant: `2.4pre2` is now `2.4.0-pre02`, `2.4rc1` is now `2.4.0-rc01`.

  - Added new static method to `Configuration` to query build date: `getBuildDate()`. This is also printed by the main command line class.

- Various internal code cleanups.

## Other changes

- Many JavaDoc improvements, mostly in the documentation of the basic (most frequently used) classes.

- FreeMarker source code has moved to GitHub (https://github.com/freemarker/freemarker), other project resources has remained on sourceforge.net.

- Project structure cleanup, Ivy-based build script.

Previous Next