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 theboolean_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
. Liken?abs
will give the absolute value ofn
. -
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 to2.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 theu2028
-u2029
line terminators (problem for JavaScript) and theu007F
-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 throughConfiguration
) couldn't include or import other templates, and thrown aNullPointerException
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 amongTemplateModel
-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 forTemplateExceptionHandler
-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-inTemplateExceptionHandler
-s (DEBUG_HANDLER
andHTML_DEBUG_HANDLER
). -
Added convenience constructor
Template(String name, String sourceCode, Configuration cfg)
. -
TemplateException
-s andTemplateModelExcepton
-s now can haveThrowable
cause, not justException
(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 forTemplateException
-s, and somewhat forParseException
-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 ofgetMessage()
. (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 (seefreemarker.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 toTemplateDirectiveModel
-s if there are no parameters) now allowsremove(key)
,clear()
andputAll(anyEmptyMap)
as these do nothing anyway. -
Bug fix [375]:
NullPointerException
on IBM J9 VM (not on the Sun/Oracle implementation) inBeansWrapper
when the Java implementation legally returnsnull
for someBeanInfo
getters. -
Bug fix: Cloning a
Configuration
didn't deep-clone the data structures storing theauto_imports
andauto_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 theattempt
directive will catch. -
Bug fix [391]: If a template name has contained
*
that was not the only character in the path step, it threwNegativeArraySizeException
instead ofFileNotFoundException
. -
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 wasnull
or missing variable, like inmissingVar.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 allBeanModel
-s wereTemplateScalarModel
-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 value2
alongtrue
(alias1
) andfalse
(alias0
).2
meanstrue
but with emulating bugs in early 2.x classic-compatibility mode. Currently this only affects how booleans are converted to string; with1
it's always"true"
/""
, but with2
it's"true"/"false"
for values wrapped byBeansWrapper
as thenBoolean.toString()
prevails. Note thatsomeBoolean?string
will always consistently format the boolean according theboolean_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 anError
, rather than with anException
, loading theDefaultObjectWrapper
class itself has failed, instead of the Jython (or W3C DOM) support being disabled. From now in, it will survive any kind ofThrowable
there, and if theThrowable
is not anClassNotFoundException
, it will also log theThrowable
. -
Improved the performance of
(thisVarIsMissing.foo)!default
and similar parenthetical existence operators and existence built-ins in the case when thenull
/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 aCacheStorage
that implements it. It's implemented by all out-of-the-boxCacheStorage
implementations. Also addedgetStrongSize()
andgetSoftSize()
toMRUCacheStorage
. -
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 like2.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 now2.4.0-pre02
,2.4rc1
is now2.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.