Date of release: 2015-07-05
Changes on the FTL side
-
Listing (
#list
) has received some specialized convenience features that target typical tasks people do again and again in templates.-
New
list
directive child directives. There areelse
anditems
to deal with special cases with 0-length lists, andsep
for inserting separators between items. For more details, see thelist
directive in the Reference. -
New built-ins that act on loop variables:
var?index
(deprecatesvar_index
),var?counter
(1-based index),var?has_next
(deprecatesvar_has_next
),var?is_first
,var?is_last
,var?item_parity
(returns"odd"
or"even"
),var?item_parity_cap
,var?item_cycle
(...)
, etc.
-
-
Added convenience assignment operators, which can be used in assignment directives (
#assign
,#global
and#local
currently) only:-
++
and--
: For example,<#assign counter++>
is equivalent to<#assign counter = counter + 1>
. -
+=
,-=
,*=
,/=
and%=
: For example,<#assign counter += 2>
is equivalent to<#assign counter = counter + 2>
.
-
-
Added the
then
built-in, which can be used like a ternary operator:someBoolean?then(whenTrue, whenFalse)
. Just like with the ternary operator of most other languages, only one of the parameter expressions will be evaluated. More details... -
Added the
switch
built-in, which can be used like an in-line (expression) switch-case-default statement:someValue?switch(case1, result1, case2, result2, ... caseN, resultN, defaultResult)
, wheredefaultResult
can be omitted (then it will be error if none of the cases matches). More details... -
Added camel case support for the identifiers that are part of the template language (user defined names aren't affected). For example, now
<#noEscape>${x?upperCase}</#noEscape>
or<#setting numberFormat="0.0">
or<#ftl stripText=true>
are valid. However, within the same template, FreeMarker will require you to use the same naming convention consistently for all identifiers that are part of the template language. It's also possible to enforce the same naming convention on all templates from Java viaConfiguration.setNamingConvention(int)
. It's certain that camel case will be the recommended convention starting from some future version, because the Java API-s users call from templates use that too. -
Added new special variables,
.current_template_name
and.main_template_name
. These deprecate.template_name
, which was always broken when it comes to macro calls. The new.current_template_name
always returns the name of the template that contains the reference to the special variable, and.main_template_name
always returns the name of the topmost template. -
Smaller error message improvements. Like, added tip in the error message for the frequent issue when
someMap[someNumber]
complains thatsomeMap
is not a sequence nor is coercible to string. -
Bug fixed, activated with setting
incompatible_improvements
to 2.3.23: There's a long existing parse-time rule that says that#break
, in the FTL source code itself, must occur nested inside a breakable directive, such as#list
or#switch
. This check could be circumvented with#macro
or#function
, like this:<#list 1..1 as x><#macro callMeLater><#break></#macro></#list><@callMeLater />
. After activating this fix, this will be caught as parse time error.
Changes on the Java side
-
Added
Configuration.setNamingConvention(int)
. By default FreeMarker will auto-detect the naming convention (legacy VS camel case) used for the identifiers that are part of the template language, for each template independently. This setting lets you enforce a naming convention instead. -
Configuration
(and in fact anyConfigurable
) setting names now can be written with camel case as well. For example, if you are configuring FreeMarker from properties file, you can havedefaultEncoding=utf-8
instead ofdefault_encoding=utf-8
. You can use the two naming conventions (camel case, and tradition snake case) mixed, andConfiguration.setNamingConvention(int)
does not influence this behavior. -
Added
Configuration.setTemplateUpdateDelayMilliseconds(long)
andConfiguration.getTemplateUpdateDelayMilliseconds()
. This deprecatessetTemplateUpdateDelay(int)
, which uses seconds resolution, hence going against Java conventions and often leading to misunderstandings. (Also that couldn't have a getter pair.) -
The
template_update_delay
setting, when specified as a string (as insidejava.util.Properties
), supports time units, like intemplate_update_delay=500 ms
. -
Added
Environment.getCurrentTemplate()
method, which return the currently executed template (as opposed to the main template). -
Added
WebappTemplateLoader.setAttemptFileAccess(boolean)
, which can be used to disable the legacy trick where we try to load templates through direct file access, so that template updating works without restarting. Disabling URL connection caches (someURLBasedTemplateLoader.setURLConnectionUsesCaches(false)
, which is also the default sinceincompatible_improvements
2.3.21) probably solves that on modern Servlet containers. -
In the
FreemarkerServlet
TemplatePath
init-param, paths (like/templates
) can have a?settings(...)
postfix, with which you can set the JavaBean properties of the resultingTemplateLoader
. For example:<param-value>/templates?settings(attemptFileAccess=false, URLConnectionUsesCaches=false)</param-value>
-
Added
FileTemplateLoader.setEmulateCaseSensitiveFileSystem(boolean)
. This is handy when you are developing on Windows but will deploy to a platform with case sensitive file system. The default isfalse
, andtrue
is only meant for development, not for production installations. The default can be overridden by setting theorg.freemarker.emulateCaseSensitiveFileSystem
system property totrue
. -
Bug fixed [424]:
WebappTemplateLoader
didn't find templates that are stored inWEB-INF/lib/*.jar/META-INF/resources
. Files under that directory are visible asServletContext
resources since Servlet 3.0, yetWebappTemplateLoader
has usually failed to see them because of some internal tricks. -
Bug fixed: If a template "file" was successfully opened for reading, but then there was an
IOException
during reading its content, the parser (JavaCC) acted like if the template "file" was ended there, and the exception was suppressed. It's actually a JavaCC quirk that affects many other JavaCC-based languages too, but now FreeMarker has added a workaround in theTemplate
constructor, and so now an exception will be thrown as expected. -
Bug fixed:
InvalidReferenceException.FAST_INSTANCE
could accidentally store reference to anEnvironment
instance, which hence was never garbage collected. -
Bug fixed [426]: When setting
incompatible_improvements
to 2.3.22, the special variable reference.template_name
in templates always returns the name of the main (topmost) template, due to an oversight in 2.3.22. Settingincompatible_improvements
to 2.3.23 restores the old, backward compatible behavior. (Note that the old behavior that we emulate is itself broken, as it doesn't work well with macro calls; you should use.current_template_name
or.main_template_name
instead.) -
Bug fixed [53]: Template parsing was abnormally slow for templates with very high number AST (abstract syntax tree) nodes on the same hierarchy level.
-
Bug fixed: When the template was concurrently replaced on the backing store during its first loading was still ongoing, the older version of the template could get into the cache with the time stamp of the new version, hence it wasn't reloaded after the configured update delay.
-
Bug fixed: The
log_template_exceptions
setting (added in 2.3.22) couldn't be set through theConfigurable.setSetting(String, String)
API. -
Bug fixed:
StringUtil.FTLStringLiteralEnc
has escaped$
(hence generating an illegal escape) and haven't escaped{
after$
and#
. While this function is only used for generating error messages by FreeMarker, it's a public methods so anyone could use it. -
Bugs fixed: Various canonical form glitches (they only affect error messages as far as FreeMarker is concerned).
Other changes
-
Modernized Manual and site design with improved functionality (always visible navigation tree, search inside the Manual, etc.), thanks to Evangelia Dendramis. (Also now the Site uses the same format and HTML generator as the Manual.)
-
Many smaller Manual and site content updates/improvements.
Notes
Changes compared to 2.3.23 RC1:
-
.current_name_name
and.main_template_name
is now missing (null
) instead of""
if the template has no name -
Some minor error message improvements
-
Documentation refinements