blob: 02ec4d814918b9bec3affbd2b59893b7d14000f0 [file] [log] [blame]
<!doctype html>
<!-- Generated by FreeMarker/Docgen from DocBook -->
<html lang="en" class="page-type-section">
<head prefix="og: http://ogp.me/ns#">
<meta charset="utf-8">
<title>2.3.29 - 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.29">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="https://freemarker.apache.org/docs/versions_2_3_29.html">
<link rel="canonical" href="https://freemarker.apache.org/docs/versions_2_3_29.html">
<link rel="icon" href="favicon.png" type="image/png">
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:500,700,400,300|Droid+Sans+Mono">
<link rel="stylesheet" type="text/css" href="docgen-resources/docgen.min.css?1707770044859">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/cookie-bar/cookiebar-latest.min.js"></script>
</head>
<body itemscope itemtype="https://schema.org/Code">
<meta itemprop="url" content="https://freemarker.apache.org/docs/">
<meta itemprop="name" content="Apache FreeMarker Manual">
<!--[if lte IE 9]>
<div class="oldBrowserWarning" style="display: block">
Unsupported web browser - Use a modern browser to view this website!
</div>
<![endif]--> <div class="oldBrowserWarning">
Unsupported web browser - Use a modern browser to view this website!
</div>
<div class="header-top-bg"><div class="site-width header-top"><div id="hamburger-menu" role="button"></div> <div class="logo">
<a href="https://freemarker.apache.org" role="banner"><img itemprop="image" src="logo.png" alt="FreeMarker"></a> </div>
<ul class="tabs"><li><a href="https://freemarker.apache.org/">Home</a></li><li class="current"><a href="index.html">Manual</a></li><li><a class="external" href="api/index.html">Java API</a></li></ul><ul class="secondary-tabs"><li><a class="tab icon-heart" href="https://freemarker.apache.org/contribute.html" title="Contribute"><span>Contribute</span></a></li><li><a class="tab icon-bug" href="https://issues.apache.org/jira/projects/FREEMARKER" title="Report a Bug"><span>Report a Bug</span></a></li><li><a class="tab icon-download" href="https://freemarker.apache.org/freemarkerdownload.html" title="Download"><span>Download</span></a></li></ul></div></div><div class="header-bottom-bg"><div class="site-width search-row"><a href="index.html" class="navigation-header">Manual</a><div class="navigation-header"></div><form method="get" class="search-form" action="search-results.html"><fieldset><legend class="sr-only">Search form</legend><label for="search-field" class="sr-only">Search query</label><input id="search-field" name="q" type="search" class="search-input" placeholder="Search" spellcheck="false" autocorrect="off" autocomplete="off"><button type="submit" class="search-btn"><span class="sr-only">Search</span></button></fieldset></form></div><div class="site-width breadcrumb-row"> <div class="breadcrumbs">
<ul class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList"><li class="step-0" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="index.html"><span itemprop="name">Apache FreeMarker Manual</span></a></li><li class="step-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="app.html"><span itemprop="name">Appendixes</span></a></li><li class="step-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="app_versions.html"><span itemprop="name">Version history</span></a></li><li class="step-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="versions_2_3_29.html"><span itemprop="name">2.3.29</span></a></li></ul> </div>
<div class="bookmarks" title="Bookmarks"><span class="sr-only">Bookmarks:</span><ul><li><a href="alphaidx.html">Alpha. index</a></li><li><a href="gloss.html">Glossary</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions</a></li><li><a href="ref_builtins_alphaidx.html">?builtins</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_specvar.html">.spec_vars</a></li><li><a href="app_faq.html">FAQ</a></li></ul></div></div></div> <div class="main-content site-width">
<div class="content-wrapper">
<div id="table-of-contents-wrapper" class="col-left">
<script>var breadcrumb = ["Apache FreeMarker Manual","Appendixes","Version history","2.3.29"];</script>
<script src="toc.js?1707770044859"></script>
<script src="docgen-resources/main.min.js?1707770044859"></script>
</div>
<div class="col-right"><div class="page-content"><div class="page-title"><div class="pagers top"><a class="paging-arrow previous" href="versions_2_3_30.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_3_28.html"><span>Next</span></a></div><div class="title-wrapper">
<h1 class="content-header header-section1" id="versions_2_3_29" itemprop="headline">2.3.29</h1>
</div></div><div class="page-menu">
<div class="page-menu-title">Page Contents</div>
<ul><li><a class="page-menu-link" href="#autoid_156" data-menu-target="autoid_156">Changes on the FTL side</a></li><li><a class="page-menu-link" href="#autoid_157" data-menu-target="autoid_157">Changes on the Java side</a></li></ul> </div><p>Release date: 2019-08-17</p>
<h2 class="content-header header-section2" id="autoid_156">Changes on the FTL side</h2>
<ul>
<li>
<p>Added new built-ins: <a href="ref_builtins_sequence.html#ref_builtin_filter"><code>?filter(<em>predicate</em>)</code></a>,
<a href="ref_builtins_sequence.html#ref_builtin_map"><code>?map(<em>mapper</em>)</code></a>,
<a href="ref_builtins_sequence.html#ref_builtin_take_while"><code>?take_while(<em>predicate</em>)</code></a>,
<a href="ref_builtins_sequence.html#ref_builtin_drop_while"><code>?drop_while(<em>predicate</em>)</code></a>.
These allow using lambda expressions, like
<code class="inline-code">users?filter(user -&gt; user.superuser)</code> or
<code class="inline-code">users?map(user -&gt; user.name)</code>, or accept a
function/method as parameter. Lambda expressions are also new in
this release, but they can only be used in said built-ins, so
they aren&#39;t like in Java for example, and also, unlike the
similar Java methods, these built-ins aren&#39;t lazy in general,
only in specific cases (see more <a href="ref_builtins_sequence.html#topic.filterLazyEval">here</a>). The main goal of
adding these built-ins was to allow conditionally skipping
elements in the <code class="inline-code">list</code> directive without nested
<code class="inline-code">if</code>-s that interfere with the <a href="ref_directive_list.html#ref.directive.sep"><code>sep</code>
directive</a>, and the <a href="ref_builtins_loop_var.html">loop variable built-ins</a>
(see examples <a href="ref_directive_list.html#ref_list_skipping">here</a>).</p>
</li>
<li>
<p>Added new built-ins for truncating text.
<code class="inline-code"><em class="code-color">string</em>?truncate(<em class="code-color">length</em>)</code>
truncates the text to the given length, and by default adds
<code class="inline-code">[...]</code> at the end if truncation has happened.
Truncation happens at word boundaries, unless the result is too
short that way, in which case it falls back to truncation mid
word. There&#39;s also <code class="inline-code">?truncate_w</code> to force Word
Boundary truncation, and <code class="inline-code">?truncate_c</code> (for
Character Boundary) that doesn&#39;t care about word boundaries. The
truncation algorithm is pluggable in the FreeMarker
configuration. See <a href="ref_builtins_string.html#ref_builtin_truncate">the
reference</a> for more details.</p>
</li>
<li>
<p><a href="ref_builtins_expert.html#ref_builtin_sequence"><code>?sequence</code></a>
now collaborates with
<code class="inline-code"><em class="code-color">seq</em>?size</code>,
<code class="inline-code"><em class="code-color">seq</em>[<em class="code-color">index</em>]</code>,
<code class="inline-code"><em class="code-color">seq</em>[<em class="code-color">range</em>]</code>,
and with some other built-ins (<code class="inline-code">filter</code>,
<code class="inline-code">map</code>, <code class="inline-code">join</code>, etc.) to spare
collecting all the elements into the memory when possible. For
example <code class="inline-code">anIterator?sequence[1]</code> will now just
fetch the first 2 items, while earlier it has built a sequence
that contains all the elements, only to get the 2nd element from
that. Or, <code class="inline-code">anIterator?sequence?size</code> will now
just count the elements, without collecting them into the
memory. See <a href="ref_builtins_expert.html#ref_builtin_sequence_optimizations">the
reference</a> for more details.</p>
</li>
<li>
<p><a href="ref_builtins_number.html#topic.extendedJavaDecimalFormat">Extended
decimal format</a> parameter "multiplier" was
incorrectly written as "multipier". Now both words
are recognized.</p>
</li>
<li>
<p><code class="inline-code">?min</code> and <code class="inline-code">?max</code> will
now immediately stop with error when applied on a right
unbounded numerical range (like <code class="inline-code">1..</code>), as that
would run forever anyway.</p>
</li>
</ul>
<h2 class="content-header header-section2" id="autoid_157">Changes on the Java side</h2>
<ul>
<li>
<p><a href="https://issues.apache.org/jira/browse/FREEMARKER-109">FREEMARKER-109</a>:
In JSP TLD-s, line breaks inside function parameter lists have
caused <code class="inline-code">IllegalArgumentException</code>
"Invalid function signature".</p>
</li>
<li>
<p><a href="https://issues.apache.org/jira/browse/FREEMARKER-104">FREEMARKER-104</a>:
More helpful log and error messages (especially, no
<code class="inline-code">NullPointerException</code> cause exception logged
during FreeMarker XPath support initialization) if no XPath
implementation is available because Java 9 modules don&#39;t allow
accessing the internal Xalan that&#39;s stored under
<code class="inline-code">com.sun</code> packages. (The messages now recommend
adding Apache Xalan or Jaxen as dependency if you need XPath
support.)</p>
</li>
<li>
<p>The <code class="inline-code">boolean_format</code> configuration
setting now can be set to <code class="inline-code">&quot;c&quot;</code>. Then
<code class="inline-code">${<em class="code-color">aBoolean</em>}</code> will
behave as
<code class="inline-code">${<em class="code-color">aBoolean</em>?c}</code>.
This should only be used if you are generating output for
non-human (computer) consumption only. If your output has pieces
for human audience too, it&#39;s still recommended to use
<code class="inline-code">${<em class="code-color">aBoolean</em>?c}</code>
where <code class="inline-code">true</code>/<code class="inline-code">false</code> output is
needed, and either not set the <code class="inline-code">boolean_format</code>
at all, or set it to something that&#39;s appropriate for everyday
users (like <code class="inline-code">&quot;yes,no&quot;</code>).</p>
</li>
<li>
<p>New configuration setting,
<code class="inline-code">fallback_on_null_loop_variable</code>: Specifies the
behavior when reading a loop variable (like <code class="inline-code">i</code>
in <code class="inline-code">&lt;#list items as i&gt;</code>, or in
<code class="inline-code">&lt;@myMacro items; i&gt;</code>) that&#39;s
<code class="inline-code">null</code> (missing); if <code class="inline-code">true</code>,
FreeMarker will look for a variable with the same name in higher
variable scopes, or if <code class="inline-code">false</code> the variable
will be simply <code class="inline-code">null</code> (missing). For backward
compatibility the default is <code class="inline-code">true</code>. The
recommended value for new projects is <code class="inline-code">false</code>,
as otherwise adding new variables to higher scopes (typically to
the data-model) can unintentionally change the behavior of
templates.</p>
</li>
<li>
<p>If the result of
<code class="inline-code"><em class="code-color">seq</em>?size</code> is
compared to an integer <em>literal</em> in a
template, like in <code class="inline-code"><em class="code-color">seq</em>?size
!= 0</code>, or <code class="inline-code"><em class="code-color">seq</em>?size
&lt; 1</code>, and to decide the answer it&#39;s enough to know
if <code class="inline-code"><em class="code-color">seq</em></code> is empty or
not (i.e., the exact size isn&#39;t needed), and
<code class="inline-code"><em class="code-color">seq</em></code> implements
<code class="inline-code">TemplateCollectionModelEx</code>, FreeMarker will
call <code class="inline-code">TemplateCollectionModelEx.isEmpty()</code>
instead of <code class="inline-code">size()</code>. Furthermore, if
<code class="inline-code"><em class="code-color">seq</em></code> is the result
of <code class="inline-code">?filter</code>, or of a similar built-ins that
can provide lazily generated result, it will do counting to
figure out the size (rather than constructing the whole sequence
in memory), and will limit how far it counts based on what
literal the result of <code class="inline-code">?size</code> is compared
with.</p>
</li>
<li>
<p>Added
<code class="inline-code">TemplateModelUtils.wrapAsHashUnion(ObjectWrapper,
List&lt;?&gt;)</code> and
<code class="inline-code">wrapAsHashUnion(ObjectWrapper, Object...)</code>,
which is useful when you want to compose the data-model from
multiple objects in a way so that their entries
(<code class="inline-code">Map</code> key-value pairs, bean properties, etc.)
appear together on the top level of the data-model.</p>
</li>
<li>
<p><code class="inline-code">HTMLOutputFormat</code>,
<code class="inline-code">XMLOutputFormat</code>,
<code class="inline-code">XHTMLOutputFormat</code> aren&#39;t final classes
anymore, furthermore <code class="inline-code">XHTMLOutputFormat</code> now
extends <code class="inline-code">XMLOutputFormat</code>. Same applies to the
respective <code class="inline-code">TemplateOutputModel</code>-s
(<code class="inline-code">TemplateHTMLOutputModel</code> is not final
anymore, etc.). This allows defining new custom markup output
format classes that will work with program logic that&#39;s only
prepared for the standard markup output formats, because
<code class="inline-code">instanceof
<em class="code-color">SomeStandardOutputFromat</em></code>
will return <code class="inline-code">true</code> for them.</p>
</li>
<li>
<p>When configuring FreeMarker with string values (like with
a <code class="inline-code">.properties</code> file), in the settings that
support the "object builder" syntax, now you can
create a <code class="inline-code">TemplateMarkupOutputModel</code> value with
the new <code class="inline-code">markup</code> function, like
<code class="inline-code">markup(HTMLOutputFormat(),
&quot;&lt;p&gt;Example&lt;/p&gt;&quot;)</code>.</p>
</li>
<li>
<p><code class="inline-code">BeansWrapper.clearClassIntrospecitonCache</code>
was deprecated as there&#39;s a typo in the method name; use
<code class="inline-code">clearClassIntrospectionCache</code> instead.</p>
</li>
</ul>
<div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="versions_2_3_30.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_3_28.html"><span>Next</span></a></div></div></div></div> </div>
</div>
<div class="site-footer"><div class="site-width"><div class="footer-top"><div class="col-left sitemap"><div class="column"><h3 class="column-header">Overview</h3><ul><li><a href="https://freemarker.apache.org/">What is FreeMarker?</a></li><li><a href="https://freemarker.apache.org/freemarkerdownload.html">Download</a></li><li><a href="app_versions.html">Version history</a></li><li><a href="app_faq.html">FAQ</a></li><li><a itemprop="license" href="app_license.html">License</a></li><li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy policy</a></li></ul></div><div class="column"><h3 class="column-header">Often used / Reference</h3><ul><li><a href="https://try.freemarker.apache.org/">Try template online</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions cheatsheet</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_builtins_alphaidx.html">?built_ins</a></li><li><a href="ref_specvar.html">.special_vars</a></li><li><a href="api/freemarker/core/Configurable.html#setSetting-java.lang.String-java.lang.String-">Configuration settings</a></li></ul></div><div class="column"><h3 class="column-header">Community</h3><ul><li><a href="https://github.com/apache/freemarker">Github project page</a></li><li><a href="https://issues.apache.org/jira/projects/FREEMARKER">Report a bug</a></li><li><a href="https://freemarker.apache.org/report-security-vulnerabilities.html">Report security vulnerability</a></li><li><a href="https://stackoverflow.com/questions/ask?tags=freemarker">Get help on StackOverflow</a></li><li><a href="https://twitter.com/freemarker">Announcements on Twitter</a></li><li><a href="https://freemarker.apache.org/mailing-lists.html">Discuss on mailing lists</a></li></ul></div></div><div class="col-right"><ul class="social-icons"><li><a class="github" href="https://github.com/apache/freemarker">Github</a></li><li><a class="twitter" href="https://twitter.com/freemarker">Twitter</a></li><li><a class="stack-overflow" href="https://stackoverflow.com/questions/ask?tags=freemarker">Stack Overflow</a></li></ul><a class="xxe" href="http://www.xmlmind.com/xmleditor/" rel="nofollow" title="Edited with XMLMind XML Editor"><span>Edited with XMLMind XML Editor</span></a></div></div><div class="footer-bottom"> <p class="last-generated">
Last generated:
<time itemprop="dateModified" datetime="2024-02-12T20:34:04Z" title="Monday, February 12, 2024 at 8:34:04 PM Greenwich Mean Time">2024-02-12 20:34:04 GMT</time>, for Freemarker 2.3.32 </p>
<p class="copyright">
© <span itemprop="copyrightYear">1999</span>–2024
<a itemtype="http://schema.org/Organization" itemprop="copyrightHolder" href="https://apache.org/">The Apache Software Foundation</a>. Apache FreeMarker, FreeMarker, Apache Incubator, Apache, the Apache FreeMarker logo are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners. </p>
</div></div></div></body>
</html>