| <!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 -> user.superuser)</code> or |
| <code class="inline-code">users?map(user -> 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't like in Java for example, and also, unlike the |
| similar Java methods, these built-ins aren'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'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'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't allow |
| accessing the internal Xalan that'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">"c"</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'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's appropriate for everyday |
| users (like <code class="inline-code">"yes,no"</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"><#list items as i></code>, or in |
| <code class="inline-code"><@myMacro items; i></code>) that'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 |
| < 1</code>, and to decide the answer it'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'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<?>)</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'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'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(), |
| "<p>Example</p>")</code>.</p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code">BeansWrapper.clearClassIntrospecitonCache</code> |
| was deprecated as there'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> |