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
andassign
directives are no longer synonyms.assign
creates a variable in the currentnamespace
, whileglobal
creates variable that is visible from all namespaces (as if the variable would be in the data-model). Thus, the variable created withassign
is more specific, and hides the variable of the same name created withglobal
. As a result, if you use bothglobal
andassign
mixed for the same variable in your templates, now they will malfunction. The solution is to search-and-replace allglobal
s in your old templates withassign
. -
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 forroot
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 asTemplateScalarModel
. This way, number objects wrapped throughBeansWrapper
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 nowObject
instead ofjavax.servlet.ServletContext
. Thus, you have to recompile your classes that call this method. The change was required to prevent class-loading failure whenjavax.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 newftl
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: 模板语言参考 /废弃的 FTL 结构/老式 FTL 语法 -
The data-model created by the
FreemarkerServlet
now uses automatic scope discovery, so writingApplication.attrName
,Session.attrName
,Request.attrName
is no longer mandatory; it's enough to writeattrName
(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 theContentType
init-param, such astext/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: 程序开发指南/配置(Configuration)/模板加载 -
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 calledsect
, you may call it via<@sect title="Blah" style="modern">Blah blah...</@sect>
. For more information read: 模板开发指南/其它/自定义指令 -
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: 模板开发指南/其它/命名空间
-
With the introduction of namespaces our variable related terminology changed. As a result,
assign
is no longer synonymous withglobal
. Theassign
directive has been undeprecated, and should be used instead ofglobal
almost everywhere. In the new approachassign
creates variables in the current namespace, whileglobal
creates a variable that is visible from all namespaces (as if the variable were in the root of the data-model). A variable created withassign
in the current namespace hides the variable of the same name that was created withglobal
. -
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: 模板开发指南/其它/空白处理/剥离空白 -
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 isfoo?string(format)
, instead of the less naturalfoo?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 theboolean_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
andlt
directives allow you to do explicit white-space removal in extreme FTL applications. For more information read the reference. -
assign
,local
andglobal
now can capture the output generated be the nested template fragment into the variable. This deprecatescapture_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
andtransform
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: 模板语言参考 /废弃的 FTL 结构/老式 FTL 语法 -
foreach
is depreciated (but still working). Uselist
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: 程序开发指南/其它/在Servlet中使用FreeMarker -
Various improvements for
BeansWrapper
:-
The
BeansWrapper
no longer exposes arbitrary objects asTemplateScalarModel
s, onlyjava.lang.String
andCharacter
objects. This way, number objects wrapped throughBeansWrapper
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 throughBeansWrapper
. -
Experimental feature: With the
setSimpleMapWrapper
method ofBeansWrapper
you can configure it to wrapjava.util.Map
-s asTemplateHashModelEx
-s, and do not expose the methods of the object.
-
-
TransformControl
interface (was experimental earlier): If theWriter
returned byTemplateTransformModel.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 theonStart
andafterBody
methods now are allowed to throwIOException
. 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 thecache_storage
setting. The core package now ships with two implementations:SoftCacheStorage
andStrongCacheStorage
. For more information read: 程序开发指南/配置(Configuration)/模板加载 -
You can set settings with string name and string value with the new
setSetting(String key, String value)
method ofConfigurable
super-classes (asConfiguration
). Also you can load settings from.properties
file with thesetSettings
method. -
Other new
Configuration
methods:clearTemplateCache
,clearSharedVariables
,getTemplateLoader
, andclone
. -
Changes to
TemplateTransformModel
interface:getWriter
can throwIOException
, and can returnnull
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 writeattrName
. For more information read this. -
FreemarkerServlet
now uses the encoding of the template file for the output, unless you specify the encoding in theContentType
init-param, such astext/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 offreemarker.ext.jdom.NodeListModel
that does not rely on JDOM; you don't need JDOM .jar anymore. The newNodeListModel
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. NowWebappTemplateLoader
tries to access the resources directly asFile
, 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, becauseConfiguration
explicitly referred tojavax.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 thusConfiguration.getTemplate
) sometimes threwTokenMgrError
(a non-checked exception) instead ofParseException
.
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 thesetSettings
method ofConfiguration
and otherConfigurable
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 defaultConfiguration
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 theContentType
init-param, such astext/html; charset=UTF-8
. -
Non backward compatible change compared to RC1!: The
capture_output
transform creates variable in the current namespace (asassign
directive) with thevar
parameter, not a global variable. -
The new and preferred way of number formatting with
string
built-in isfoo?string(format)
, instead of the less naturalfoo?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 theboolean_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 thecache_storage
setting. The core package now ships with two implementations:SoftCacheStorage
andStrongCacheStorage
. For more information read: 程序开发指南/配置(Configuration)/模板加载 -
You can set settings with string name and string value with the new
setSetting(String key, String value)
method ofConfigurable
super-classes (asConfiguration
). -
Other new
Configuration
methods:getTemplateLoader
,clone
. -
assign
,local
andglobal
now can capture the output generated be the nested template fragment into the variable. This deprecatescapture_output
transform. More information: assign directive reference -
Other new
Configuration
methods:getTemplateLoader
,clone
. -
Changes to
TemplateTransformModel
interface:getWriter
can throwIOException
, and can returnnull
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
andafterBody
methods are now allowed to throwIOException
. -
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)
ofConfiguration
was overridden when you have calledsetTemplateLoader
. -
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 offreemarker.cache.TemplateLoader
has been removed, because it has caused too many complications. Instead, normalization happens on a single point in theTempateCache
. 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 ofBeansWrapper
you can configure it to wrapjava.util.Map
-s asTemplateHashModelEx
-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 offreemarker.ext.jdom.NodeListModel
that does not rely on JDOM; you don't need JDOM .jar anymore. The newNodeListModel
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. NowWebappTemplateLoader
tries to access the resources directly asFile
, 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
andlt
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 theWriter
returned byTemplateTransformModel.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 aTemplateModel
, nor aPyObject
, it is first coerced into aPyObject
using Jython's own wrapping machinery, and then wrapped into aTemplateModel
as any otherPyObject
. -
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 thrownServletException
even if a debugTemplateException
handler was in use (so you may got Error 500 page instead of debug information).