blob: a934e2fd4b3cfc7424fd7e2290538c77cb707d81 [file] [log] [blame]
<!doctype html>
<!-- Generated by FreeMarker/Docgen from DocBook -->
<html lang="en" class="page-type-section">
<head prefix="og: http://ogp.me/ns#">
<meta charset="utf-8">
<title>2.3.21 - Apache FreeMarker Manual</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="format-detection" content="telephone=no">
<meta property="og:site_name" content="Apache FreeMarker Manual">
<meta property="og:title" content="2.3.21">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="https://freemarker.apache.org/docs/versions_2_3_21.html">
<link rel="canonical" href="https://freemarker.apache.org/docs/versions_2_3_21.html">
<link rel="icon" href="favicon.png" type="image/png">
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:500,700,400,300|Droid+Sans+Mono">
<link rel="stylesheet" type="text/css" href="docgen-resources/docgen.min.css?1707770044859">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/cookie-bar/cookiebar-latest.min.js"></script>
</head>
<body itemscope itemtype="https://schema.org/Code">
<meta itemprop="url" content="https://freemarker.apache.org/docs/">
<meta itemprop="name" content="Apache FreeMarker Manual">
<!--[if lte IE 9]>
<div class="oldBrowserWarning" style="display: block">
Unsupported web browser - Use a modern browser to view this website!
</div>
<![endif]--> <div class="oldBrowserWarning">
Unsupported web browser - Use a modern browser to view this website!
</div>
<div class="header-top-bg"><div class="site-width header-top"><div id="hamburger-menu" role="button"></div> <div class="logo">
<a href="https://freemarker.apache.org" role="banner"><img itemprop="image" src="logo.png" alt="FreeMarker"></a> </div>
<ul class="tabs"><li><a href="https://freemarker.apache.org/">Home</a></li><li class="current"><a href="index.html">Manual</a></li><li><a class="external" href="api/index.html">Java API</a></li></ul><ul class="secondary-tabs"><li><a class="tab icon-heart" href="https://freemarker.apache.org/contribute.html" title="Contribute"><span>Contribute</span></a></li><li><a class="tab icon-bug" href="https://issues.apache.org/jira/projects/FREEMARKER" title="Report a Bug"><span>Report a Bug</span></a></li><li><a class="tab icon-download" href="https://freemarker.apache.org/freemarkerdownload.html" title="Download"><span>Download</span></a></li></ul></div></div><div class="header-bottom-bg"><div class="site-width search-row"><a href="index.html" class="navigation-header">Manual</a><div class="navigation-header"></div><form method="get" class="search-form" action="search-results.html"><fieldset><legend class="sr-only">Search form</legend><label for="search-field" class="sr-only">Search query</label><input id="search-field" name="q" type="search" class="search-input" placeholder="Search" spellcheck="false" autocorrect="off" autocomplete="off"><button type="submit" class="search-btn"><span class="sr-only">Search</span></button></fieldset></form></div><div class="site-width breadcrumb-row"> <div class="breadcrumbs">
<ul class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList"><li class="step-0" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="index.html"><span itemprop="name">Apache FreeMarker Manual</span></a></li><li class="step-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="app.html"><span itemprop="name">Appendixes</span></a></li><li class="step-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="app_versions.html"><span itemprop="name">Version history</span></a></li><li class="step-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="versions_2_3_21.html"><span itemprop="name">2.3.21</span></a></li></ul> </div>
<div class="bookmarks" title="Bookmarks"><span class="sr-only">Bookmarks:</span><ul><li><a href="alphaidx.html">Alpha. index</a></li><li><a href="gloss.html">Glossary</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions</a></li><li><a href="ref_builtins_alphaidx.html">?builtins</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_specvar.html">.spec_vars</a></li><li><a href="app_faq.html">FAQ</a></li></ul></div></div></div> <div class="main-content site-width">
<div class="content-wrapper">
<div id="table-of-contents-wrapper" class="col-left">
<script>var breadcrumb = ["Apache FreeMarker Manual","Appendixes","Version history","2.3.21"];</script>
<script src="toc.js?1707770044859"></script>
<script src="docgen-resources/main.min.js?1707770044859"></script>
</div>
<div class="col-right"><div class="page-content"><div class="page-title"><div class="pagers top"><a class="paging-arrow previous" href="versions_2_3_22.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_3_20.html"><span>Next</span></a></div><div class="title-wrapper">
<h1 class="content-header header-section1" id="versions_2_3_21" itemprop="headline">2.3.21</h1>
</div></div><div class="page-menu">
<div class="page-menu-title">Page Contents</div>
<ul><li><a class="page-menu-link" href="#autoid_179" data-menu-target="autoid_179">Changes on the FTL side</a></li><li><a class="page-menu-link" href="#autoid_180" data-menu-target="autoid_180">Changes on the Java side</a></li><li><a class="page-menu-link" href="#autoid_181" data-menu-target="autoid_181">Other changes</a></li></ul> </div><p>Date of release: 2014-10-12</p><p>Note that since 2.3.21 is designed to be fully backward
compatible with the previous 2.3.x releases, <em>some of the
improvements and fixes described below are only activated when you
specifically ask for 2.3.21 "incompatible
improvements"</em>, because they could, with very small
chance, break existing applications. If the dependent project is still
actively developed, allowing 2.3.21 &quot;incompatible improvements&quot; is
highly recommended. See <a href="pgui_config_incompatible_improvements.html#pgui_config_incompatible_improvements_how_to_set">how to set
"incomplatible improvements" here</a>.</p><p>Note that we have changed our proprietary BSD-style license to
Apache License, Version 2.0. See the <a href="app_license.html">new
license here</a>.</p><p>Note that the minimum required Java version was increased from
1.2 to 1.4.</p>
<h2 class="content-header header-section2" id="autoid_179">Changes on the FTL side</h2>
<ul>
<li>
<p>Improved ranges:</p>
<ul>
<li>
<p>Added ranges with exclusive end:
<code class="inline-code"><em class="code-color">start</em>..&lt;<em class="code-color">end</em></code>
(also can be written as
<code class="inline-code"><em class="code-color">start</em>..!<em class="code-color">end</em></code>).
<a href="dgui_template_exp.html#dgui_template_exp_direct_ranges">More...</a></p>
</li>
<li>
<p>Added length limited ranges:
<code class="inline-code"><em class="code-color">start</em>..*<em class="code-color">length</em></code>:
For example, <code class="inline-code">10..*4</code> gives <code class="inline-code">[10,
11, 12, 13]</code>, <code class="inline-code">10..*-4</code> gives
<code class="inline-code">[10, 9, 8, 7]</code>, and
<code class="inline-code">10..*0</code> gives <code class="inline-code">[]</code>. When
these kind of ranges are used for slicing, the slice will
end without error if the end of the sliced sequence or
string is reached before the specified range length was
reached. Thus, for example, to take the first 10 characters
from the string <code class="inline-code">s</code>, or less if
<code class="inline-code">s</code> is shorter than 10 characters, you can
use <code class="inline-code">s[0..*10]</code>. <a href="dgui_template_exp.html#dgui_template_exp_seqenceop_slice">More...</a></p>
</li>
<li>
<p>Square bracket now accepts range values from any
source, like <code class="inline-code">&lt;#assign r = 1..3&gt;
${&#39;foobar&#39;[r]}</code> will print
<code class="inline-code">&quot;oob&quot;</code>. Earlier it has only supported
ranges that were specified directly inside the square
brackets, like <code class="inline-code">&#39;foobar&#39;[1..3]</code>.</p>
</li>
<li>
<p>When slicing a sequence with a right-unbounded range,
it&#39;s now allowed to have a range start index that&#39;s one
higher than the last index of the sliced sequence. For
example, <code class="inline-code">[&#39;x&#39;, &#39;y&#39;][2..]</code> is not an error
anymore, but an empty sequence. (Of course, <code class="inline-code">[&#39;x&#39;,
&#39;y&#39;][3..]</code> is still an error.)</p>
</li>
<li>
<p><code class="inline-code"><em class="code-color">someString</em>?substring(<em class="code-color">from</em>,
<em class="code-color">toExclusive</em>)</code> and
<code class="inline-code"><em class="code-color">someString</em>?substring(<em class="code-color">from</em>)</code>
are now deprecated; use this slicing expression instead:
<code class="inline-code"><em class="code-color">someString</em>[<em class="code-color">from</em>..&lt;<em class="code-color">toExclusive</em>]</code>
and
<code class="inline-code"><em class="code-color">someString</em>[<em class="code-color">from</em>..]</code>.
A warning if you are processing XML: Since slicing
expressions work both for sequences and strings, and XML
nodes in FTL are typically both sequences and strings at the
same time, there the equivalent expression is
<code class="inline-code"><em class="code-color">someXmlNode</em>?string[<em class="code-color">from</em>..&lt;<em class="code-color">toExclusive</em>]</code>
and
<code class="inline-code"><em class="code-color">exp</em>?string[<em class="code-color">from</em>..]</code>,
because without the <code class="inline-code">?string</code> it would
slice the node sequence instead of the text value of the
node.</p>
</li>
<li>
<p>If the <code class="inline-code">incompatible_improvements</code> in
the FreeMarker configuration is set to at least 2.3.21,
right-unbounded ranges become readable (like
<code class="inline-code">#list</code>-able). Earlier they could only be
used for slicing, and behaved like empty sequences
otherwise.</p>
</li>
</ul>
</li>
<li>
<p>New built-in, <code class="inline-code">?url_path</code>: This is the
same as <a href="ref_builtins_string.html#ref_builtin_url">the
<code>url</code> built-in</a>, except that it doesn&#39;t
escape slash (<code class="inline-code">/</code>) characters. This meant to be
used for converting paths (like paths coming from the OS or some
content repository) that use slash (not backslash!) to a path
the can be inserted into the path part of an URL.</p>
</li>
<li>
<p>New built-ins for string manipulation:</p>
<ul>
<li>
<p><code class="inline-code"><em class="code-color">someString</em>?keep_before(<em class="code-color">substring</em>[,
<em class="code-color">flags</em>])</code>: <a href="ref_builtins_string.html#ref_builtin_keep_before">More...</a></p>
</li>
<li>
<p><code class="inline-code"><em class="code-color">someString</em>?keep_after(<em class="code-color">substring</em>[,
<em class="code-color">flags</em>])</code>: <a href="ref_builtins_string.html#ref_builtin_keep_after">More...</a></p>
</li>
<li>
<p><code class="inline-code"><em class="code-color">someString</em>?remove_beginning(<em class="code-color">substring</em>)</code>:
<a href="ref_builtins_string.html#ref_builtin_remove_beginning">More...</a></p>
</li>
<li>
<p><code class="inline-code"><em class="code-color">someString</em>?remove_ending(<em class="code-color">substring</em>)</code>:
<a href="ref_builtins_string.html#ref_builtin_remove_ending">More...</a></p>
</li>
<li>
<p><code class="inline-code"><em class="code-color">someString</em>?ensure_starts_with(<em class="code-color">substring</em>[,
<em class="code-color">substitution</em>[,
<em class="code-color">flags</em>]])</code>: <a href="ref_builtins_string.html#ref_builtin_ensure_starts_with">More...</a></p>
</li>
<li>
<p><code class="inline-code"><em class="code-color">someString</em>?ensure_ends_with(<em class="code-color">substring</em>)</code>:
<a href="ref_builtins_string.html#ref_builtin_ensure_ends_with">More...</a></p>
</li>
</ul>
</li>
<li>
<p><code class="inline-code"><em class="code-color">someString</em>?number</code>
now recognizes all XML Schema number formats, like
<code class="inline-code">NaN</code>, <code class="inline-code">INF</code>,
<code class="inline-code">-INF</code>, plus the Java-native formats
<code class="inline-code">Infinity</code> and
<code class="inline-code">-Infinity</code>.</p>
</li>
<li>
<p>If <code class="inline-code">incompatible_improvements</code> in the
FreeMarker configuration is set to at least 2.3.21,
<code class="inline-code"><em class="code-color">someNumber</em>?c</code> will
return <code class="inline-code">&quot;INF&quot;</code>, <code class="inline-code">&quot;-INF&quot;</code> and
<code class="inline-code">&quot;NaN&quot;</code> for positive/negative infinity and IEEE
floating point Not-a-Number, respectively. These are the XML
Schema compatible representations of these special values.
Earlier it has returned what
<code class="inline-code">java.text.DecimalFormat</code> did with US locale,
none of which was understood by any (common) computer
language.</p>
</li>
<li>
<p>New built-in:
<code class="inline-code"><em class="code-color">someString</em>?boolean</code>.
This is for example useful for converting &quot;true&quot; and &quot;false&quot;
strings coming from XML to real boolean values. <a href="ref_builtins_string.html#ref_builtin_boolean">More...</a></p>
</li>
<li>
<p>Date/time/date-time related changes:</p>
<ul>
<li>
<p>Added new kind of
<code class="inline-code">date_format</code>/<code class="inline-code">datetime_format</code>/<code class="inline-code">time_format</code>
setting values: XML Schema formats, starting with
<code class="inline-code">&quot;xs&quot;</code> and ISO 8601:2004 formats, starting
with <code class="inline-code">&quot;iso&quot;</code>. The format string can be
continued with various space (or <code class="inline-code">_</code>)
separated options, like <code class="inline-code">h</code> or
<code class="inline-code">m</code> or <code class="inline-code">s</code> or
<code class="inline-code">ms</code> for setting shown accuracy,
<code class="inline-code">nz</code> or <code class="inline-code">fz</code> for setting
time zone offset visibility, and <code class="inline-code">u</code> or,
<code class="inline-code">fu</code> for using UTC time zone . For example,
to use ISO 8601 with minute precision and without the zone
offset being shown, set the
<code class="inline-code">datetime_format</code> setting to <code class="inline-code">&quot;iso
m nz&quot;</code>, so then the output will be like
<code class="inline-code">2014-09-03T20:56</code>. <a href="ref_directive_setting.html#topic.dateTimeFormatSettings">More...</a></p>
</li>
<li>
<p>Because anything that&#39;s accepted as
<code class="inline-code">date_format</code>/<code class="inline-code">datetime_format</code>/<code class="inline-code">time_format</code>
setting value can also be used with the
<code class="inline-code">?string</code> and
<code class="inline-code">?date</code>/<code class="inline-code">?time</code>/<code class="inline-code">?datetime</code>
build-ins, you can use the new formats like
<code class="inline-code">someDate?string.xs</code> and
<code class="inline-code">someString?date.xs</code>. (For the
<code class="inline-code">&quot;xs&quot;</code> and <code class="inline-code">&quot;iso&quot;</code>
formats, <code class="inline-code">_</code> can be used instead of space,
which means that, for example, you can write
<code class="inline-code">lastModified?string.iso_m_u</code> instead of
the more verbose <code class="inline-code">lastModified?string[&quot;iso m
u&quot;]</code>.)</p>
</li>
<li>
<p>That <code class="inline-code">&quot;iso&quot;</code> and
<code class="inline-code">&quot;xs&quot;</code> are now possible
<code class="inline-code">date_format</code>/<code class="inline-code">datetime_format</code>/<code class="inline-code">time_format</code>
setting values also means that such values can now be parsed
too via
<code class="inline-code">?date</code>/<code class="inline-code">?time</code>/<code class="inline-code">?datetime</code>.
The main application is with processing XML DOM-s, as there
values are coming in as strings, and now you can do
something like <code class="inline-code">order.confirmDate?date.xs</code>
to convert them to real dates.</p>
</li>
<li>
<p>The <a href="ref_builtins_date.html#ref_builtin_date_iso"><code>?iso_...</code>
built-ins</a> are now deprecated in favor of the new
setting values described above. They can be set as the
default date/time/date-time format, seamlessly fit into the
formatting architecture (and thus can parse strings too),
and has more/better options (<code class="inline-code">ms</code> always
shows 3 millisecond digits, <code class="inline-code">fz</code> for
forcing showing time zone offset).</p>
</li>
<li>
<p>If the "incompatible improvements"
configuration setting is at least 2.3.21, the
<code class="inline-code">?iso_...</code> built-ins won&#39;t show time zone
offset for <code class="inline-code">java.sql.Time</code> values anymore.
Most databases store time values that aren&#39;t in any time
zone, but just store hour, minute, second, and decimal
second field values, so showing the time zone doesn&#39;t make
sense. (Notable exceptions are PostgreSQL &quot;time with time
zone&quot; columns, where
<code class="inline-code"><em class="code-color">mzTime</em>?string.iso_fz</code>
could be used.)</p>
</li>
<li>
<p>Added <code class="inline-code">?is_time</code>,
<code class="inline-code">?is_datetime</code>,
<code class="inline-code">?is_date_only</code> (should be called
<code class="inline-code">?is_date</code>, but that was already taken) and
<code class="inline-code">?is_unknown_date_like</code> to check the exact
type of a date-like value.</p>
</li>
<li>
<p><code class="inline-code">?is_date</code> is now a deprecated name,
use <code class="inline-code">?is_date_like</code> instead. This is
because <code class="inline-code">?is_date</code> sounds like it checks if
the value is a date without time part, but actually it also
returns <code class="inline-code">true</code> for time, date-time, and
unknown date-like values.</p>
</li>
<li>
<p>Added <code class="inline-code">?date_if_unknown</code>,
<code class="inline-code">?time_if_unknown</code> and
<code class="inline-code">?datetime_if_unknown</code> built-ins, which
mark a date-like value with some of the sub-types: date
without time, time, or date-time, respectively. However, if
the value already holds this information, the built-in has
no effect. That is, it will never convert the sub-type of a
value, it only adds the sub-type if it was unknown.</p>
</li>
<li>
<p>Bug fixed: ISO 8601 dates (via
<code class="inline-code">?iso_...</code> and <code class="inline-code">&quot;iso&quot;</code>
format settings) now use proleptic Gregorian calendar for
the years before 1582, rather than Julian calendar. This is
(indirectly) required by the standard, and it&#39;s also how the
default Sun/Oracle Java XML Schema date/time/dateTime parser
works.</p>
</li>
</ul>
</li>
<li>
<p>Error message quality improvements (targeting frequent
support requests and some error message bugs):</p>
<ul>
<li>
<p>Fixed glitch where if an <code class="inline-code">#if</code> had
and <code class="inline-code">#else</code> or <code class="inline-code">#elseif</code>,
the
<code class="inline-code">#if</code>/<code class="inline-code">#else</code>/<code class="inline-code">#elseif</code>
wasn&#39;t hidden in the FTL stack trace when the error was
inside its nested block.</p>
</li>
<li>
<p>Some new context sensitive hints in undefined variable
exception error messages.</p>
</li>
<li>
<p>Fixed unclosed directive error messages at end of file
where the wrong unclosed directive name was reported</p>
</li>
<li>
<p>Better type error messages when accessing XML data
(applies when wrapped with
<code class="inline-code">freemarker.ext.dom</code>):</p>
<ul>
<li>
<p>Trying to use
<code class="inline-code">node.<em class="code-color">noSuchChildNodes</em></code>
on a place where scalar value is expected will explain
that the problem is that you had no matches in the
constructing XML query.</p>
</li>
<li>
<p>Trying to use
<code class="inline-code">node.<em class="code-color">multipleSuchChildNodes</em></code>
on a place where scalar value is expected will explain
that the problem is that you had multiple matches in the
constructing XML query.</p>
</li>
<li>
<p>Trying to use
<code class="inline-code">node.<em class="code-color">exactlyOneChildNode</em></code>
as number, date/time/date-time or boolean will explain
that values coming from XML are always strings (text),
and must be converted explicitly via
<code class="inline-code">?number</code>, <code class="inline-code">?boolean</code>,
<code class="inline-code">?date.xs</code>, etc.</p>
</li>
</ul>
</li>
<li>
<p>Trying to use <code class="inline-code">obj.someMethod</code>
without <code class="inline-code">()</code> on a place where method value
is not expected will recommend calling the method.</p>
</li>
<li>
<p>Trying to use methods like
<code class="inline-code">obj.getFoo</code> or
<code class="inline-code">obj.isFoo</code> without <code class="inline-code">()</code>on
a place where method value is not expected will recommend
using the <code class="inline-code">obj.foo</code> form.</p>
</li>
<li>
<p>Messages are now much more readable when rendered in
environments that don&#39;t obey to line-breaks. (This often
happens in improperly implemented HTML error pages and logs
viewers.)</p>
</li>
<li>
<p>Better FTL instruction stack traces:</p>
<ul>
<li>
<p>Error messages now contain up to 10 lines of FTL
stack trace (unless it&#39;s on the top of a full FTL stack
trace), because the FTL stack trace wasn&#39;t printed at
all when the exception was a cause exception in a Java
stack trace, or when only the value of
<code class="inline-code">getMessage()</code> was printed instead of a
stack trace.</p>
</li>
<li>
<p>The FTL stack trace is now more self explanatory
as it contains more text labels.</p>
</li>
<li>
<p>Stack frames that belong to nestings are now
marked differently, and are filtered out when the stack
trace wouldn&#39;t fit into the error message
otherwise.</p>
</li>
</ul>
</li>
<li>
<p>Bug fixed: <code class="inline-code">?substring</code> has thrown
low level
<code class="inline-code">java.lang.IndexOutOfBoundsException</code>-s
instead of more descriptive
<code class="inline-code">TemplateModelException</code>-s with FTL stack
trace.</p>
</li>
<li>
<p>Bug fixed: Slicing with ranges sometimes thrown low
level
<code class="inline-code">java.lang.IndexOutOfBoundsException</code>-s
instead of more descriptive
<code class="inline-code">TemplateModelException</code>-s with FTL stack
trace.</p>
</li>
<li>
<p>Bug fixed [<a href="https://sourceforge.net/p/freemarker/bugs/402/">402</a>]:
Fixed misleading parser error message when a directive
called without its required parameters (like
<code class="inline-code">&lt;#list&gt;</code>) was reported as unknown
directive.</p>
</li>
<li>
<p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/222/">222</a>]:
Poor quality error message when
<code class="inline-code"><em class="code-color">someString</em>[<em class="code-color">someIndex</em>]</code>
fails with string index out of bounds.</p>
</li>
<li>
<p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/27/">27</a>]:
Not very good quality error messages when
<code class="inline-code">#import</code>-ing a template whose parsing
fails.</p>
</li>
</ul>
</li>
<li>
<p>New <code class="inline-code">include</code> directive option,
<code class="inline-code">ignore_missing=<em class="code-color">boolean</em></code>.
When this is set to <code class="inline-code">true</code>, and the template to
include is missing, the error will be silently ignored, and
nothing will be included.</p>
</li>
<li>
<p>The <code class="inline-code">setting</code> directive can now set the
<code class="inline-code">output_encoding</code> setting.</p>
</li>
<li>
<p>New special variable: <code class="inline-code">.locale_object</code>.
This is like <code class="inline-code">.locale</code>, except that it&#39;s a
<code class="inline-code">java.util.Locale</code> object, not a string. This
is handy if you want to pass the current locale to Java
methods.</p>
</li>
<li>
<p>If <code class="inline-code">incompatible_improvements</code> in the
FreeMarker configuration is set to at least 2.3.21, hash
<em>literals</em> that repeat keys now only have the
key once with <code class="inline-code">?keys</code>, and only has the last
value associated to that key with <code class="inline-code">?values</code>.
This is consistent with the behavior of
<code class="inline-code"><em class="code-color">hash</em>[<em class="code-color">key</em>]</code>
and how maps work in Java.</p>
</li>
<li>
<p>Bug fixed: <code class="inline-code">?is_enumerable</code> has returned
<code class="inline-code">true</code> for Java methods get from Java objects,
despite that those values aren&#39;t <code class="inline-code">&lt;#list
...&gt;</code>-able. (This is actually a historical quirk of
<code class="inline-code">BeansWrapper</code>, not a bug in
<code class="inline-code">?is_enumerable</code>, but now
<code class="inline-code">?is_enumerable</code> is aware of this exceptional
case.)</p>
</li>
<li>
<p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/257/">257</a>]:
The result value of <code class="inline-code">?matches</code> wasn&#39;t
"reentrant". For example, you couldn&#39;t list the
matches inside another listing where you are also listing
exactly the same result value (stored in a common variable), as
they would consume from the same iterator. Most importantly,
even accessing the <code class="inline-code">?size</code> of the same result
value has terminated the outer listing of the same value.</p>
</li>
<li>
<p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/229/">229</a>]:
If you set <code class="inline-code">incompatible_improvements</code> to
2.3.21 (or higher), unclosed comments (<code class="inline-code">&lt;#--
<em class="code-color">...</em></code>) and
<code class="inline-code">#noparse</code>-s won&#39;t be silently closed at the
end of template anymore, but cause a parsing error
instead.</p>
</li>
</ul>
<h2 class="content-header header-section2" id="autoid_180">Changes on the Java side</h2>
<ul>
<li>
<p>Added new <code class="inline-code">Configuration</code> constructor,
<code class="inline-code">Configuration(Version
incompatibleImprovements)</code>. This deprecates the vague
<code class="inline-code">Configuration()</code> constructor, and makes using
<code class="inline-code">setIncompatibleImprovements(Version)</code> needless
in most cases. See an example <a href="pgui_quickstart_createconfiguration.html">here...</a></p>
</li>
<li>
<p>When setting the
<code class="inline-code">incompatible_improvements</code> setting (like with
the constructor above) to 2.3.21, two setting defaults
change:</p>
<ul>
<li>
<p>The default of the <code class="inline-code">object_wrapper</code>
setting
(<code class="inline-code">Configuration.getObjectWrapper()</code>)
changes from
<code class="inline-code">ObjectWrapper.DEFAULT_WRAPPER</code> to another
almost identical <code class="inline-code">DefaultObjectWrapper</code>
singleton, returned by <code class="inline-code">new
DefaultObjectWrapperBuilder(Version).build()</code>. The
new default object wrapper&#39;s "incompatible
improvements" version is set to the same as of the
<code class="inline-code">Configuration</code>. (See later regarding the
2.3.21 "incompatible improvements" of
<code class="inline-code">BeansWrapper</code> and
<code class="inline-code">DefaultObjectWrapper</code>). Furthermore, the
new default object wrapper doesn&#39;t allow changing its
settings; setter methods will throw
<code class="inline-code">IllegalStateException</code>. (If anything tries
to call setters on the old default in your application,
that&#39;s a dangerous bug that won&#39;t remain hidden now. As the
old default is a singleton too, potentially shared by
independently developed components, most of them expects the
out-of-the-box behavior from it (and the others are
necessarily buggy). Also, then concurrency glitches can
occur (and even pollute the class introspection cache)
because the singleton is modified after publishing.)</p>
</li>
<li>
<p>The default of the <code class="inline-code">template_loader</code>
setting
(<code class="inline-code">Configuration.getTemplateLoader()</code>})
changes to <code class="inline-code">null</code>, which means that
FreeMarker will not find any templates. Earlier the default
was a <code class="inline-code">FileTemplateLoader</code> that used the
current directory as the root. This was dangerous and
fragile as you usually don&#39;t have good control over what the
current directory will be. Luckily, the old default almost
never looked for the templates at the right place anyway, so
pretty much all applications had to set
<code class="inline-code">template_loader</code>, so it&#39;s unlikely that
changing the default breaks your application.</p>
</li>
</ul>
</li>
<li>
<p>New <code class="inline-code">BeansWrapper</code>,
<code class="inline-code">DefaultObjectWrapper</code> and
<code class="inline-code">SimpleObjectWrapper</code> constructor that takes a
<code class="inline-code">Version</code>
<code class="inline-code">incompatibleImprovements</code> argument. This has
the same role as the
<code class="inline-code">incompatible_improvements</code> setting of the
<code class="inline-code">Configuration</code>, but it applies to the
<code class="inline-code">ObjectWrapper</code> instead. (As
<code class="inline-code">ObjectWrapper</code>-s are often shared among
multiple <code class="inline-code">Configuration</code>-s, so they can&#39;t use
that setting of the <code class="inline-code">Configuration</code>.) In new or
actively developed projects it&#39;s recommended to use
<code class="inline-code">Configuration.VERSION_2_3_21</code> now. The
constructor without the <code class="inline-code">Version</code> parameter is
now deprecated.</p>
</li>
<li>
<p>Safer and more memory-efficient way of managing singletons
of <code class="inline-code">DefaultObjectWrapper</code>-s and
<code class="inline-code">BeansWrapper</code>-s that are possibly shared by
independently developed subsystems:</p>
<ul>
<li>
<p>Instead of <code class="inline-code">new
DefaultObjectWrapper(<em class="code-color">...</em>)</code>
and <code class="inline-code">new
BeansWrapper(<em class="code-color">...</em>)</code>, from
now on you should use <code class="inline-code">new
DefaultObjectWrapperBuilder(version).build()</code> and
<code class="inline-code">new BeansWrapperBuilder(version).build()</code>.
(The builder objects have properties (configuration
settings) like <code class="inline-code">BeansWrapper</code> has, which
specify the properties of the objects created.) The created
objects are <em>singletons</em> (VM-wide, or at
least Web-Application-wide) and read-only (means,
non-configurable, hence safe to share). The main benefit of
using these factories instead of creating new instances is
that it allows FreeMarker to share the class introspection
caches (an internal part of
<code class="inline-code">BeansWrapper</code>-s/<code class="inline-code">DefaultObjectWrapper</code>-s
that is expensive to populate) among the returned instances.
This allow sharing the caches (and the object wrappers)
between components that aren&#39;t aware of each other and use
FreeMarker internally.</p>
</li>
<li>
<p>Deprecated the static fields
<code class="inline-code">ObjectWrapper.DEFAULT_WRAPPER</code>,
<code class="inline-code">BEANS_WRAPPER</code> and
<code class="inline-code">SIMPLE_WRAPPER</code>, because these
<code class="inline-code">ObjectWrapper</code>-s are configurable (not
read-only), and thus dangerous to use as singletons (a badly
behaving 3rd party component can mess them up). Use the
factories described above instead. They are also more
flexible, as you can specify the desired
incompatible-improvements version for them and various other
<code class="inline-code">BeansWrapper</code> settings.</p>
</li>
<li>
<p>Deprecated all <code class="inline-code">SimpleHash</code>,
<code class="inline-code">SimpleCollection</code> and
<code class="inline-code">SimpleSequence</code> constructors that didn&#39;t
take an <code class="inline-code">ObjectWrapper</code> argument, as they
have usually used
<code class="inline-code">ObjectWrapper.DEFAULT_WRAPPER</code> as the
default, which itself is deprecated.</p>
</li>
<li>
<p><code class="inline-code">BeansWrapper</code>,
<code class="inline-code">DefaultObjectWrapper</code> and
<code class="inline-code">SimpleObjectWrapper</code> now implements the
<code class="inline-code">freemarker.template.utility.WriteProtectable</code>
interface with which the configuration properties of the
object wrapper can be set permanently to read-only by
calling <code class="inline-code">writeProtect()</code>. An attempt to
call a setter on a such <code class="inline-code">ObjectWrapper</code>
will immediately cause
<code class="inline-code">IllegalStateException</code>. (This is what&#39;s
used for the singletons returned by the
<code class="inline-code">getInstance</code> methods too; see
earlier).</p>
</li>
</ul>
</li>
<li>
<p>The value of the <code class="inline-code">time_zone</code> setting,
when you specify it with a <code class="inline-code">String</code> (in a
<code class="inline-code">java.util.Properties</code> object, or via
<code class="inline-code">&lt;#setting
<em class="code-color">...</em>&gt;</code>) can now be
<code class="inline-code">&quot;JVM default&quot;</code> to use the JVM default time
zone. The JVM default is the default value of that setting
anyway, but now you can state this explicitly, or restore this
value if it was overridden earlier.</p>
</li>
<li>
<p>Added new configuration setting,
<code class="inline-code">sql_date_and_time_time_zone</code>
(<code class="inline-code">Configurable.setSQLDateAndTimeTimeZone(TimeZone)</code>).
When this is set to non-<code class="inline-code">null</code>, the time zone
used when dealing with <code class="inline-code">java.sql.Date</code> and
<code class="inline-code">java.sql.Time</code> values will be this time zone
instead of the value of the <code class="inline-code">time_zone</code>
FreeMarker configuration setting. This is useful because JDBC
will, usually, construct the Java <code class="inline-code">Date</code>
objects so that they will show the year-month-day and
hour-minute-seconds values from the database "as
is" if you render them using the JVM default time zone.
As time zone conversions for SQL date-only and SQL time-only
values doesn&#39;t make much sense (unlike for SQL timestamps), you
should certainly set this setting to the JVM default time zone
(<code class="inline-code">TimeZone.getDefault()</code>, or if you configure
FreeMarker via <code class="inline-code">java.util.Properties</code>, as
property value &quot;JVM default&quot;). The default value is
<code class="inline-code">null</code> for backward compatibility. For more
details see the JavaDoc of
<code class="inline-code">Configurable.setSQLDateAndTimeTimeZone(TimeZone)</code>.</p>
</li>
<li>
<p>When configuring FreeMarker with
<code class="inline-code">java.util.Properties</code> (typically, when the
configuration is stored in a <code class="inline-code">.properties</code>
file), for the settings where you could specify a fully
qualified class name (most notably for the
<code class="inline-code">object_wrapper</code> setting) now you can also
specify constructor arguments and JavaBean property assignments.
For example, now you can write
<code class="inline-code">object_wrapper=com.example.MyObjectWrapper(1, 2,
exposeFields=true, cacheSize=5000)</code>that&#39;s nearly
equivalent with this Java code: <code class="inline-code">obj = new
com.example.MyObjectWrapper(1, 2); obj.setExposeFields(true);
obj.setCacheSize(5000); object_wrapper = obj;</code>. If you
are using this new syntax (i.e., if you have parentheses after
the class name, even if they are empty), and there&#39;s a builder
class for the requested class, that will be automatically used.
For example,
<code class="inline-code">object_wrapper=DefaultObjectWrapper(2.3.21)</code>
will create a <code class="inline-code">DefaultObjectWrapperBuilder</code> to
build the final instance, thus the object wrapper will be a
singleton instead of a new instance. The new syntax will also
look for a public static <code class="inline-code">INSTANCE</code> field if
there are 0 arguments and property assignments. For more details
see the Java API documentation of
<code class="inline-code">Configuration.setSetting</code>.</p>
</li>
<li>
<p>Template not found exceptions now explain that the
template path is interpreted by a template loader, and show the
<code class="inline-code">toString</code> of the
<code class="inline-code">TemplateLoader</code>. The out-of-the-box
<code class="inline-code">TemplateLoader</code> implementations now have an
overridden <code class="inline-code">toString</code> to show the actual base
directory and such details. Custom
<code class="inline-code">TemplateLoader</code> implementations are encouraged
to override <code class="inline-code">toString</code>.</p>
</li>
<li>
<p>Added
<code class="inline-code">Configuration.setSharedVariables(Map/*&lt;String,
Object&gt;*/)</code> for setting the shared variables from
Spring IoC and other IoC solutions. The already existing
<code class="inline-code">Configuration.setSharedVariable(String,
Object)</code> isn&#39;t a JavaBean property so it was hard to
use for that. Furthermore, the order in which
<code class="inline-code">Configuration.setObjectWrapper</code> and
<code class="inline-code">Configuration.setSharedVariables</code> are called
doesn&#39;t mater (unlike in the case of
<code class="inline-code">Configuration.setSharedVariable</code>), which is
essential in most IoC solutions.</p>
</li>
<li>
<p>Mostly concerning tool (like IDE plugin) authors:</p>
<ul>
<li>
<p><code class="inline-code">ParseException</code>-s now also store the
end-location of the error, not just its start-location. This
is useful if you want to underline the error in the source
code, not just point at it.</p>
</li>
<li>
<p><code class="inline-code">Configuration.getSupportedBuiltInDirectiveNames()</code>
can be used to return the names of directives supported by
FreeMarker.</p>
</li>
<li>
<p><code class="inline-code">TemplateExceptions</code> now expose the
position of the error (template name, line, column, end
line, end column) similarly to
<code class="inline-code">ParseException</code>-s. Where applicable, they
also expose the blamed expression in its canonical FTL
source form; this is mostly useful for
<code class="inline-code">InvalidReferenceException</code>-s.</p>
</li>
</ul>
</li>
<li>
<p>The concurrent performance of overloaded method lookups
(from the cache) was improved under Java 5 and later.</p>
</li>
<li>
<p>The <code class="inline-code">Version</code> instances that are
"incompatible improvements" break points are now
available via constants like:
<code class="inline-code">Configuration.VERSION_2_3_21</code>.</p>
</li>
<li>
<p>From now on, if you try to set the "incompatible
improvements" to greater than the current FreeMarker
version, or less than 2.3.0, an
<code class="inline-code">IllegalArgumentException</code> will be thrown.
Thus, <code class="inline-code">new
Configuration(<em class="code-color">someVersion</em>)</code>
not only activates the fixes up to that version, but ensures
that the application will not run in an environment with an
older FreeMarker version. (On an older FreeMarker version the
improvements that you have requested aren&#39;t implemented yet, so
you should get an exception.)</p>
</li>
<li>
<p>Added new configuration setting,
<code class="inline-code">show_error_tips</code>, defaults to
<code class="inline-code">true</code>. Sets if tips should be shown in error
messages of errors arising during template processing.</p>
</li>
<li>
<p>Instead of overriding
<code class="inline-code">BeansWrapper.finetuneMethodAppearance</code> (now
deprecated), now you can use
<code class="inline-code">BeansWrapper.setMethodAppearanceFineTuner(MethodAppearanceFineTuner)</code>,
so you don&#39;t need to extend the object wrapper class to
customize this aspect.</p>
</li>
<li>
<p>Added
<code class="inline-code">Configuration.getCoreDirecticeNames()</code> which
returns the names of all directives that are provided by
FreeMarker. This can useful for IDE-s.</p>
</li>
<li>
<p><code class="inline-code">template_loader</code> was added as possible
configuration setting <code class="inline-code">Properties</code> key.</p>
</li>
<li>
<p>The standard <code class="inline-code">CacheStorage</code>
implementations now have a <code class="inline-code">getSize()</code> method
for monitoring the cache size.
<code class="inline-code">MruCacheStorage</code> also has
<code class="inline-code">getSoftSize()</code> and
<code class="inline-code">getStrongSize()</code>.</p>
</li>
<li>
<p>Various smaller improvements in configuration setting
errors messages.</p>
</li>
<li>
<p>With incompatible improvements 2.3.21 only: Empty ranges
return <code class="inline-code">Constants.EMPTY_SEQUENCE</code> instead of an
empty <code class="inline-code">SimpleSequence</code>. This is in theory
backward compatible, as the API only promises to give something
that implements <code class="inline-code">TemplateSequenceModel</code>.</p>
</li>
<li>
<p>FreeMarker now requires Java version has changed from 1.2
to 1.4.</p>
</li>
<li>
<p>Bugs fixed and improvements in overloaded method
selection/invocation, but only if you create the
<code class="inline-code">BeansWrapper</code>/<code class="inline-code">DefaultObjectWrapper</code>
with constructor parameter
<code class="inline-code">Configuration.VERSION_2_3_21</code> (or if you are
using <code class="inline-code">Properties</code> to configure FreeMarker, you
can do that like
<code class="inline-code">object_wrapper=BeansWrapper(2.3.21)</code>), or if
you have a <code class="inline-code">Configuration</code> with similar
<code class="inline-code">incompatible_improvements</code> 2.3.21
<em>and</em> you leave the
<code class="inline-code">object_wrapper</code> setting on its default value.
There&#39;s a little chance that because of these changes, a
different overloaded method will be chosen than before, or even
that ambiguity errors will arise where earlier they didn&#39;t
(although the opposite is far more frequent), hence the fixes
aren&#39;t automatically activated. But the fix mostly only effect
calls that were failing or have chosen then wrong method
earlier, so it&#39;s recommended to activate it for projects that
are still actively developed. This fix includes numerous
changes:</p>
<ul>
<li>
<p>Earlier, <code class="inline-code">null</code> argument values has
only matched overloaded methods where the corresponding
parameter had <code class="inline-code">Object</code> type, not a subclass
of it. That&#39;s clearly a bug. Now it considers all overloads
where the parameter type is non-primitive, and just like the
Java language, it choses the one with the most specific type
among them. This is the most important fix, and also the
most risky one regarding backward-compatibility. Like if you
have <code class="inline-code">m(Object o)</code> and <code class="inline-code">m(String
s)</code> in a Java class, earlier for a
<code class="inline-code">m(null)</code> call in the template it has
chosen <code class="inline-code">m(Object o)</code>, but now it will
choose <code class="inline-code">m(String s)</code> instead (because
<code class="inline-code">String</code> is also
<code class="inline-code">null</code>-able and is more specific than
<code class="inline-code">Object</code>). Furthermore, if you also had
<code class="inline-code">m(File f)</code> in the same class, now it will
cause an ambiguity exception, since the specificity of
<code class="inline-code">File</code> and <code class="inline-code">String</code> can&#39;t
be compared (same rule as under Java language), while
earlier that wasn&#39;t a problem as only <code class="inline-code">m(Object
o)</code> was seen as applicable.</p>
</li>
<li>
<p>The behavior of numbers with overloaded method
selection was heavily reworked:</p>
<ul>
<li>
<p>If possible, it now always choses the overload
where overflow and truncation to integer (like 1.5 to 1)
is avoided. Among the methods where no such critical
loss occurs, it choses the overload with the least risk
of precision loss (unless other conditions with higher
priority suggest otherwise). Earlier, the method
selection was prone to do choices that led to overflow
or precision loss, especially when the parameter was a
literal with decimals.</p>
</li>
<li>
<p>Overloaded method call can now convert to
non-primitive numerical types, like a
<code class="inline-code">Byte</code> or <code class="inline-code">byte</code> value
is automatically converted to <code class="inline-code">Integer</code>
if the parameter type is <code class="inline-code">Integer</code>.
(This has always worked for non-overloaded methods.)
Earlier where such conversion was needed, the method
wasn&#39;t seen seen applicable.</p>
</li>
<li>
<p>Method selection is now not only based on the type
of the wrapped number, but also on its value. For
example, a <code class="inline-code">Long</code> with value
<code class="inline-code">1</code> is now seen as compatible with a
method with parameter type <code class="inline-code">int</code> or
<code class="inline-code">short</code> or <code class="inline-code">byte</code>, as
<code class="inline-code">1</code> can be stored in those without
loss. This is important as unlike in Java language, in
FTL you doesn&#39;t have strict control over the numerical
types (the type of the wrapped number, actually), as FTL
has no type declarations. (If multiple compatible
methods are available, it will still try to chose the
one with the same or bigger numerical type.)</p>
</li>
<li>
<p>Conversion from/to <code class="inline-code">BigInteger</code>
is now supported.</p>
</li>
</ul>
</li>
<li>
<p>Method choice ambiguity errors now occur much less
often. Ambiguities was and are resolved by selecting the
compatible methods then choosing the one with the most
specific parameter types among them. The changes are:</p>
<ul>
<li>
<p>When comparing the overall specificity of two
parameter lists: Earlier the parameter list seen as more
specific was the one that had some parameters that won
in specificity, and if both had such parameters then it
was an ambiguity. Now it&#39;s enough if a method has more
such parameters where it&#39;s a better match than the other
has, or if the two methods are still equal, if it has
the first better matching parameter. This can lead to
choices that seem arbitrary (but are still
deterministic), but as there&#39;s no automated way of
discovering method selection ambiguities in templates
(unlike in Java source code, where they will be detected
during compilation), especially as overloaded selection
has to rely on the <em>runtime</em> type of
the values which even make proper testing hard, this was
considered to be a better compromise than throwing an
exception whenever the choice of the method is not
obvious. Also note that in fact this mechanism is more
complicated than just counting the "winner"
parameter positions for each methods, as certain kind of
wins are stronger than any number of the others: wins
where the other possibility is risking of substantial
mantissa precision loss are the strongest (like dropping
decimals versus not to), wins where the primitive type
wins over the boxed class is the weakest (like
<code class="inline-code">int</code> versus
<code class="inline-code">Integer</code>), subclassing wins (like
<code class="inline-code">String</code> versus
<code class="inline-code">Object</code>) are between these two.</p>
</li>
<li>
<p>When comparing the specificity of two parameters
types at the same parameter position: The algorithm now
considers a primitive type as more specific that its
corresponding boxing class (like <code class="inline-code">int</code>
is considered to be more specific than
<code class="inline-code">Integer</code>).</p>
</li>
<li>
<p>There was a bug with overloaded varargs methods of
different parameter counts, where sometimes the last
parameters of the compared methods was ignored, which is
taking away a potential deciding factor and thus can
lead to ambiguity error. Whether this happened depends
on the order in which the Java reflection API has
returned the methods, which is undocumented and known to
change at least after some Java updates, breaking the
application.</p>
</li>
<li>
<p>When comparing the specificity of two array types,
until now they were seen as equal. Now the component
types are compared, and then that with the less specific
component type is preferred. For example, among
<code class="inline-code">f(String[])</code> and
<code class="inline-code">f(Object[])</code>, the last will always
win. This might sounds controversial, but as we can&#39;t
efficiently tell the common type of all the items in a
sequence or <code class="inline-code">List</code>, and so we don&#39;t
know if both arrays are indeed valid targets, we go for
the safest choice.</p>
</li>
</ul>
</li>
<li>
<p>FTL sequence values (like Java
<code class="inline-code">List</code>-s or FTL
<code class="inline-code">[<em class="code-color">x</em>,
<em class="code-color">y</em>,
<em class="code-color">...</em>]</code> constants) were
not seen as applicable to a parameter with array type if
there were multiple overloaded methods with the same number
of parameters but with different types on the position of
the array parameter. That is, if you had
<code class="inline-code">f(String[])</code> and
<code class="inline-code">f(String)</code> in Java, then
<code class="inline-code">f([&#39;foo&#39;, &#39;bar&#39;])</code> in the template
reported no compatible overloads. Now it will choose
<code class="inline-code">f(String[])</code>. Note that if there&#39;s also an
<code class="inline-code">f(List)</code> or even an
<code class="inline-code">f(Collection)</code>, it will prefer those over
arrays. (For consistency, this conversion will work even if
the argument is a <code class="inline-code">List</code> that come directly
from Java (as opposed to be created inside FTL), i.e., when
it was wrapped then unwrapped to the original
<code class="inline-code">List</code> object.) For a multidimensional
array parameter type, this conversion works recursively, so
you can pass in a sequence-of-sequences as the
argument.</p>
</li>
<li>
<p>FTL sequence values that wrapped a Java array (when
FreeMarker was also aware of that via
<code class="inline-code">AdapterTemplateModel</code> or
<code class="inline-code">WrapperTemplateModel</code>) were not seen as
applicable to a parameter with <code class="inline-code">List</code> type
if there were multiple overloaded methods with the same
number of parameters but with different types on the
position of the array parameter. So this is pretty much like
the issue described in the previous point, but for array to
<code class="inline-code">List</code> conversion. The array to
<code class="inline-code">List</code> conversion will be avoided if
possible, but it will be attempted if there&#39;s no other
alternative. Note that unlike with <code class="inline-code">List</code>
to array conversions, here FreeMarker can&#39;t cope with
multi-dimensional lists, that is, an array-of-arrays won&#39;t
be converted to a
<code class="inline-code">List</code>-of-<code class="inline-code">List</code>-s.</p>
</li>
<li>
<p>FTL string to Java
<code class="inline-code">char</code>/<code class="inline-code">Character</code>
conversion now works for overloaded method parameters;
earlier it has worked for non-overloaded methods only. If
the string length is 1, it will be seen as compatible with
parameters with <code class="inline-code">char</code> or
<code class="inline-code">Character</code> type.</p>
</li>
<li>
<p>Decreased the chance of choosing the wrong target Java
type when unwrapping multi-typed FTL values: When unwrapping
a parameter value that implements multiple FTL types (e.g.
string and hash) but doesn&#39;t implement
<code class="inline-code">AdapterTemplateModel</code> or
<code class="inline-code">WrapperTemplateModel</code>, a decision has to
be made if to what Java type the value should be unwrapped
to (e.g. to <code class="inline-code">String</code> or to
<code class="inline-code">Map</code>). In earlier versions that decision
was made based on the most specific common super type of the
parameters types of the given parameter position. However,
it&#39;s quite common that the common super type is too generic,
usually <code class="inline-code">Object</code>. Now
<code class="inline-code">BeansWrapper</code> stores "type
flags" for each parameter position of overloaded
methods, from which it can tell whether a potential target
Java type occurs in any of the overloads on the given
parameter position.</p>
</li>
<li>
<p>In many cases, less specific hint class was used for
unwrapping than that was possible within the limitations of
the applied hint generation algorithm. (The unwrapping hint
has influence when there&#39;s an ambiguity regarding how to
create a Java object form an FTL value. In the vast majority
of the cases, a too generic hint has no effect.) (This is a
highly technical topic. The way it works is that a single
common unwrapping hint class is chosen for a given argument
position shared by the overloads that has the same number of
parameters, and that hint class has to be as specific as
possible while it must fit all those parameter types. The
issue with the too generic hints had several instances: (a)
When the most specific common class/interface of two
same-position parameter types was searched, if there was
multiple common classes/interfaces that had no relationship
(this is always at most one class and one or more unrelated
interfaces), due to the ambiguity it has felt back to using
<code class="inline-code">Object</code> as the unwrapping hint. Now if
there&#39;s a non-<code class="inline-code">Object</code> class among them in
such case, it will be chosen as the hint (i.e., we ignore
the common interfaces). Otherwise if only a single interface
remains by removing <code class="inline-code">Cloneable</code>,
<code class="inline-code">Serializable</code>, and
<code class="inline-code">Comparable</code> (in that order), that will be
chosen. Only then it falls back to
<code class="inline-code">Object</code>. (b) The common most specific
class of a primitive type and the corresponding boxing class
was sometimes <code class="inline-code">Object</code> instead of the
boxing class. This has depended on Java&#39;s internal ordering
of the methods, and so were quite unpredictable, like the
result could change after upgrading Java under the
application. (c) The common superclass of a numerical
primitive value and a numerical non-primitive value was
always <code class="inline-code">Object</code>, now if they are a
primitive-boxing class pair, then it&#39;s the boxing class,
otherwise it&#39;s <code class="inline-code">Number</code>. (d) If the varags
parameter position was not the same in all the overloaded
varargs methods, sometimes some varargs arguments where
unwrapped with too generic hints. When this happened was
unpredictable as it depended on Java&#39;s internal method
ordering again.)</p>
</li>
<li>
<p>When unwrapping method call arguments before calling a
Java method, if the argument was an
<code class="inline-code">AdapterTemplateModel</code> and the target
parameter type was primitive,
<code class="inline-code">AdapterTemplateModel.getAdaptedObject(Class
hint)</code> has received the primitive type of the
target parameter (like <code class="inline-code">int</code> instead of
<code class="inline-code">Integer</code>) as the hint. This did not make
sense since <code class="inline-code">getAdaptedObject</code> can only
return <code class="inline-code">Object</code>-s, not primitive values.
Yet, <code class="inline-code">BeansWrapper</code> has expected the
returned value to be of the primitive type, otherwise it has
discarded it. Exactly the same problem occurs with
<code class="inline-code">WrapperTemplateModel</code>. Thus, ultimately,
if the target parameter type was primitive and some of these
interfaces were implemented, their return value was always
discarded and FreeMarker has felt back to other means of
unwrapping. Now <code class="inline-code">BeansWrapper</code> always
passes in and expects the boxing type (like
<code class="inline-code">Integer</code>) instead of the primitive
type.</p>
</li>
</ul>
</li>
<li>
<p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/373/">373</a>]:
These are three bugs actually, which can cause problems when
FreeMarker re-loads a template because of a charset override
with <code class="inline-code">&lt;#ftl encoding=&quot;...&quot;&gt;</code>: First, if
the template loader was a <code class="inline-code">URLTemplateLoader</code>,
when <code class="inline-code">TemplateLoader.getReader()</code> was called
for the second time, and the <code class="inline-code">Reader</code> returned
for the first time was already used, it might returned an empty
or corrupted template, depending on the backing URL
implementation. Secondly, when FreeMarer has decided if a
template file has to be re-loaded because its encoding specified
with <code class="inline-code">&lt;#ftl encoding=&quot;...&quot;&gt;</code> differs from
the encoding used for loading the template first, it has used
case-sensitive comparison, thus often re-loaded needlessly (like
&quot;UTF-8&quot; and &quot;utf-8&quot; mean the same). Now this comparison is
case-insensitive. Last not least, when retrying with the second
charset, the <code class="inline-code">TemplateCache</code> has forgotten to
close the first <code class="inline-code">Reader</code>, which can be a handle
leak.</p>
</li>
<li>
<p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/411/">411</a>]:
Invalid and redundant execution environment names from the OSGi
bundle manifest were removed. It looks like this now:
<code class="inline-code">Bundle-RequiredExecutionEnvironment: J2SE-1.5,
J2SE-1.4</code>. That is, we prefer (and compile against)
1.5, but only require 1.4.</p>
</li>
<li>
<p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/409/">409</a>]:
<code class="inline-code">SimpleHash</code>&#39;s internal <code class="inline-code">Map</code>
is concurrently modified on a non-safe way when getting length-1
<code class="inline-code">String</code> key that exists but maps to
<code class="inline-code">null</code>. This operation will accidentally add a
<code class="inline-code">Character</code> key to the internal map, which is
not a thread-safe operation.</p>
</li>
<li>
<p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/273/">273</a>]:
<code class="inline-code">TemplateLoader</code>-s that use
<code class="inline-code">java.net.URLConnection</code>-s should set
<code class="inline-code">URLConnection.useCaches</code> to
<code class="inline-code">false</code>, or else it won&#39;t detect template
caches on certain configurations.</p>
<ul>
<li>
<p><code class="inline-code">URLTemplateLoader</code> and its
subclasses and
<code class="inline-code">WebApplicationTemplateLoader</code> now has a
<code class="inline-code">setURLConnectionUsesCaches(Boolean)</code>
method. It&#39;s recommended to set this property to
<code class="inline-code">false</code> from its default backward
compatible value, <code class="inline-code">null</code>. As FreeMarker has
its own template cache with its own update delay setting
(<code class="inline-code">template_update_delay</code>,
<code class="inline-code">Configuration.setTemplateUpdateDelay(int)</code>),
it shouldn&#39;t cause performance problems. The
<code class="inline-code">null</code> value will leave the caching of the
<code class="inline-code">java.net.URLConnection</code> on its default,
which is usually <code class="inline-code">true</code>.</p>
</li>
<li>
<p>If <code class="inline-code">incompatible_improvements</code> is set
to 2.3.21 (or higher) and templates are loaded through
<code class="inline-code">Configuration.getTemplate</code>, and the
<code class="inline-code">TemplateLoader</code> in use has
<code class="inline-code">URLConnectionUsesCaches</code> left on
<code class="inline-code">null</code>, it will behave as if it was set to
<code class="inline-code">false</code>. Note that this
<code class="inline-code">incompatible_improvements</code> trick only
works if the template is loaded through
<code class="inline-code">Configuration.getTemplate</code> (or
<code class="inline-code">TemplateCache</code>).</p>
</li>
</ul>
</li>
<li>
<p>Bug fixed: When changing the properties of
<code class="inline-code">DefaultObjectWrapper</code> or
<code class="inline-code">BeansWrapper</code> that influenced class
introspection results (like <code class="inline-code">exposureLevel</code> or
<code class="inline-code">exposeFields</code>), the introspection cache wasn&#39;t
cleared, and thus returned stale information for the classes
that were introspected before those properties were changed. Now
changing such properties always clears the introspection
caches.</p>
</li>
<li>
<p>Bug fixed: Constants used for empty sequence, empty hash,
empty collection and empty iterator weren&#39;t
<code class="inline-code">Serializable</code>.</p>
</li>
<li>
<p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/311/">300</a>]:
Logger class availability check was incorrect in that it has
checked the availability of logger libraries with the thread
context class loader, then later it tried to link to them with
the defining class loader of the FreeMarker classes. With some
class loader setups (notably under Netbeans sometimes) this led
to <code class="inline-code">ClassDefNotFoundError</code>-s that made
FreeMarker unusable. (The check itself was also not very
durable, as it didn&#39;t expected <code class="inline-code">LinakeError</code>-s,
only <code class="inline-code">ClassNotFoundException</code>.)</p>
</li>
<li>
<p>Bug fixed: <code class="inline-code">ClassUtil.forName</code>, used
inside FreeMarker everywhere to resolve class names to classes,
if the thread context class loader is <code class="inline-code">null</code>,
no longer tries to load with the bootstrap class loader before
loading with the defining class loader of FreeMarker.</p>
</li>
<li>
<p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/311/">311</a>]:
<code class="inline-code">TemplateBooleanModel.TRUE</code> and
<code class="inline-code">FALSE</code> are now serializable</p>
</li>
<li>
<p>Bug fixed: Various issues in <code class="inline-code">Version</code>
class, such as wrong <code class="inline-code">hashCode</code>, possible
concurrency glitches, and acceptance of some malformed version
strings.</p>
</li>
<li>
<p>Bug fixed [<a href="https://sourceforge.net/p/freemarker/bugs/414/">414</a>]:
Eclipse debug mode running was suspended during FreeMarker
static initialization on the JRebel availability checked if
JRebel wasn&#39;t available.</p>
</li>
</ul>
<h2 class="content-header header-section2" id="autoid_181">Other changes</h2>
<ul>
<li>
<p>The license has changed from our proprietary BSD-Style
license to the well know &quot;Apache License, Version 2.0&quot;.
Furthermore, the copyright owner has changed from &quot;Visigoth
Software Society&quot; (which was founded by Jonathan Revusky) to the
three main FreeMarker 2 developers/contributors, &quot;Attila
Szegedi, Daniel Dekany, and Jonathan Revusky&quot;. See the <a href="app_license.html">new license here</a>.</p>
</li>
<li>
<p>The required minimum Java version was raised from 1.2 to
1.4. FreeMarker will not work on Java 1.2 or 1.3.</p>
</li>
<li>
<p>Many smaller improvements and fixes in the Manual and API
JavaDocs.</p>
</li>
</ul>
<div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="versions_2_3_22.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_3_20.html"><span>Next</span></a></div></div></div></div> </div>
</div>
<div class="site-footer"><div class="site-width"><div class="footer-top"><div class="col-left sitemap"><div class="column"><h3 class="column-header">Overview</h3><ul><li><a href="https://freemarker.apache.org/">What is FreeMarker?</a></li><li><a href="https://freemarker.apache.org/freemarkerdownload.html">Download</a></li><li><a href="app_versions.html">Version history</a></li><li><a href="app_faq.html">FAQ</a></li><li><a itemprop="license" href="app_license.html">License</a></li><li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy policy</a></li></ul></div><div class="column"><h3 class="column-header">Often used / Reference</h3><ul><li><a href="https://try.freemarker.apache.org/">Try template online</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions cheatsheet</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_builtins_alphaidx.html">?built_ins</a></li><li><a href="ref_specvar.html">.special_vars</a></li><li><a href="api/freemarker/core/Configurable.html#setSetting-java.lang.String-java.lang.String-">Configuration settings</a></li></ul></div><div class="column"><h3 class="column-header">Community</h3><ul><li><a href="https://github.com/apache/freemarker">Github project page</a></li><li><a href="https://issues.apache.org/jira/projects/FREEMARKER">Report a bug</a></li><li><a href="https://freemarker.apache.org/report-security-vulnerabilities.html">Report security vulnerability</a></li><li><a href="https://stackoverflow.com/questions/ask?tags=freemarker">Get help on StackOverflow</a></li><li><a href="https://twitter.com/freemarker">Announcements on Twitter</a></li><li><a href="https://freemarker.apache.org/mailing-lists.html">Discuss on mailing lists</a></li></ul></div></div><div class="col-right"><ul class="social-icons"><li><a class="github" href="https://github.com/apache/freemarker">Github</a></li><li><a class="twitter" href="https://twitter.com/freemarker">Twitter</a></li><li><a class="stack-overflow" href="https://stackoverflow.com/questions/ask?tags=freemarker">Stack Overflow</a></li></ul><a class="xxe" href="http://www.xmlmind.com/xmleditor/" rel="nofollow" title="Edited with XMLMind XML Editor"><span>Edited with XMLMind XML Editor</span></a></div></div><div class="footer-bottom"> <p class="last-generated">
Last generated:
<time itemprop="dateModified" datetime="2024-02-12T20:34:04Z" title="Monday, February 12, 2024 at 8:34:04 PM Greenwich Mean Time">2024-02-12 20:34:04 GMT</time>, for Freemarker 2.3.32 </p>
<p class="copyright">
© <span itemprop="copyrightYear">1999</span>–2024
<a itemtype="http://schema.org/Organization" itemprop="copyrightHolder" href="https://apache.org/">The Apache Software Foundation</a>. Apache FreeMarker, FreeMarker, Apache Incubator, Apache, the Apache FreeMarker logo are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners. </p>
</div></div></div></body>
</html>