http://git-wip-us.apache.org/repos/asf/incubator-freemarker-site/blob/52c070a9/builds/2.3.26-nightly/versions_2_3_22.html
----------------------------------------------------------------------
diff --git a/builds/2.3.26-nightly/versions_2_3_22.html
b/builds/2.3.26-nightly/versions_2_3_22.html
new file mode 100644
index 0000000..15a52c2
--- /dev/null
+++ b/builds/2.3.26-nightly/versions_2_3_22.html
@@ -0,0 +1,1197 @@
+<!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.22 - 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.22">
+<meta property="og:locale" content="en_US">
+<meta property="og:url"
content="http://freemarker.org/docs/versions_2_3_22.html">
+<link rel="canonical" href="http://freemarker.org/docs/versions_2_3_22.html">
+<link rel="icon" href="favicon.png" type="image/png">
+<link rel="stylesheet" type="text/css"
href="http://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?1489402528979">
+<script>
+(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+ga('create', 'UA-55420501-1', 'auto');
+ga('send', 'pageview');
+</script>
+</head>
+<body itemscope itemtype="https://schema.org/Code">
+ <meta itemprop="url" content="http://freemarker.org/docs/">
+ <meta itemprop="name" content="Apache FreeMarker Manual">
+
+ <!--[if lte IE 9]>
+ <div style="background-color: #C00; color: #fff; padding: 12px 24px;">Please
use a modern browser to view this website.</div>
+ <![endif]--><div class="header-top-bg"><div class="site-width header-top"><a
class="logo" href="http://freemarker.org" role="banner"> <img
itemprop="image" src="logo.png" alt="FreeMarker">
+</a><ul class="tabs"><li><a href="http://freemarker.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="http://freemarker.org/contribute.html"
title="Contribute"><span>Contribute</span></a></li><li><a class="tab icon-bug"
href="https://issues.apache.org/jira/browse/FREEMARKER/" title="Report a
Bug"><span>Report a Bug</span></a></li><li><a class="tab icon-download"
href="http://freemarker.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="searc
h-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"><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="itemListEl
ement" itemscope itemtype="http://schema.org/ListItem"><a class="label"
itemprop="item" href="versions_2_3_22.html"><span
itemprop="name">2.3.22</span></a></li></ul><div class="bookmarks"
title="Bookmarks"><span class="sr-only">Bookmarks:</span><ul
class="bookmark-list"><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.22"];</script>
+ <script src="toc.js?1489402528979"></script>
+ <script src="docgen-resources/main.min.js?1489402528979"></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_23.html"><span>Previous</span></a><a class="paging-arrow
next" href="versions_2_3_21.html"><span>Next</span></a></div><div
class="title-wrapper">
+<h1 class="content-header header-section1" id="versions_2_3_22"
itemprop="headline">2.3.22</h1>
+</div></div><div class="page-menu">
+<div class="page-menu-title">Page Contents</div>
+<ul><li><a class="page-menu-link" href="#autoid_168"
data-menu-target="autoid_168">Changes on the FTL side</a></li><li><a
class="page-menu-link" href="#autoid_169" data-menu-target="autoid_169">Changes
on the Java side</a></li><li><a class="page-menu-link" href="#autoid_170"
data-menu-target="autoid_170">Notes</a></li></ul> </div><p>Date of release:
2015-03-01</p><p>Note that since 2.3.22 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.22 "incompatible
+ improvements"</em> (it's always clearly indicated),
+ because they could, with very small chance, break existing
+ applications. For actively maintained applications it's probably
+ better to allow them. See <a
href="pgui_config_incompatible_improvements.html#pgui_config_incompatible_improvements_how_to_set">how
to set
+ "incomplatible improvements" here</a>.</p>
+
+
+
+
+<h2 class="content-header header-section2" id="autoid_168">Changes on the FTL
side</h2>
+
+
+ <ul>
+ <li>
+ <p>New built-ins: <code class="inline-code">api</code> and
+ <code class="inline-code">has_api</code>.
+ <code class="inline-code"><em
class="code-color">value</em>?api</code> provides
+ access to the API (usually, the Java API) of
+ <code class="inline-code"><em
class="code-color">value</em></code>, like
+ <code class="inline-code"><em
class="code-color">value</em>?api.<em
class="code-color">someJavaMethod()</em></code>
+ or
+ <code class="inline-code"><em
class="code-color">value</em>?api.<em
class="code-color">someBeanProperty</em></code>),
+ if the value itself supports exposing its API. This meant to be
+ used rarely, when you need to call a Java method of an object,
+ but the by-design simplistic view of the value that FreeMarker
+ exposes to the templates hides that, and there's no
equivalent
+ built-in either. For example, when you put a
+ <code class="inline-code">Map</code> into the data-model (and
you are using
+ the default object wrapper), <code
class="inline-code">myMap.myMethod()</code>
+ in a template basically translates to <code
class="inline-code">((Method)
+ myMap.get("myMethod")).invoke(...)</code> in Java,
thus you
+ can't call <code class="inline-code">myMethod</code>. If,
however, you write
+ <code class="inline-code">myMap?api.myMethod()</code> instead,
that means
+ <code class="inline-code">myMap.myMethod()</code> in Java.
Similarly,
+ <code class="inline-code">myMap?api.myProperty</code> translates
to
+ <code class="inline-code">myMap.getMyProperty()</code> in Java,
instead of to
+ <code
class="inline-code">myMap.get("myProperty")</code>.</p>
+
+ <p><em>If you can, rely on the capabilities of the FTL
+ types and the related built-ins as far as possible. Using
+ <code class="inline-code">?api</code> is only the last
+ resort.</em></p>
+
+ <p>Using <code class="inline-code">?api</code> also happens to
offer a
+ workaround for the lack of non-<code
class="inline-code">String</code>
+ <code class="inline-code">Map</code> key support in FTL's
+ <code class="inline-code">[]</code> operator (as in
+ <code class="inline-code">myMap[key]</code>), because now you
can write
+ <code class="inline-code">myMap?api.get(nonStringKey)</code>.</p>
+
+ <p><code class="inline-code">?api</code> is not enabled by
default and
+ isn't available for all values. <a
href="ref_builtins_expert.html#ref_buitin_api_and_has_api">See more
+ here...</a></p>
+ </li>
+
+ <li>
+ <p>Identifiers (like <code
class="inline-code">someVariable</code>) can now
+ contain minus (<code class="inline-code">-</code>), dot
+ (<code class="inline-code">.</code>), and colon (<code
class="inline-code">:</code>) at any
+ position, but those characters <em>must be escaped with a
+ preceding backslash</em> (<code class="inline-code">\</code>),
or else
+ they would be interpreted as operators. For example, to read the
+ variable whose name is "data-id", the correct
+ expression is <code class="inline-code">data\-id</code>, as
+ <code class="inline-code">data-id</code> would be interpreted as
"data
+ minus id". This also works for named macro parameters,
+ which is useful when you want to accept arbitrary HTML
+ attributes in a catch-all parameter, like in <code
class="inline-code"><@box
+ class="someCssClass" data\-id=product.id /></code>.
(When
+ you enumerate the catch-all parameter names inside the macro,
+ the key string you get is <code
class="inline-code">"data-id"</code> without
+ <code class="inline-code">\</code> of course.)</p>
+ </li>
+
+ <li>
+ <p>Added <code class="inline-code">?lower_abc</code> and
+ <code class="inline-code">?upper_abc</code>. This converts
+ <code class="inline-code">1</code>, <code
class="inline-code">2</code>,
+ <code class="inline-code">3</code>, etc., to the string
+ <code class="inline-code">"a"</code>, <code
class="inline-code">"b"</code>,
+ <code class="inline-code">"c"</code>, etc. (or for
<code class="inline-code">"A"</code>,
+ <code class="inline-code">"B"</code>, <code
class="inline-code">"C"</code>, etc.). When
+ reaching <code class="inline-code">"z"</code>, it
continues like
+ <code class="inline-code">"aa"</code>, <code
class="inline-code">"ab"</code>, etc. This is
+ the same logic that you can see in column labels in spreadsheet
+ applications (like Excel or Calc). <a
href="ref_builtins_number.html#ref_builtin_lower_abc">More details...</a></p>
+ </li>
+
+ <li>
+ <p>Added <code class="inline-code">?keep_before_last</code> and
+ <code class="inline-code">?keep_after_last</code>. Example:
+ <code
class="inline-code">"foo.bar.txt"?keep_before_last(".")</code>
returns
+ <code class="inline-code">"foo.bar"</code>,
+ <code
class="inline-code">"foo.bar.txt"?keep_after_last(".")</code>
returns
+ <code class="inline-code">"txt"</code>. (These work
like
+ <code class="inline-code">?keep_before</code> and
+ <code class="inline-code">?keep_after</code>, but those look for
the first
+ occurrence of the separator.)</p>
+ </li>
+
+ <li>
+ <p>Added many missing UNICODE letters and digits to the set
+ of legal identifier characters, like Korean letters (bug fixed:
+ [<a
href="https://sourceforge.net/p/freemarker/bugs/129/">129</a>])</p>
+ </li>
+
+ <li>
+ <p>Error message quality improvements:</p>
+
+ <ul>
+ <li>
+ <p>Several improvements when calling custom JSP tags; see
+ them in its own section later.</p>
+ </li>
+
+ <li>
+ <p>Bug fixed: When localized lookup or template
+ acquisition has kicked in, error messages have still quoted
+ the name used for requesting the template, rather that the
+ actual template source name (like <code
class="inline-code">foo.ftl</code>
+ instead of <code class="inline-code">foo_en.ftl</code>, when
the template
+ was get as <code class="inline-code">foo.ftl</code>, but
behind the scenes
+ was loaded from <code
class="inline-code">foo_en.ftl</code>).</p>
+ </li>
+
+ <li>
+ <p>"Template not found" errors are now more
+ detailed, giving hints about accidentally using
+ <code class="inline-code">\</code> instead of <code
class="inline-code">/</code>, or
+ backing out of the <code
class="inline-code">TemplateLoader</code>'s root
+ directory.</p>
+ </li>
+
+ <li>
+ <p>The <code class="inline-code">#setting</code> directive
gives more
+ helpful error message when the setting name is not
+ recognized, and lists the allowed setting names or a
+ correction suggestion.</p>
+ </li>
+
+ <li>
+ <p>When a bad special variable name
+ (<code class="inline-code">.<em
class="code-color">name</em></code>) is
+ encountered, the list of available names is shown in the
+ error message.</p>
+ </li>
+
+ <li>
+ <p>When <code class="inline-code">Map.get</code> or
+ <code class="inline-code">Map.containsKey</code> of a wrapped
+ <code class="inline-code">Map</code> throws a
+ <code class="inline-code">ClassCastException</code> or
+ <code class="inline-code">NullPointerException</code>, the
error will
+ point to the causing FTL expression (with some explanation),
+ rather than bubbling up as low level runtime error.</p>
+ </li>
+ </ul>
+ </li>
+ </ul>
+
+
+
+
+
+<h2 class="content-header header-section2" id="autoid_169">Changes on the Java
side</h2>
+
+
+ <ul>
+ <li>
+ <p>Object wrapping improvements:</p>
+
+ <ul>
+ <li>
+ <p><code class="inline-code">DefaultObjectWrapper</code>,
only with its
+ <code class="inline-code">incompatible_improvements</code>
set to 2.3.22
+ (<a
href="pgui_datamodel_objectWrapper.html#topic.defaultObjectWrapperIcI">see how
+ here...</a>), or more precisely, with its new
+ <code class="inline-code">useAdaptersForContainers</code>
setting set to
+ <code class="inline-code">true</code> (which defaults to
+ <code class="inline-code">true</code> when
+ <code class="inline-code">incompatible_improvements</code>
is set to
+ 2.3.22): It doesn't copy <code
class="inline-code">Map</code>-s,
+ <code class="inline-code">List</code>-s, and arrays anymore
when wrapping
+ them into <code class="inline-code">TemplateModel</code>-s
(which is the
+ interface through with templates access all values), just
+ wraps them into thin <code
class="inline-code">TemplateModel</code>
+ adapters, that will reach the original object for all
+ operations. The wrapped values will be instances of the new
+ <code class="inline-code">DefaultMapAdapter</code>,
+ <code class="inline-code">DefaultListAdapter</code> and
+ <code class="inline-code">DefaultArrayAdapter</code>
classes, instead of
+ the legacy (copying) <code
class="inline-code">SimpleHash</code> and
+ <code class="inline-code">SimpleSequence</code> classes.
(Note that many
+ projects use pure <code
class="inline-code">BeansWrapper</code> instead of
+ <code class="inline-code">DefaultObjectWrapper</code>, which
has always
+ used the adapter approach, albeit a different implementation
+ of it. As the shortcomings of
+ <code class="inline-code">DefaultObjectWrapper</code> are
fixed now, it's
+ always recommended over <code
class="inline-code">BeansWrapper</code>, as
+ <code class="inline-code">BeansWrapper</code> gives quite
confusing
+ multi-typed values and is substantially slower.)</p>
+
+ <p>While keeping backward compatibility as much as
+ possible was an important factor in this change, this is a
+ quite deep change, so you may want to <a
href="#topic.defaultObjectWrapperSwitchToAdapters">review
+ the consequences and reasons here...</a> (But again, this
+ change is <em>not</em> active by default, so
+ merely updating FreeMarker wont risk the stability of
+ existing applications)</p>
+ </li>
+
+ <li>
+ <p>Added <code class="inline-code">TemplateMethodModelEx
+ BeansWrapper.wrap(Object object, Method method)</code>
+ for wrapping methods without wrapping their parent object
+ and without going through overloaded method selection on
+ invocation time.</p>
+ </li>
+
+ <li>
+ <p>Bug fixed [<a
href="http://sourceforge.net/p/freemarker/bugs/372/">372</a>]:
+ <code class="inline-code">ClassCastException</code> when a
+ <code class="inline-code">SortedMap</code> (typically, a
+ <code class="inline-code">TreeMap</code>) is wrapped with
+ <code class="inline-code">DefaultObjectWrapper</code> and
then a 1
+ character long string is get from it that doesn't exist.
To
+ fix the issue, if the wrapped <code
class="inline-code">Map</code> is a
+ <code class="inline-code">SortedMap</code> and it's
wrapped by
+ <code class="inline-code">DefaultObjectWrapper</code>, it
won't try to
+ fall back to a <code class="inline-code">Character</code>
key after with
+ the <code class="inline-code">String</code> key has got
+ <code class="inline-code">null</code>. (This change should
be backward
+ compatible, because when a <code
class="inline-code">SortedMap</code> has
+ <code class="inline-code">Character</code> keys, the initial
attempt with
+ <code class="inline-code">String</code> key causes
+ <code class="inline-code">ClassCastException</code>, thus,
such
+ <code class="inline-code">SortedMap</code>-s were never
usable as FTL
+ hashes.)</p>
+ </li>
+
+ <li>
+ <p>Bug fixed [<a
href="http://sourceforge.net/p/freemarker/bugs/368/">368</a>]:
+ Only with <code
class="inline-code">incompatible_improvements</code> set
+ to 2.3.22 or with its new
+ <code class="inline-code">useAdaptersForContainers</code>
setting set to
+ <code class="inline-code">true</code>: Key order and other
behavioral
+ peculiarities of "custom"
+ <code class="inline-code">Map</code> types isn't lost
anymore. The same
+ stands for <code class="inline-code">List</code>-s too.</p>
+ </li>
+
+ <li>
+ <p>Added new setting,
+ <code
class="inline-code">forceLegacyNonListCollections</code>. This only
+ matters when <code
class="inline-code">useAdaptersForContainers</code> is
+ <code class="inline-code">true</code>. Then, unless you set
this to
+ <code class="inline-code">true</code>,
+ <code class="inline-code">java.util.Collection</code>-s that
aren't
+ <code class="inline-code">List</code>-s (like <code
class="inline-code">Set</code>-s)
+ will continue using <code
class="inline-code">SimpleSequence</code> (i.e.,
+ the copying approach) instead of the adapter approach. The
+ default is <code class="inline-code">false</code>, at least
until
+ <code class="inline-code">incompatible_improvements</code>
2.4.0, because
+ <code class="inline-code">SimpleSequence</code> gave indexed
access to
+ these non-<code class="inline-code">List</code>-s, like in
+ <code class="inline-code">mySet[2]</code>, which is strange
but some
+ existing templates may utilize this, even if only
+ accidentally. With
+ <code
class="inline-code">forceLegacyNonListCollections</code> set to
+ <code class="inline-code">false</code>, indexed access
won't be possible
+ for <code class="inline-code">Set</code>-s and such anymore
(nor will
+ <code class="inline-code">?first</code> and <code
class="inline-code">?last</code> work,
+ but <code class="inline-code">?size</code> will still do),
so you may want
+ to retest old templates. On the other hand, you get the
+ advantages of the adapter approach. Hence, in new projects
+ it's highly recommended to set
+ <code
class="inline-code">forceLegacyNonListCollections</code> to
+ <code class="inline-code">false</code>. (The adapter
approach is
+ implemented by
+ <code
class="inline-code">DefaultNonListCollectionAdapter</code>.)</p>
+ </li>
+
+ <li>
+ <p>Added new, <em>experimental</em> FTL type
+ interface,
+ <code
class="inline-code">freemarker.template.TemplateCollectionModelEx</code>,
+ which adds the <code class="inline-code">size()</code>,
+ <code class="inline-code">isEmpty()</code>, and <code
class="inline-code">boolean
+ contains(TemplateModel)</code> methods to the
+ <code class="inline-code">TemplateCollectionModel</code>
interface. This
+ was added because when wrapping
+ <code class="inline-code">java.util.Collections</code> these
extra
+ capabilities area available anyway, but FTL couldn't tap
on
+ them till now. While the exact interface details are marked
+ as experimental, the feature itself is already utilized for
+ <code class="inline-code">?size</code> when setting the
+ <code
class="inline-code">forceLegacyNonListCollections</code> property of
+ <code class="inline-code">DefaultObjectWrapper</code> to
+ <code class="inline-code">false</code> (see earlier).</p>
+ </li>
+
+ <li>
+ <p>Added new <em>experimental</em> interface,
+ <code
class="inline-code">freemarker.template.ObjectWrapperAndUnwrapper</code>.
+ This extends <code class="inline-code">ObjectWrapper</code>
with
+ unwrapping functionality. This functionality has already
+ existed for a long time in <code
class="inline-code">BeansWrapper</code>
+ and its subclasses, like in
+ <code class="inline-code">DefaultObjectWrapper</code>, but
it wasn't
+ "factored out" into its own published interface
+ that other <code class="inline-code">ObjectWrapper</code>-s
could
+ implement. This is useful for
+ <code class="inline-code">TemplateModel</code>
implementations that don't
+ want to require a <code
class="inline-code">BeansWrapper</code> (or its
+ subclass), only the availability of the unwrapping
+ functionality.</p>
+ </li>
+
+ <li>
+ <p>Added new <em>experimental</em> interfaces
+ to implement <code class="inline-code">?api</code> (see it
in the FTL
+ section): <code
class="inline-code">TemplateModelWithAPISupport</code>,
+ <code class="inline-code">ObjectAPIWrapper</code>,
+ <code class="inline-code">RichObjectWrapper</code>. Note
that while the
+ interfaces are experimental, <code
class="inline-code">?api</code> itself
+ isn't.</p>
+ </li>
+ </ul>
+ </li>
+
+ <li>
+ <p><code class="inline-code">FreemarkerServlet</code>
improvements:</p>
+
+ <ul>
+ <li>
+ <p><code class="inline-code">FreemarkerServlet</code> now
supports
+ custom JSP EL functions (defined in TLD-s with
+ <code class="inline-code">function</code> XML elements).
Earlier it has
+ ignored them. The custom EL function can be called like a
+ Java method, for example: <code
class="inline-code"><#assign
+ u=JspTaglibs["/WEB-INF/utils.tld"]> ...
+ ${u.truncate(title, 25)}</code>.</p>
+ </li>
+
+ <li>
+ <p>Bug fixed: Error message was unhelpful when there was
+ a type mismatch between the actual and the expected type of
+ a custom tag parameter. This was a very frequent problem of
+ users who call JSP taglibs from FTL (the typical
+ "java.lang.IllegalArgumentException: argument type
+ mismatch", without any FTL context). Now it's a
proper error
+ with explanation, solution tip, and FTL error
+ position/quotation.</p>
+ </li>
+
+ <li>
+ <p>RFE resolved [<a
href="https://sourceforge.net/p/freemarker/feature-requests/113/">113</a>]
+ [<a
href="https://sourceforge.net/p/freemarker/feature-requests/114/">114</a>]:
+ <code class="inline-code">FreemarkerServlet</code> can now
discover
+ <code class="inline-code">META-INF/**/*.tld</code>-s that
are visible for
+ the class loader but aren't in
+ <code class="inline-code">WEB-INF/lib/*.jar</code>-s. For
this feature to
+ be active, you must setup the extra TLD lookup with the
+ <code class="inline-code">MetaInfTldSources</code> and/or
+ <code class="inline-code">ClasspathTlds</code>
+ <code class="inline-code">FreemarkerServlet</code>
init-params (see the
+ <a
href="http://freemarker.org/docs/api/freemarker/ext/servlet/FreemarkerServlet.html">Java
+ API documentation of
+ <code>FreemarkerServlet</code></a> for the
+ description of these). For example, if you run your
+ application from Eclipse with an embedded Servlet container,
+ and thus the tag library jar-s aren't on the standard
+ locations but are in the classpath like any other
+ dependencies, now you can just write:</p>
+
+
+
+<div class="code-wrapper"><pre class="code-block
code-unspecified"><init-param>
+ <param-name>MetaInfTldSources</param-name>
+ <param-value>classpath</param-value>
+</init-param></pre></div>
+
+ <p>and then all the <code class="inline-code">META-INF</code>
+ directories that are visible for the class loader will be
+ searched for TLD-s.</p>
+ </li>
+
+ <li>
+ <p><code class="inline-code">MetaInfTldSources</code> and
+ <code class="inline-code">ClasspathTlds</code> can also be
appended to or
+ replaced by the values of Java system properties
+ <code
class="inline-code">org.freemarker.jsp.metaInfTldSources</code> and
+ <code
class="inline-code">org.freemarker.jsp.classpathTlds</code>,
+ respectively. Thus one can adjust these in the Eclipse run
+ configuration without modifying the
+ <code class="inline-code">web.xml</code>. (See the <a
href="http://freemarker.org/docs/api/freemarker/ext/servlet/FreemarkerServlet.html">Java
+ API documentation of
+ <code>FreemarkerServlet</code></a> for
+ more.)</p>
+ </li>
+
+ <li>
+ <p><code class="inline-code">FreemarkerServlet</code> now
recognizes
+ the
+ <code
class="inline-code">org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</code>
+ servlet context attribute, and adds entries to
+ <code class="inline-code">MetaInfTldSources</code>
(introduced above) from
+ it.</p>
+ </li>
+
+ <li>
+ <p>Added <code class="inline-code">protected
+ FreemarkerServlet.createTaglibFactory()</code> to allow
+ fine tuning the settings of the
+ <code class="inline-code">TaglibFactory</code>. It now have
a few setters,
+ like <code class="inline-code">setObjectWrapper</code>,
+ <code class="inline-code">setMetaInfTldSource</code>,
etc.</p>
+ </li>
+
+ <li>
+ <p>Added new servlet init-param,
+ <code class="inline-code">BufferSize</code>. This sets the
buffer size via
+ <code
class="inline-code">HTTPServletResponse.setBufferSize()</code> if
+ the response state still allows that, ignores it
+ otherwise.</p>
+ </li>
+
+ <li>
+ <p>The <code class="inline-code">TemplatePath</code> servlet
init-param
+ now supports a new kind of path, that looks like
+ <code
class="inline-code">classpath:com/example/myapp/templates</code>.
+ This is similar to the old
+ <code
class="inline-code">class://com/example/myapp/templates</code>, but
+ it uses the Thread Context Class Loader of the thread that
+ initializes <code
class="inline-code">FreemarkerSerlvet</code>, and thus
+ will work even if <code
class="inline-code">freemarker.jar</code> is not
+ local to the web application. <code
class="inline-code">class://</code>
+ has the problem that it uses the defining class loader of
+ <code class="inline-code">FreemarkerSerlvet</code> itself
(or of its
+ subclass).</p>
+ </li>
+
+ <li>
+ <p>If <code
class="inline-code">incompatible_improvements</code> is set
+ to 2.3.22 (or higher), the <code
class="inline-code">TemplatePath</code>
+ servlet init-param supports specifying multiple comma
+ separated paths inside
+ <code class="inline-code">[<em
class="code-color">...</em>]</code>, like
+ <code class="inline-code"><param-value>[
WEB-INF/templates,
+ classpath:com/example/myapp/templates
+ ]</param-value></code>. This internally creates a
+ <code
class="inline-code">freemarker.cache.MultiTemplateLoader</code>.</p>
+ </li>
+
+ <li>
+ <p>Added new servlet <code
class="inline-code">init-param</code>,
+ <code class="inline-code">ExceptionOnMissingTemplate</code>.
Setting this
+ to <code class="inline-code">true</code> changes the
behavior on
+ template-not-found errors to similar to what you experience
+ with other kind of template exceptions (a HTTP 500
+ "Internal Server error" response on most
+ setups). When it's <code
class="inline-code">false</code> (the legacy
+ behavior), you only get a HTTP 404 "Not found".
+ While that's also how JSP views work, this turns out to
be a
+ problem, because some frameworks give 404 to the visitor too
+ if the MVC view gives 404. But to get to the point where you
+ forward to the MVC View, the visitor had to visit a valid
+ URL, only that page misses its View, so its broken on the
+ server side, so it should be a 500.</p>
+ </li>
+
+ <li>
+ <p>Added new overridable method:
+ <code
class="inline-code">FreemarkerServlet.createDefaultObjectWrapper()</code>.
+ This can be used for what
+ <code class="inline-code">createObjectWrapper()</code> is
usually
+ overridden for, but without unwillingly disabling the
+ processing of the related init-params (like of
+ <code class="inline-code">object_wrapper</code>).</p>
+ </li>
+
+ <li>
+ <p>Improved (or fixed) error logging: Now logs will
+ always get into FreeMarker's own log, not only into the
+ servlet container log. Also, earlier template-not-found and
+ template parsing error details logs were sometimes lost,
+ depending on the servlet container.</p>
+ </li>
+
+ <li>
+ <p>Bug fixed, only active with
+ <code class="inline-code">incompatible_improvements</code>
set to 2.3.22
+ (or higher): Some kind of values, when put into the JSP
+ <em>page</em> scope (via
+ <code class="inline-code">#global</code> or via the JSP
+ <code class="inline-code">PageContext</code> API) and later
read back with
+ the JSP <code class="inline-code">PageContext</code> API
(typically in a
+ custom JSP tag), might come back as FreeMarker
+ <code class="inline-code">TemplateModel</code> objects
instead of as
+ objects with a standard Java type. Other Servlet scopes
+ aren't affected. It's highly unlikely that something
expects
+ the presence of this bug. The affected values are of the FTL
+ types listed below, and to trigger the bug, they either had
+ to be created directly in the template (like as an FTL
+ literal or with
+ <code class="inline-code">?date</code>/<code
class="inline-code">time</code>/<code class="inline-code">datetime</code>),
+ or you had to use <code
class="inline-code">DefaultObjectWrapper</code> or
+ <code class="inline-code">SimpleObjectWrapper</code> (or a
subclass of
+ them):</p>
+
+ <ul>
+ <li>
+ <p>FTL date/time/date-time values may came back as
+ <code
class="inline-code">freemarker.template.SimpleDate</code>-s, now
+ they come back as <code
class="inline-code">java.util.Date</code>-s
+ instead.</p>
+ </li>
+
+ <li>
+ <p>FTL sequence values may came back as
+ <code class="inline-code">SimpleSequence</code>-s, now
they come back
+ as <code class="inline-code">java.util.List</code>-s as
expected. This
+ stands assuming that the
+ <code class="inline-code">object_wrapper</code>
configuration setting
+ is a subclass of <code
class="inline-code">BeansWrapper</code> (such
+ as <code
class="inline-code">DefaultObjectWrapper</code>), but that's
+ practically always the case in applications that use
+ FreeMarker's JSP extension (otherwise it can still
work,
+ but it depends on the quality and capabilities of the
+ <code class="inline-code">ObjectWrapper</code>
implementation).</p>
+ </li>
+
+ <li>
+ <p>FTL hash values may came back as
+ <code class="inline-code">SimpleHash</code>-es, now they
come back as
+ <code class="inline-code">java.util.Map</code>-s as
expected (again,
+ assuming that the object wrapper is a subclass of
+ <code class="inline-code">BeansWrapper</code>).</p>
+ </li>
+
+ <li>
+ <p>FTL collection values may came back as
+ <code class="inline-code">SimpleCollection</code>-s, now
they come
+ back as <code
class="inline-code">java.util.Collection</code>-s as
+ expected (again, assuming that the object wrapper is a
+ subclass of <code
class="inline-code">BeansWrapper</code>).</p>
+ </li>
+ </ul>
+ </li>
+
+ <li>
+ <p>Bug fixed: Now <code class="inline-code">*.tld</code>
files are
+ searched in <code class="inline-code">WEB-INF/</code> and in
all its
+ subdirectories recursively. Earlier they were only searched
+ directly under <code class="inline-code">WEB-INF/</code> and
+ <code class="inline-code">WEB-INF/lib/</code>.</p>
+ </li>
+
+ <li>
+ <p>Bug fixed: Leading and trailing whitespace in TLD-s
+ inside the <code class="inline-code">name</code> and
+ <code class="inline-code">tag-class</code> elements is now
removed.</p>
+ </li>
+
+ <li>
+ <p>Unwanted behavior fixed: In case multiple TLD-s map to
+ the same tag library URI, now
+ <code class="inline-code">WEB-INF/**/*.tld</code>-s has
priority over
+ <code class="inline-code">META-INF/**/*.tld</code>-s coming
from jar-s or
+ classpath directories. Earlier, it was the other way around,
+ except that <code
class="inline-code">META-INF/lib/*.tld</code>-s could
+ still take precedence randomly. While the JSP specification
+ (2.2) explicitly states that the order is not defined and
+ shouldn't be relied upon, it's just logical that if
someone
+ puts a TLD directly under <code
class="inline-code">WEB-INF</code>, he
+ meant that to be used in that particular web application,
+ rather than the TLD-s coming from the dependency jars which
+ are often shared by multiple web applications.</p>
+ </li>
+
+ <li>
+ <p>Bug fixed: Defaults set in an overridden
+ <code
class="inline-code">FreemarkerServlet.createConfiguration</code>
+ won't be accidentally overwritten by
+ <code class="inline-code">FreemarkerServlet</code>'s
factory defaults
+ anymore. This was a problem with theses settings only:
+ <code class="inline-code">template_exception_handler</code>,
+ <code class="inline-code">log_template_exceptions</code>,
+ <code class="inline-code">object_wrapper</code>,
+ <code class="inline-code">template_loader</code>.</p>
+ </li>
+
+ <li>
+ <p>Bug fixed: If you had multiple
+ <code class="inline-code">FreemarkerServlet</code>-s with
different
+ configuration settings in the same servlet context, that
+ could lead to malfunction. (Normally, you only have one,
+ just like there's only one servlet that processes
+ <code class="inline-code">*.jsp</code>.)</p>
+ </li>
+
+ <li>
+ <p>Removed all the <code class="inline-code">xsd</code> files
+ (<code class="inline-code">web-app</code> and <code
class="inline-code">taglib</code>
+ schemas) from the FreeMarker artifact and from the XML
+ entity resolver, as they were unused during XML
+ parsing.</p>
+ </li>
+
+ <li>
+ <p>Generally improved implementation quality
+ (maintainability, error messages, performance bug fixes,
+ test coverage) and better API documentation.</p>
+ </li>
+ </ul>
+ </li>
+
+ <li>
+ <p>Logging facility improvements:</p>
+
+ <ul>
+ <li>
+ <p>Just like earlier, when auto-selecting the logger
+ library (the default behavior), FreeMarker choses Log4j if
+ it's available. But now, if that turns out to be
+ <code class="inline-code">log4j-over-slf4j</code>,
FreeMarker will use
+ SLF4J directly instead. (This fixes the issue where the
+ logged location points to FreeMarker's log adapter class
+ instead of the real call place.)</p>
+ </li>
+
+ <li>
+ <p>FreeMarker now recognizes the
+ <code
class="inline-code">org.freemarker.loggerLibrary</code> system
+ property, which specifies which logger to use, like
+ <code class="inline-code">java <em
class="code-color">...</em>
+ -Dorg.freemarker.loggerLibrary=SLF4J</code>. This option
+ deprecates
+ <code
class="inline-code">Logger.selectLoggerLibrary(int)</code> as that
+ was inherently unreliable (because you usually can't
control
+ class initialization order very well). The system property
+ has precedence over
+ <code
class="inline-code">Logger.selectLoggerLibrary</code>.</p>
+ </li>
+
+ <li>
+ <p>Generally improved implementation quality (more info
+ printed when something fails, etc.).</p>
+ </li>
+
+ <li>
+ <p>New configuration setting:
+ <code class="inline-code">log_template_exceptions</code>
+ (<code
class="inline-code">Configuration.setLogTemplateExceptions(boolean)</code>).
+ This specifies if <code
class="inline-code">TemplateException</code>-s
+ thrown by template processing are logged by FreeMarker or
+ not. The default is <code class="inline-code">true</code>
for backward
+ compatibility, but that results in logging the exception
+ twice in properly written applications, because there the
+ <code class="inline-code">TemplateException</code> thrown by
the public
+ FreeMarker API is also logged by the caller (even if only as
+ the cause exception of a higher level exception). Hence, in
+ modern applications it should be set to
+ <code class="inline-code">false</code>. (Note that this
setting has no
+ effect on the logging of exceptions caught by
+ <code class="inline-code">#attempt</code>/<code
class="inline-code">#recover</code>;
+ those are always logged.)</p>
+ </li>
+ </ul>
+ </li>
+
+ <li>
+ <p><code class="inline-code">Environment</code> and custom
directive
+ related improvements:</p>
+
+ <ul>
+ <li>
+ <p>Added
+ <code
class="inline-code">Environment.getCurrentDirectiveCallPlace()</code>,
+ which returns a <code
class="inline-code">DirectiveCallPlace</code> object
+ when called from a custom directive (i.e., from
+ <code
class="inline-code">TemplateDirectiveModel.execute()</code>). The
+ <code class="inline-code">DirectiveCallPlace</code> objects
lets you
+ associate an arbitrary object to the directive invocation
+ inside the template, which can be used for call-place-bound
+ caching (like the minification of non-dynamic nested
+ content). See <code
class="inline-code">DirectiveCallPlace</code> in the
+ Java API documentation for more.</p>
+ </li>
+
+ <li>
+ <p>Added
+ <code
class="inline-code">Environment.getMainTemplate()</code>. Deprecated
+ the ambiguous (and often broken: [<a
href="https://sourceforge.net/p/freemarker/bugs/145/">145</a>])
+ <code
class="inline-code">Environment.getTemplate()</code>.</p>
+ </li>
+ </ul>
+ </li>
+
+ <li>
+ <p>Template loading:</p>
+
+ <ul>
+ <li>
+ <p>Added new <code class="inline-code">Configuration</code>
setting,
+ <code class="inline-code">template_lookup_strategy</code>
+ (<code
class="inline-code">Configuration.setTemplateLookupStrategy(TemplateLookupStrategy)</code>).
+ This allows customizing what
+ <code class="inline-code">TemplateLoader</code>-level names
will be tried
+ when a template is requested. With this you can, for
+ example, define a custom localized lookup sequence instead
+ of the default (which looks like:
+ <code class="inline-code">foo_de_LU_MAC.ftl, foo_de_LU.ftl,
+ foo_de.ftl,</code><code class="inline-code">
foo.ftl</code>).</p>
+ </li>
+
+ <li>
+ <p>Added new
+ <code class="inline-code">Configuration.getTemplate(<em
class="code-color">...</em>)</code>
+ parameter, <code class="inline-code">Object
customLookupCondition</code>.
+ This parameter can be used by custom a
+ <code class="inline-code">TemplateLookupStrategy</code> to
deduce the
+ actual template name(s) from the requested name (similarly
+ to as the default lookup strategy does that based on the
+ locale). For example, on a multi-domain Web site, one may
+ want to define some templates that are specialized to a
+ domain, and thus use the domain name as the custom lookup
+ condition. Then, when <code
class="inline-code">foo.ftl</code> is
+ requested, a custom
+ <code class="inline-code">TemplateLookupStrategy</code>
could first look
+ for <code
class="inline-code">@somedomain.com/foo.ftl</code>, and then for
+ <code class="inline-code">@default/foo.ftl</code>. See the
JavaDoc of the
+ relevant
+ <code class="inline-code">Configuration.getTemplate(<em
class="code-color">...</em>)</code>
+ overload for more details; note there the requirements
+ regarding the <code class="inline-code">hashCode</code> and
+ <code class="inline-code">equals</code> of the
+ <code class="inline-code">customLookupCondition</code>.</p>
+ </li>
+
+ <li>
+ <p>Added new <code class="inline-code">Configuration</code>
setting,
+ <code class="inline-code">template_name_format</code>
+ (<code
class="inline-code">Configuration.setTemplateNameFormat(TemplateNameFormat)</code>).
+ This allows specifying the naming rules used by FreeMarker.
+ For now, custom implementations aren't allowed, and you
can
+ only chose between
+ <code
class="inline-code">TemplateNameFormat.DEFAULT_2_3_0</code> (the
+ default) and <code class="inline-code">DEFAULT_2_4_0</code>
(recommended,
+ at least for new projects). <code
class="inline-code">DEFAULT_2_4_0</code>
+ has several advantages, but isn't fully backward
compatible
+ (though most applications won't be affected). For typical
+ mistakes like using backslash instead of slash, or backing
+ out of the root, it gives
+ <code
class="inline-code">MalformedTemplateNameFormatException</code>
+ instead of <code
class="inline-code">TempalteNotFoundException</code>. It
+ allows scheme names to be terminated with
+ <code class="inline-code">:</code> alone, instead of a
+ <code class="inline-code">://</code> (which is also
supported), like in
+ <code class="inline-code">classpath:foo/bar.ftl</code>. It
fixes numerous
+ legacy glitches (bugs), mostly related to the interpretation
+ of <code class="inline-code">..</code> after special steps
like
+ <code class="inline-code">.</code> or <code
class="inline-code">*</code>. See the full
+ list of differences in the <a
href="http://freemarker.org/docs/api/freemarker/cache/TemplateNameFormat.html#DEFAULT_2_4_0">Java
+ API documentation of
+ <code>TemplateNameFormat.DEFAULT_2_4_0</code></a>.</p>
+ </li>
+
+ <li>
+ <p><code class="inline-code">ClassTemplateLoader</code> now
can be
+ created by specifying a <code
class="inline-code">ClassLoader</code>
+ directly, rather than by specifying a base
+ <code class="inline-code">Class</code>. That is, now
there's
+ <code class="inline-code">ClassTemplateLoader(ClassLoader,
String)</code>
+ constructor, and also a
+ <code
class="inline-code">Configuration.setClassLoaderForTemplateLoading(ClassLoader,
+ String)</code> method.</p>
+ </li>
+
+ <li>
+ <p>Added new exception,
+ <code class="inline-code">TemplateNotFoundException</code>,
which is now
+ used instead of <code
class="inline-code">TemplateNotFoundException</code>
+ when getting a template. As it extends
+ <code class="inline-code">TemplateNotFoundException</code>,
this change is
+ backward compatible. The main goal was to counter the common
+ misunderstanding that template paths are real file paths.
+ However, the new exception also has the benefit that it can
+ give additional FreeMarker-specific information about the
+ error, like right now it has
+ <code class="inline-code">getTemplateName()</code> and
+ <code class="inline-code">getCustomLookupCondition()</code>
+ methods.</p>
+ </li>
+
+ <li>
+ <p><code class="inline-code">Template</code>-s now have a
+ <code class="inline-code">getSourceName()</code> method, in
additionally
+ to <code class="inline-code">getName()</code>. These two
return the same
+ as far as no localized lookup or acquisition
+ (<code class="inline-code">*</code> in the name) or other
lookup strategy
+ was actively involved. But when it was,
+ <code class="inline-code">getSourceName()</code> gives the
name with which
+ the template was actually loaded from the
+ <code class="inline-code">TemplateLoader</code>, while
+ <code class="inline-code">getName()</code> returns (and had
always
+ returned) the name with which the template was requested (in
+ canonicalized form). <code
class="inline-code">getName()</code> is used
+ for everything (like for relative inclusion resolution),
+ except for location information in error messages, which now
+ uses <code class="inline-code">getSourceName()</code>. Also,
+ <code class="inline-code">TemplateException</code> now has a
+ <code class="inline-code">getSourceName()</code> method.</p>
+ </li>
+
+ <li>
+ <p><code class="inline-code">Configuration.getTemplate(<em
class="code-color">...</em>)</code>
+ overloads now accept <code class="inline-code">null</code>
for the
+ <code class="inline-code">locale</code> and <code
class="inline-code">encoding</code>
+ parameters, in which case they use the same defaults as the
+ overloads where the parameter is omitted.</p>
+ </li>
+
+ <li>
+ <p>Debugger SPI implementators, attention: The
+ <code class="inline-code">DebugBreak</code> instruction will
now send the
+ <code class="inline-code">sourceName</code> of the template
to the
+ <code class="inline-code">suspendEnvironmentSpi</code>
callback, rather
+ than its <code class="inline-code">name</code>. You should
also use the
+ <code class="inline-code">sourceName</code> in
+ <code class="inline-code">registerTemplateSpi</code> and
such, not the
+ <code class="inline-code">name</code>.</p>
+ </li>
+ </ul>
+ </li>
+
+ <li>
+ <p>Configuration:</p>
+
+ <ul>
+ <li>
+ <p>Added
+ <code class="inline-code">Configuration.unset<em
class="code-color">Xxx</em></code>
+ and
+ <code class="inline-code">is<em
class="code-color">Xxx</em>ExplicitlySet</code>
+ methods for several settings. Unsetting a setting makes it
+ behave as if
+ <code class="inline-code">set<em
class="code-color">Xxx</em></code> was
+ never called, thus the setting will use the default value
+ that fits the current
+ <code class="inline-code">incompatible_improvements</code>
value and will
+ be adjusted as <code
class="inline-code">incompatible_improvements</code>
+ is changed later.</p>
+ </li>
+
+ <li>
+ <p>When configuring FreeMarker from
+ <code class="inline-code">java.util.Properties</code> (or
with
+ <code class="inline-code">String</code>-<code
class="inline-code">String</code>
+ name-value pairs in general):</p>
+
+ <ul>
+ <li>
+ <p>The <code class="inline-code">default</code> setting
value is
+ now recognized by
+ <code
class="inline-code">template_exception_handler</code>,
+ <code class="inline-code">template_storage</code>,
+ <code class="inline-code">template_loader</code> (and by
the new
+ <code
class="inline-code">template_lookup_strategy</code> and
+ <code class="inline-code">template_name_format</code>)
settings, and
+ it causes
+ <code class="inline-code">Configuration.unset<em
class="code-color">Xxx</em>()</code>
+ to be called.</p>
+ </li>
+
+ <li>
+ <p>Bug fixed: When setting
+ <code class="inline-code">object_wrapper</code> to
+ <code class="inline-code">default</code> (as opposed to
not specifying
+ it), it has ignored the
+ <code
class="inline-code">incompatible_improvements</code> and has
+ always used
+ <code
class="inline-code">ObjectWrapper.DEFAULT_WRAPPER</code>. This
+ fix only matters when
+ <code
class="inline-code">incompatible_improvements</code> is exactly
+ 2.3.21, as that's when the default object wrapper was
+ changed from
+ <code
class="inline-code">ObjectWrapper.DEFAULT_WRAPPER</code> to the
+ result of <code class="inline-code">new
+
DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_21).build()</code>,
+ which is a bit different singleton, as it has read-only
+ configuration settings and bug fixed overloaded method
+ selection rules. To use
+ <code
class="inline-code">ObjectWrapper.DEFAULT_WRAPPER</code>
+ regardless of the value of the
+ <code
class="inline-code">incompatible_improvements</code> setting,
+ use the new <code
class="inline-code">default_2_3_0</code>
+ value.</p>
+ </li>
+ </ul>
+ </li>
+
+ <li>
+ <p>Bug fixed: Changing the value of the
+ <code class="inline-code">localized_lookup</code> setting
now empties the
+ template cache, so that old lookup results won't be
reused.
+ (This of course only matters if you change this setting
+ under an already running service, which is very
+ unlikely.)</p>
+ </li>
+ </ul>
+ </li>
+
+ <li>
+ <p>Miscellaneous:</p>
+
+ <ul>
+ <li>
+ <p>Bug fixed [<a
href="https://sourceforge.net/p/freemarker/bugs/145/">145</a>],
+ active only with
+ <code class="inline-code">incompatible_improvements</code>
set to 2.3.22
+ (or higher): <code class="inline-code">#include</code> and
+ <code class="inline-code">#nested</code> doesn't change
the parent
+ <code class="inline-code">Template</code> (see
+ <code class="inline-code">Configurable.getParent()</code>)
of the
+ <code class="inline-code">Environment</code> anymore to the
+ <code class="inline-code">Template</code> that's
included or where
+ <code class="inline-code">#nested</code> "returns" to. Thus,
+ the parent of <code class="inline-code">Environment</code>
will be now
+ always the main <code class="inline-code">Template</code>.
(The main
+ <code class="inline-code">Template</code> is the
+ <code class="inline-code">Template</code> whose <code
class="inline-code">process</code>
+ or <code
class="inline-code">createProcessingEnvironment</code> method was
+ called to initiate the output generation.) Note that this
+ only matters if you have set settings directly on
+ <code class="inline-code">Template</code> objects (not to be
confused with
+ setting settings in templates via
+ <code class="inline-code">#setting</code>, which just
modifies the
+ <code class="inline-code">Environment</code>, and so
isn't affected by
+ this fix), and almost nobody does that. Also note that macro
+ calls have never changed the <code
class="inline-code">Environment</code>
+ parent to the <code class="inline-code">Template</code> that
contains the
+ macro definition, so there's no change there now.</p>
+ </li>
+
+ <li>
+ <p>Bug fixed [<a
href="https://sourceforge.net/p/freemarker/bugs/419/">419</a>]:
+ FreeMarker doesn't fail anymore when it has no
permission to
+ read Java system properties, like when used in unsigned
+ applets. It just logs some warnings.</p>
+ </li>
+
+ <li>
+ <p><code class="inline-code">HTML_DEBUG</code> and
+ <code class="inline-code">DEBUG</code>
+ <code class="inline-code">TemplateExceptionHandler</code>
output now
+ contains a warning like "HTML_DEBUG mode; use RETHROW
+ in production!", due to frequent misuse.</p>
+ </li>
+
+ <li>
+ <p>Some fixes and improvements in template canonical form
+ output, and as a consequence of that, in FTL stack trace
+ instruction displaying.</p>
+ </li>
+
+ <li>
+ <p>Marked some historically public but otherwise internal
+ API-s as deprecated, so that the disclaimer is more apparent
+ in IDE-s.</p>
+ </li>
+ </ul>
+ </li>
+ </ul>
+
+
+
+
+
+<h2 class="content-header header-section2" id="autoid_170">Notes</h2>
+
+
+ <p><a name="topic.defaultObjectWrapperSwitchToAdapters"></a>The
+ consequences and reasons of introducing adapter approach for
+ container types in <code
class="inline-code">DefaultObjectWrapper</code> when its
+ incompatibleImprovements is set to 2.3.22:</p>
+
+ <ul>
+ <li>
+ <p>With the new approach (the adapter approach), the key
+ order of <code class="inline-code">Map</code>-s is never lost.
The copying
+ approach could only keep that for <code
class="inline-code">HashMap</code>
+ subclasses (such as <code
class="inline-code">LinkedHashMap</code>) and
+ <code class="inline-code">SortedMap</code>-s (such as
+ <code class="inline-code">TreeMap</code>), but not for more
exotic
+ <code class="inline-code">Map</code>-s, like Guava's
+ <code class="inline-code">ImmutableMap</code>. Also, any other
behavioral
+ peculiarities of the original <code
class="inline-code">Map</code> (e.g., case
+ insensitive key lookup) is kept now.</p>
+ </li>
+
+ <li>
+ <p>The exact type and identity of the
+ <code class="inline-code">Map</code>/<code
class="inline-code">List</code> is kept when the
+ wrapped value is passed back to a Java method from the template.
+ With the legacy approach the Java methods have received a
+ <code class="inline-code">Map</code> or <code
class="inline-code">List</code> of a special
+ FreeMarker specific type (that acted as an adapter for the
+ <code class="inline-code">TemplateModel</code>).</p>
+ </li>
+
+ <li>
+ <p>Performance characteristics change, mostly for the better,
+ but it depends on the application. If the template reads the
+ <em>same(!)</em> entry <em>from the data
+ model</em> roughly once or twice (or not at all), which is
+ typical, them the adapter approach gives better results,
+ otherwise the legacy copying approach is faster (as it can reuse
+ the wrapped entry from the previous read), though this slowdown
+ certainly not a concern for most applications. The performance
+ of the new adapter approach is more predictable, because it has
+ no initial "spike" to set up the container copy
+ (especially painful for huge collections), instead the
+ performance is linearly proportional to the number of data model
+ reads (and not to the number of collection entries).</p>
+ </li>
+
+ <li>
+ <p>If the
+ <code class="inline-code">Map</code>/<code
class="inline-code">List</code>/array is changed
+ after it was wrapped, the change will now become visible in the
+ data-model. With the copying approach, the wrapped value was a
+ shallow-snapshot of the original
+ <code class="inline-code">Map</code>/<code
class="inline-code">List</code>/array. While it's
+ unlikely that someone has deliberately utilized this, it's a
+ risk factor when switching to adapters.</p>
+ </li>
+
+ <li>
+ <p>It's theoretically possible that some code (mostly
+ <code class="inline-code">TemplateDirectiveModel</code>
implementations)
+ mistakenly assumed that wrapped <code
class="inline-code">Map</code>-s are
+ <code class="inline-code">SimpleHash</code>-es, and wrapped
+ <code class="inline-code">List</code>-s are
+ <code class="inline-code">SimpleSequence</code>-s, etc., instead
of them just
+ being <code class="inline-code">TemplateHashModel</code>-s and
+ <code class="inline-code">TemplateSequenceModel</code>-s. Such
code was always
+ wrong, but now it will indeed break, so it's a risk
+ factor.</p>
+ </li>
+
+ <li>
+ <p>As now the exact type of the wrapped original object is
+ used for overloaded method selection, the choice can be
+ different (and similar to what it would be with pure
+ <code class="inline-code">BeansWrapper</code>). It's
difficult to find cases
+ where this matters. A change is most probable around arrays, as
+ with the copying approach they were unwrapped to
+ <code class="inline-code">List</code>-s, not to the original
array. As the
+ overloaded method mechanism can convert between arrays and lists
+ (in both directions), it's usually not a problem. But, it
+ doesn't do conversion between different array types when the
+ overloaded method has various types on the parameter position of
+ the array, so that's a risk factor.</p>
+ </li>
+
+ <li>
+ <p><code class="inline-code">SimpleHash</code> and
+ <code class="inline-code">SimpleSequence</code> haven't
become deprecated.
+ They are still used for hashes and sequences created in FTL, and
+ are recommended for values that are built specifically to be
+ used from templates, rather than wrapping an already existing
+ <code class="inline-code">Map</code> or <code
class="inline-code">List</code> or
+ array.</p>
+ </li>
+
+ <li>
+ <p><code class="inline-code">List</code>-s and <code
class="inline-code">Map</code>-s
+ that are exposed to templates in multiple threads are now under
+ greater stress regarding their correct operation under
+ multi-threaded read-only access. This is because the adapters
+ won't copy their contents into well known
+ <code class="inline-code">List</code> and <code
class="inline-code">Map</code>
+ implementations (<code class="inline-code">HashMap</code>,
+ <code class="inline-code">ArrayList</code>, etc.) before
accessing them from
+ multiple threads. So this is mostly a concern with custom
+ <code class="inline-code">List</code> and <code
class="inline-code">Map</code>
+ implementations, which aren't as mature as the standard Java
+ classes. Note that this was always like so with pure
+ <code class="inline-code">BeansWrapper</code>, which is used by
a lot of
+ projects/frameworks (like by Struts) for a long time, so it's
+ not an uncharted territory.</p>
+ </li>
+
+ <li>
+ <p>When the wrapped <code class="inline-code">List</code> is a
+ <code class="inline-code">AbstractSequentialList</code> (like a
+ <code class="inline-code">LinkedList</code>), the resulting
adapter will
+ implement <code
class="inline-code">TemplateCollectionModel</code> for more
+ efficient enumeration (<code
class="inline-code">#list</code>-ing), in
+ additionally to <code
class="inline-code">TemplateSequenceModel</code> of
+ course. <code class="inline-code">TemplateCollectionModel</code>
allows FTL to
+ traverse the list without accessing elements by index. With the
+ legacy copying approach
+ <code class="inline-code">TemplateCollectionModel</code>
wasn't implemented as
+ it wasn't needed for efficient enumeration there.</p>
+ </li>
+
+ <li>
+ <p>Iterators (when you put them directly into the data-model)
+ are wrapped into <code
class="inline-code">DefaultIteratorAdapter</code>
+ instead of <code class="inline-code">SimpleCollection</code>.
This has two
+ consequences:</p>
+
+ <ul>
+ <li>
+ <p>The wrapped <code class="inline-code">Iterator</code> is
now
+ unwrapped properly to the original Java object when it's
+ passed to Java method from the template.</p>
+ </li>
+
+ <li>
+ <p>Wrapped <code class="inline-code">Iterator</code>-s (not
to be
+ confused with <code class="inline-code">Iterable</code>)
aren't
+ thread-safe anymore, to spare some synchronizations, after
+ all, exposing the same <code
class="inline-code">Iterator</code> to
+ multiple parallel template executions doesn't make much
+ sense. This shouldn't be a migration concern, as even
+ earlier, only one of those template executions could succeed
+ (the "content" of <code class="inline-code">Iterator</code>-s
+ wasn't copied, so the one who first accessed it become
the
+ exclusive owner). The change is just that earlier it was
+ guaranteed that the other threads will fail (that was the
+ thread-safe about it), while now there are no such
+ guarantees.</p>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ <div class="bottom-pagers-wrapper"><div class="pagers bottom"><a
class="paging-arrow previous"
href="versions_2_3_23.html"><span>Previous</span></a><a class="paging-arrow
next" href="versions_2_3_21.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="http://freemarker.org/">What is FreeMarker?</a></li><li><a
href="http://freemarker.org/freemarkerdownload.html">Download</a></li><li><a
href="app_versions.html">Version history</a></li><li><a
href="http://freemarker.org/history.html">About us</a></li><li><a
itemprop="license" href="app_license.html">License</a></li></ul></div><div
class="column"><h3 class="column-header">Handy stuff</h3><ul><li><a
href="http://freemarker-online.kenshoo.com/">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></ul></div><div
class="column"><h3 class="column-header">Community</h3><ul><li><a href
="https://github.com/freemarker/freemarker">FreeMarker on
Github</a></li><li><a href="https://twitter.com/freemarker">Follow us on
Twitter</a></li><li><a
href="https://issues.apache.org/jira/browse/FREEMARKER/">Report a
bug</a></li><li><a
href="http://stackoverflow.com/questions/ask?tags=freemarker">Ask a
question</a></li><li><a href="http://freemarker.org/mailing-lists.html">Mailing
lists</a></li></ul></div></div><div class="col-right"><ul
class="social-icons"><li><a class="github"
href="https://github.com/freemarker/freemarker">Github</a></li><li><a
class="twitter" href="https://twitter.com/freemarker">Twitter</a></li><li><a
class="stack-overflow"
href="http://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="2017-03-13T10:55:28Z" title="Monday,
March 13, 2017 10:55:28 AM GMT">2017-03-13 10:55:28 GMT</time>, for Freemarker
2.3.26 </p>
+<p class="copyright">
+© <span itemprop="copyrightYear">1999</span>â2017
+<a itemtype="http://schema.org/Organization" itemprop="copyrightHolder"
href="http://apache.org/">The Apache Software Foundation</a>. Apache
FreeMarker, FreeMarker, Apache Incubator, Apache, the Apache FreeMarker logo
are trademarks of The Apache Software Foundation. </p>
+</div></div></div></body>
+</html>