2.2 - 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.2

Date of release: 2003-03-27

This release introduces some really important new features. Unfortunately, evolution was painful again; we have a few non-backward compatible changes (see below). Also, for those of you awaiting desired native date/time type, sorry, it is still not here (because of some internal chaos in the team... stand by, it's coming).

## Non backward-compatible changes!

- Macros are now plain variables. This means that if you are unlucky and you have both a macro and another variable with the same name, now the variable will overwrite the macro, so your old template will malfunction. If you have a collection of common macros, you should use the new namespace feature to prevent accidental clashes with the variables used in the templates.

- With the introduction of the new namespace support, `global` and `assign` directives are no longer synonyms. `assign` creates a variable in the current `namespace`, while `global` creates variable that is visible from all namespaces (as if the variable would be in the data-model). Thus, the variable created with `assign` is more specific, and hides the variable of the same name created with `global`. As a result, if you use both `global` and `assign` mixed for the same variable in your templates, now they will malfunction. The solution is to search-and-replace all `global`s in your old templates with `assign`.

- The reserved hash `root` no longer exists as a predefined variable (we no longer have reserved variables). Use special variable expressions to achieve similar effects. However, we have no equivalent replacement for `root` because of the changes in the variable scopes caused by the introduction of namespaces. You may should use `.globals` or `.namespace`.

- The `BeansWrapper` no longer exposes native Java arrays, booleans, numbers, enumerations, iterators, and resource bundles as `TemplateScalarModel`. This way, number objects wrapped through `BeansWrapper` are subject to FreeMarker's number formatting machinery. Also, booleans can be formatted using the `?string` built-in.

- The signature of `Configuration.setServletContextForTemplateLoading` has been changed: the first parameter is now `Object` instead of `javax.servlet.ServletContext`. Thus, you have to recompile your classes that call this method. The change was required to prevent class-loading failure when `javax.servlet` classes are not available and you would not call this method.

- This release introduces a parse-time white-space remover that strips some of the typical superfluous white-space around FreeMarker tags and comments. This feature is on by default! Most probably this will not cause problems if you generate white-space neutral output like HTML. But if it does cause undesirable reformatting in output you generate, you can disable it with `config.setWhitespaceStripping(false)`. Also, you can enable/disable it on a per-template basis with the new `ftl` directive.

- Some new directives were introduced: `nested`, `import`, `escape`, `noescape`, `t`, `rt`, `lt`. This means that if you are unlucky and the text of your template contains something like `<nested>`, then that will be misinterpreted as a directive. To prevent this kind of problem in the future, we recommend everybody to switch from the old syntax to the new syntax ("strict syntax"). The strict syntax will be the the default syntax starting from some of the later releases anyway. We plan to release a conversion tool for converting old templates. For more information please read: Template Language Reference/Deprecated FTL constructs/Old FTL syntax

- The data-model created by the `FreemarkerServlet` now uses automatic scope discovery, so writing `Application.attrName`, `Session.attrName`, `Request.attrName` is no longer mandatory; it's enough to write `attrName` (for more information read this). This may break an old template if that rely on the non-existence of certain top-level variables.

- `FreemarkerServlet` now uses the encoding of the template file for the output, unless you specify the encoding in the `ContentType` init-param, such as `text/html; charset=UTF-8`.

- The format of template paths is now more restricted than before. The path must not use `/`, `./` and `../` and `://` with other meaning as they have in URL paths (or in UN*X paths). The characters `*` and `?` are reserved. Also, the template loader must not want paths starting with `/`. For more information please read: Programmer's Guide/The Configuration/Template loading

- Till now `TemplateTransformModel.getWriter` has received null as parameter map if the transform was called without parameters. From now, it will receive an empty Map instead. Note that the previous API documentation didn't state that it always receives null if there are no parameters, so hopelessly only very few classes exploit this design mistake.

## Changes in FTL (FreeMarker Template Language)

- User-defined directives: Transform and macro call syntax has been unified; they can be called in the same way, as user-defined directives. This also means that macros support named parameters and nested content (like the -- now deprecated -- `transform` directive did). For example, if you have a macro called `sect`, you may call it via `<@sect title="Blah" style="modern">Blah blah...</@sect>`. For more information read: Template Author's Guide/Miscellaneous/Defining your own directives

- Macros are now plain variables. This significantly simplifies FreeMarker semantics, while providing more flexibility; for example you can pass macros as parameters to other macros and transforms. As for the problem of clashing commonly-used-macro and variable names, we provide a more powerful solution: namespaces.

- Namespaces: Names-spaces are invaluable if you want to assemble collections ("libraries") of macros and transforms (and other variables), and then use them in any template without worrying about accidental name clashes with the application specific and temporary variables, or with the variables of other collections you want to use in the same template. This is extremely important if FreeMarker users want to share their macro/transform collections. For more information read: Template Author's Guide/Miscellaneous/Namespaces

- With the introduction of namespaces our variable related terminology changed. As a result, `assign` is no longer synonymous with `global`. The `assign` directive has been undeprecated, and should be used instead of `global` almost everywhere. In the new approach `assign` creates variables in the current namespace, while `global` creates a variable that is visible from all namespaces (as if the variable were in the root of the data-model). A variable created with `assign` in the current namespace hides the variable of the same name that was created with `global`.

- `ftl` directive: With this directive you can give information about the template for FreeMarker, like the encoding (charset) of the template, the used FTL syntax variant, etc. Also, this directive helps you to write templates that are less dependent on FreeMarker configuration settings, also it helps third-party tools to identify and correctly parse FreeMarker templates. For more information see: `ftl` directive

- White-space stripping: FreeMarker now automatically removes some of the typical superfluous white-spaces around FreeMarker tags and comments, like the indentation spaces before- and line-break after `<#if ...>` tags. For more information read: Template Author's Guide/Miscellaneous/White-space handling/White-space stripping

- New directive to apply a common ("escaping") expression to all interpolations in a block: `escape`. The name comes from the common usage of this directive for automatic HTML-escaping of interpolations.

- The new and preferred way of number formatting with `string` built-in is `foo?string(format)`, instead of the less natural `foo?string[format]`.

- The `string` built-in works for boolean values. For example: `${spamFilter?string("enabled", "disabled")}`. For more information read the reference.

- The default strings for outputting boolean value using the `string` built-in can be set using the `boolean_format` setting.

- Comments can be placed inside FTL tags and interpolations. For example: `<#assign <#-- a comment --> x = 3>`

- All letters and numbers are enabled in variable names, also `$` is allowed (as in Java programming language). Thus you can use accents, Arabic letters, Chinese letters, etc.

- String literals can be quoted with apostrophe-quote. `"foo"` and `'foo'` are equivalent.

- New string built-ins: `index_of`, `last_index_of`, `starts_with`, `ends_with`, `replace`, `split`, `chop_linebreak`, `uncap_first`.

- New sequence built-ins: `sort`, `sort_by`.

- New built-ins for experts to check the type of a variable. See: `is_...` built-ins

- New built-in for experts to create a variable of certain Java `TemplateModel` implementation. See: `new` built-in

- New built-in, `namespace`, to get the namespace of a macro.

- New expression type: special variable expression. To prevent backward compatibility problems when we introduce new predefined variables, from now special variable expressions are used to access them.

- New directives: `t`, `rt` and `lt` directives allow you to do explicit white-space removal in extreme FTL applications. For more information read the reference.

- `assign`, `local` and `global` now can capture the output generated be the nested template fragment into the variable. This deprecates `capture_output` transform. More information: assign directive reference

- Bulk assignments (as `<#assign x=1, y=2, z=3>`) no longer need colon to separate the assignments (as `<#assign x=1 y=2 z=3>`), although it is still allowed to preserve backward compatibility.

- Path that contains `//:` is considered as absolute path.

- `include` and `transform` directives no longer need a semicolon to separate the template or transform name from the parameter list, although it is still allowed to preserve backward compatibility.

- `#`-less tag syntax is deprecated (but still working). That is, you should write `<#directive ...>` instead of `<directive ...>`, and `</#directive ...>` instead of `</directive ...>`. For more info read: Template Language Reference/Deprecated FTL constructs/Old FTL syntax

- `foreach` is depreciated (but still working). Use `list` instead.

- Bugfix: Undefined variables in hash and sequence constructors (as `[a, b, c]`) didn't caused errors.

- Bugfix: String concatenation had performance problem if there was multiple concatenations chained, as: `"a"+x+"a"+x+"a"+x+"a"+x+"a"+x`.

## Changes on the Java side

- Arbitrary JSP custom tags can be used as FreeMarker transforms in `FreemarkerServlet`-driven templates. More information: Programmer's Guide/Miscellaneous/Using FreeMarker with servlets

- Various improvements for `BeansWrapper`:

  - The `BeansWrapper` no longer exposes arbitrary objects as `TemplateScalarModel`s, only `java.lang.String` and `Character` objects. This way, number objects wrapped through `BeansWrapper` are subject to FreeMarker's number formatting machinery. As a side effect, non-string and non-number objects that were previously accepted in equality and inequality operations (because they had a string representation) will now cause the engine to throw exception on comparison attempt.

  - `java.lang.Character` objects are exposed as scalars through `BeansWrapper`.

  - Experimental feature: With the `setSimpleMapWrapper` method of `BeansWrapper` you can configure it to wrap `java.util.Map`-s as `TemplateHashModelEx`-s, and do not expose the methods of the object.

- `TransformControl` interface (was experimental earlier): If the `Writer` returned by `TemplateTransformModel.getWriter` implements this interface, it can instruct the engine to skip or to repeat evaluation of the nested content, and gets notified about exceptions that are thrown during the nested content evaluation. Note that the `onStart` and `afterBody` methods now are allowed to throw `IOException`. For more information please read the API documentation.

- Localized lookup can be disabled with the new `Configuration` methods: `set/getLocalizedLookup`, `clearTemplateCache`

- The new interface `freemarker.cache.CacheStorage` allows users to plug custom template caching strategies with the `cache_storage` setting. The core package now ships with two implementations: `SoftCacheStorage` and `StrongCacheStorage`. For more information read: Programmer's Guide/The Configuration/Template loading

- You can set settings with string name and string value with the new `setSetting(String key, String value)` method of `Configurable` super-classes (as `Configuration`). Also you can load settings from `.properties` file with the `setSettings` method.

- Other new `Configuration` methods: `clearTemplateCache`, `clearSharedVariables`, `getTemplateLoader`, and `clone`.

- Changes to `TemplateTransformModel` interface: `getWriter` can throw `IOException`, and can return `null` if the transform does not support body content.

- Till now `TemplateTransformModel.getWriter` has received null as parameter map if the transform was called without parameters. From now, it will receive an empty Map instead. Note that the previous API documentation didn't state that it always receives null if there are no parameters, so hopelessly only very few classes exploit this design mistake.

- Various improvements for `FreemarkerServlet`:

  - The data-model now uses automatic scope discovery, so writing `Application.attrName`, `Session.attrName`, `Request.attrName` is no longer mandatory; it's enough to write `attrName`. For more information read this.

  - `FreemarkerServlet` now uses the encoding of the template file for the output, unless you specify the encoding in the `ContentType` init-param, such as `text/html; charset=UTF-8`.

  - All `Configuration` level settings can by set with Servlet init-params (`template_exception_handler`, `locale`, `number_format`, etc.).

  - The object wrapper the servlet internally uses is now set as the default object wrapper for its `Configuration` instance.

  - It no longer forces session creation for requests that don't belong to an existing session, improving scalability.

- JDOM independent XML-wrapping: `freemarker.ext.xml.NodeListModel` is a re-implementation of `freemarker.ext.jdom.NodeListModel` that does not rely on JDOM; you don't need JDOM .jar anymore. The new `NodeListModel` automatically uses W3C DOM, dom4j, or JDOM, depending on which library is available (that is, depending on what object do you pass to its constructor).

- Bugfix: `WebappTemplateLoader`: Template updating didn't worked correctly with Tomcat due the caching of resources. Now `WebappTemplateLoader` tries to access the resources directly as `File`, if it is possible, thus bypasses the caching.

- Various bug-fixes for `FreemarkerServlet`:

  - The servlet now loads the correct template if it was called through `RequestDispatcher.include`.

  - The caching of `HttpServletRequest` objects is now compliant with the servlet specification.

  - `TemplateException`s was suppressed in certain situations resulting in half-rendered pages without error message.

- Bugfix: FreeMarker didn't work if the `javax.servlet` classes was not available, because `Configuration` explicitly referred to `javax.servlet.ServletContext`.

- Bugfix: classes may were not found if they was available only in the `WEB-INF`, and FreeMarker tried to load the class dynamically.

- Bugfix: the `Template` constructor (and thus `Configuration.getTemplate`) sometimes threw `TokenMgrError` (a non-checked exception) instead of `ParseException`.

## Other changes

- The Web application related examples has been replaced.

## The history of the releases before the final version

### Differences between the final and RC2 releases

- You can load settings from `.properties` file with the `setSettings` method of `Configuration` and other `Configurable` subclasses.

- New string built-in: `uncap_first`

- Bugfix: When exposing an XML document to a template and accessing it with XPath using Jaxen a `ClassCastException` has occurred.

- Bugfix: The template cache has loaded templates with bad `Configuration` instance in certain situations if you use not the static default `Configuration` instance.

### Differences between the RC2 and RC1 releases

- Non backward compatible change!: `FreemarkerServlet` now uses the encoding of the template file for the output, unless you specify the encoding in the `ContentType` init-param, such as `text/html; charset=UTF-8`.

- Non backward compatible change compared to RC1!: The `capture_output` transform creates variable in the current namespace (as `assign` directive) with the `var` parameter, not a global variable.

- The new and preferred way of number formatting with `string` built-in is `foo?string(format)`, instead of the less natural `foo?string[format]`.

- The `string` built-in works for boolean values. For example: `${spamFilter?string("enabled", "disabled")}`. For more information read the reference.

- The default strings for outputting boolean value using the `string` built-in can be set using the `boolean_format` setting.

- String literals can be quoted with apostrophe-quote. `"foo"` and `'foo'` are equivalent.

- The new interface `freemarker.cache.CacheStorage` allows users to plug custom template caching strategies with the `cache_storage` setting. The core package now ships with two implementations: `SoftCacheStorage` and `StrongCacheStorage`. For more information read: Programmer's Guide/The Configuration/Template loading

- You can set settings with string name and string value with the new `setSetting(String key, String value)` method of `Configurable` super-classes (as `Configuration`).

- Other new `Configuration` methods: `getTemplateLoader`, `clone`.

- `assign`, `local` and `global` now can capture the output generated be the nested template fragment into the variable. This deprecates `capture_output` transform. More information: assign directive reference

- Other new `Configuration` methods: `getTemplateLoader`, `clone`.

- Changes to `TemplateTransformModel` interface: `getWriter` can throw `IOException`, and can return `null` if the transform does not support body content.

- Till now `TemplateTransformModel.getWriter` has received null as parameter map if the transform was called without parameters. From now, it will receive an empty Map instead. Note that the previous API documentation didn't state that it always receives null if there are no parameters, so hopelessly only very few classes exploit this design mistake.

- Changes to `TemplateControl` interface: `onStart` and `afterBody` methods are now allowed to throw `IOException`.

- Path that contains `//:` is considered as absolute path.

- New string built-ins: `index_of`, `last_index_of`, `starts_with`, `ends_with`, `replace`, `split`, `chop_linebreak`.

- New sequence built-ins: `sort`, `sort_by`.

- All `Configuration` level settings can by set with Servlet init-params (`template_exception_handler`, `locale`, `number_format`, etc.).

- Bugfix: classes may were not found if they was available only in the `WEB-INF`, and FreeMarker tried to load the class dynamically.

- Bugfix: `setLocalizedLookup(false)` of `Configuration` was overridden when you have called `setTemplateLoader`.

- Bugfix: String concatenation had performance problem if there was multiple concatenations chained, as: `"a"+x+"a"+x+"a"+x+"a"+x+"a"+x`.

- Bugfix: white-space stripping was not worked with tags spanning over multiple lines.

- Bugfix: Removing several dependencies on JDK 1.3, so FreeMarker can be build for JDK 1.2.2.

### Differences between the Preview 2 and RC1 releases

- `ftl` is now stricter, and does not allow custom parameters. To associate custom attributes to templates, we may add a new directive later, if there is a demand for it.

- `escape` directive does not affect numerical interpolations (`#{...}`) anymore, as it has caused errors with string escapes as `?html`.

- The `normalizeName` method of `freemarker.cache.TemplateLoader` has been removed, because it has caused too many complications. Instead, normalization happens on a single point in the `TempateCache`. In consequence, FreeMarker is now stricter about the format of template paths, as things like `/../` are interpreted by the core.

- Experimental feature: With the `setSimpleMapWrapper` method of `BeansWrapper` you can configure it to wrap `java.util.Map`-s as `TemplateHashModelEx`-s, and do not expose the methods of the object.

- New `Configuration` methods: `set/getLocalizedLookup`, `clearTemplateCache`, `clearSharedVariables`.

- More cleanups in the `Environment` API.

- Better JSP standard compliance: JSP page-scope variables are the global variables that were created in the template (not the variables of the data-model).

- JDOM independent XML-wrapping: `freemarker.ext.xml.NodeListModel` is a re-implementation of `freemarker.ext.jdom.NodeListModel` that does not rely on JDOM; you don't need JDOM .jar anymore. The new `NodeListModel` automatically uses W3C DOM, dom4j, or JDOM, depending on which library is available (that is, depending on what object do you pass to its constructor).

- Bugfix: `WebappTemplateLoader`: Template updating didn't worked correctly with Tomcat due the caching of resources. Now `WebappTemplateLoader` tries to access the resources directly as `File`, if it is possible, thus bypasses the caching.

- Bugfix: Templates loaded with `MultiTemplateLoader` subclasses was removed from the template cache after the template update delay has elapsed (5 seconds by default) even if the template file was unchanged. This can cause lot of extra load for a high-traffic server if you have many templates or if the template update delay was set to 0 second.

- Bugfix: Undefined variables in hash and sequence constructors (as `[a, b, c]`) didn't caused errors.

### Differences between the Preview 1 and Preview 2 releases

- All 16-bit Unicode letters and numbers are allowed in identifiers, as well as the `$` character (as in Java programming language). Thus you can use accented letters, Arabic letters, Chinese letters, etc. as identifiers in templates

- Macros now can create loop variables for the nested content. For more information read this.

- New directives: `t`, `rt` and `lt` directives allow you to do explicit white-space removal in extreme FTL applications. For more information read the reference.

- The syntax of assignment-with-namespace has changed from `<#assign foo=123 namespace=myLib>`) to `<#assign foo=123 in myLib>`, since the previous syntax was confusing because its similarity to a bulk-assignment.

- Bulk assignments (as `<#assign x=1, y=2, z=3>`) no longer need colon to separate the assignments (as `<#assign x=1 y=2 z=3>`), although it is still allowed to preserve backward compatibility.

- Positional parameter passing is supported for macro calls as shorthand form of normal named parameter passing. For more details read read the reference.

- New built-in, `namespace`, to get the namespace of the currently executing macro.

- `TransformControl` interface (was experimental earlier): If the `Writer` returned by `TemplateTransformModel.getWriter` implements this interface, it can instruct the engine to skip or to repeat evaluation of the nested content, and gets notified about exceptions that are thrown during the nested content evaluation. For more information please read the API documentation.

- Jython wrapper can now wrap arbitrary Java objects, not only `PyObject`-s. If an object is passed to the wrapper that is neither a `TemplateModel`, nor a `PyObject`, it is first coerced into a `PyObject` using Jython's own wrapping machinery, and then wrapped into a `TemplateModel` as any other `PyObject`.

- Some cleanups in the `Environment` API.

- The Web application related examples has been replaced.

- Bugfix: Templates loaded with `URLTemplateLoader` subclasses was removed from the template cache after the template update delay has elapsed (5 seconds by default) even if the template file was unchanged. This can cause lot of extra load for a high-traffic server if you have many templates or if the template update delay was set to 0 second.

- Bugfix: `FreeMarkerServlet` has thrown `ServletException` even if a debug `TemplateException` handler was in use (so you may got Error 500 page instead of debug information).

Previous Next