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&#39;s always clearly indicated),
+        because they could, with very small chance, break existing
+        applications. For actively maintained applications it&#39;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&#39;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(&quot;myMethod&quot;)).invoke(...)</code> in Java, 
thus you
+              can&#39;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(&quot;myProperty&quot;)</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&#39;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&#39;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">&lt;@box
+              class=&quot;someCssClass&quot; data\-id=product.id /&gt;</code>. 
(When
+              you enumerate the catch-all parameter names inside the macro,
+              the key string you get is <code 
class="inline-code">&quot;data-id&quot;</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">&quot;a&quot;</code>, <code 
class="inline-code">&quot;b&quot;</code>,
+              <code class="inline-code">&quot;c&quot;</code>, etc. (or for 
<code class="inline-code">&quot;A&quot;</code>,
+              <code class="inline-code">&quot;B&quot;</code>, <code 
class="inline-code">&quot;C&quot;</code>, etc.). When
+              reaching <code class="inline-code">&quot;z&quot;</code>, it 
continues like
+              <code class="inline-code">&quot;aa&quot;</code>, <code 
class="inline-code">&quot;ab&quot;</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">&quot;foo.bar.txt&quot;?keep_before_last(&quot;.&quot;)</code>
 returns
+              <code class="inline-code">&quot;foo.bar&quot;</code>,
+              <code 
class="inline-code">&quot;foo.bar.txt&quot;?keep_after_last(&quot;.&quot;)</code>
 returns
+              <code class="inline-code">&quot;txt&quot;</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>&#39;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&#39;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&#39;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&#39;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&#39;s 
wrapped by
+                  <code class="inline-code">DefaultObjectWrapper</code>, it 
won&#39;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&#39;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&#39;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&#39;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&#39;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&#39;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&#39;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&#39;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&#39;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">&lt;#assign
+                  u=JspTaglibs[&quot;/WEB-INF/utils.tld&quot;]&gt; ...
+                  ${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
+                  &quot;java.lang.IllegalArgumentException: argument type
+                  mismatch&quot;, without any FTL context). Now it&#39;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&#39;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&#39;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">&lt;init-param&gt;
+  &lt;param-name&gt;MetaInfTldSources&lt;/param-name&gt;
+  &lt;param-value&gt;classpath&lt;/param-value&gt;
+&lt;/init-param&gt;</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">&lt;param-value&gt;[ 
WEB-INF/templates,
+                  classpath:com/example/myapp/templates
+                  ]&lt;/param-value&gt;</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&#39;s <code 
class="inline-code">false</code> (the legacy
+                  behavior), you only get a HTTP 404 "Not found".
+                  While that&#39;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&#39;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&#39;t affected. It&#39;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&#39;s
+                      practically always the case in applications that use
+                      FreeMarker&#39;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&#39;t be relied upon, it&#39;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&#39;t be accidentally overwritten by
+                  <code class="inline-code">FreemarkerServlet</code>&#39;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&#39;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&#39;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&#39;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&#39;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&#39;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&#39;t fully backward 
compatible
+                  (though most applications won&#39;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&#39;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&#39;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&#39;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&#39;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&#39;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&#39;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&#39;s no change there now.</p>
+                </li>
+
+                <li>
+                  <p>Bug fixed [<a 
href="https://sourceforge.net/p/freemarker/bugs/419/";>419</a>]:
+                  FreeMarker doesn&#39;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&#39;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&#39;s
+              unlikely that someone has deliberately utilized this, it&#39;s a
+              risk factor when switching to adapters.</p>
+            </li>
+
+            <li>
+              <p>It&#39;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&#39;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&#39;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&#39;s usually not a problem. But, it
+              doesn&#39;t do conversion between different array types when the
+              overloaded method has various types on the parameter position of
+              the array, so that&#39;s a risk factor.</p>
+            </li>
+
+            <li>
+              <p><code class="inline-code">SimpleHash</code> and
+              <code class="inline-code">SimpleSequence</code> haven&#39;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&#39;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&#39;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&#39;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&#39;t implemented as
+              it wasn&#39;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&#39;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&#39;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&#39;t make much
+                  sense. This shouldn&#39;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&#39;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>

Reply via email to