| <!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.28 - 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.28"> |
| <meta property="og:locale" content="en_US"> |
| <meta property="og:url" content="https://freemarker.apache.org/docs/versions_2_3_28.html"> |
| <link rel="canonical" href="https://freemarker.apache.org/docs/versions_2_3_28.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_28.html"><span itemprop="name">2.3.28</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.28"];</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_29.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_3_27.html"><span>Next</span></a></div><div class="title-wrapper"> |
| <h1 class="content-header header-section1" id="versions_2_3_28" itemprop="headline">2.3.28</h1> |
| </div></div><div class="page-menu"> |
| <div class="page-menu-title">Page Contents</div> |
| <ul><li><a class="page-menu-link" href="#autoid_158" data-menu-target="autoid_158">Changes on the FTL side</a></li><li><a class="page-menu-link" href="#autoid_159" data-menu-target="autoid_159">Changes on the Java side</a></li><li><a class="page-menu-link" href="#autoid_160" data-menu-target="autoid_160">Other changes</a></li></ul> </div><p>Release date: 2018-04-04</p> |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_158">Changes on the FTL side</h2> |
| |
| |
| <ul> |
| <li> |
| <p>Added new <a href="ref_specvar.html">special |
| variable</a>, <code class="inline-code">get_optional_template</code> (<a href="https://issues.apache.org/jira/browse/FREEMARKER-84">FREEMARKER-84</a>). |
| It can be used when you need to include or import a template |
| that's possibly missing, and you need to handle that case on |
| some special way. <a href="ref_specvar.html#ref_specvar_get_optional_template">See the details |
| here...</a></p> |
| </li> |
| |
| <li> |
| <p>Added new <a href="ref_specvar.html">special |
| variable</a>, <code class="inline-code">caller_template_name</code> (<a href="https://issues.apache.org/jira/browse/FREEMARKER-83">FREEMARKER-83</a>), |
| which returns the name (path) of the template from which the |
| current macro or function was called. It's mostly useful if you |
| want to resolve paths relative to the caller template.</p> |
| </li> |
| |
| <li> |
| <p>Added new built-in, |
| <code class="inline-code"><em class="code-color">templateName</em>?absolute_template_name</code> |
| or |
| <code class="inline-code"><em class="code-color">templateName</em>?absolute_template_name(<em class="code-color">baseName</em>)</code>, |
| which can be used to convert a relative template name to an |
| absolute template name. <a href="ref_builtins_expert.html#ref_builtin_absolute_template_name">See more |
| here...</a></p> |
| </li> |
| |
| <li> |
| <p>Added new built-ins: |
| <code class="inline-code"><em class="code-color">sequence</em>?min</code> and |
| <code class="inline-code"><em class="code-color">sequence</em>?max</code> |
| (<a href="https://issues.apache.org/jira/browse/FREEMARKER-86">FREEMARKER-86</a>), |
| which return the smallest and greatest item from a list of |
| numbers or date/time/date-times. <a href="ref_builtins_sequence.html#ref_builtin_min_max">See more here...</a></p> |
| </li> |
| |
| <li> |
| <p>The template language can now be configured to use |
| <code class="inline-code">[=<em class="code-color">expression</em>]</code> |
| instead of |
| <code class="inline-code">${<em class="code-color">expression</em>}</code> and |
| <code class="inline-code">#{<em class="code-color">expression</em>}</code>, |
| which is very useful if you have a lot of |
| <code class="inline-code">${<em class="code-color">...</em>}</code> or |
| <code class="inline-code">#{<em class="code-color">...</em>}</code> in the text |
| that you are generating, and so they should be static text. See |
| <a href="dgui_misc_alternativesyntax.html#dgui_misc_alternativesyntax_interpolation">more |
| about the square bracket interpolation syntax here.</a> The |
| template language can also be configured to only use |
| <code class="inline-code">${<em class="code-color">expression</em>}</code>, and |
| treat |
| <code class="inline-code">#{<em class="code-color">expression</em>}</code> as |
| static text. (See the <code class="inline-code">interpolation_syntax</code> |
| configuration setting, or the |
| <code class="inline-code">Configuration.setInterpolationSyntax(int)</code> |
| method.)</p> |
| </li> |
| |
| <li> |
| <p>In string literals, <code class="inline-code">\=</code> is now a valid |
| escape sequence, resulting in a <code class="inline-code">=</code>. This is |
| useful when you are using the new |
| <code class="inline-code">[=<em class="code-color">exp</em>]</code> |
| interpolation syntax, which can be escaped in a string literal |
| like <code class="inline-code">"Literal [\=x]"</code>.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed (<a href="https://issues.apache.org/jira/browse/FREEMARKER-83">FREEMARKER-83</a>); |
| this fix is only active when <a href="pgui_config_incompatible_improvements.html#pgui_config_incompatible_improvements_how_to_set"><code>incomplatible_improvements</code></a> |
| is set to 2.3.28 (or higher). When calling a macro or function |
| (things defined in a template, not directly in Java) and the |
| argument list contains |
| <code class="inline-code">.current_template_name</code>, now it will correctly |
| evaluate to the template that contains the call, rather than to |
| the template that contains the macro or function definition. (Of |
| course, the parameter default value expression is still |
| evaluated in the context of the called macro or |
| function.)</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed: When |
| <code class="inline-code"><em class="code-color">string</em>?split(<em class="code-color">separator</em>)</code> |
| is called with <code class="inline-code">""</code> as the argument, the string |
| will be split to characters now. Earlier it has thrown an |
| <code class="inline-code">IllegalArgumentException</code> (unless the |
| <code class="inline-code">r</code> flag was specified).</p> |
| </li> |
| </ul> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_159">Changes on the Java side</h2> |
| |
| |
| <ul> |
| <li> |
| <p>Added new <code class="inline-code">ParserConfiguration</code> (such as |
| <code class="inline-code">Configuration</code> and |
| <code class="inline-code">TemplateConfiguration</code>) setting, |
| <code class="inline-code">interpolation_syntax</code>. It has 3 possible |
| values:</p> |
| |
| <ul> |
| <li> |
| <p><code class="inline-code">legacy</code> (the default): |
| Interpolations look like |
| <code class="inline-code">${<em class="code-color">...</em>}</code> or |
| <code class="inline-code">#{<em class="code-color">...</em>}</code>. Note |
| that <code class="inline-code">#{<em class="code-color">...</em>}</code> is |
| deprecated for a long time now.</p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code">dollar</code>: Interpolations look like |
| <code class="inline-code">${<em class="code-color">...</em>}</code>. With |
| this syntax, |
| <code class="inline-code">#{<em class="code-color">...</em>}</code> will be |
| just static text.</p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code">square_bracket</code>: Interpolations look |
| like <code class="inline-code">[=<em class="code-color">...</em>]</code>. |
| With this syntax |
| <code class="inline-code">${<em class="code-color">...</em>}</code> and |
| <code class="inline-code">#{<em class="code-color">...</em>}</code> will be |
| just static text. So it's useful if you generate output in a |
| format where those (typically |
| <code class="inline-code">${<em class="code-color">...</em>}</code>) are |
| already used, such as to generate JSP pages, or to generate |
| FreeMarker templates that use the default syntax.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>When specifying the <code class="inline-code">output_format</code> |
| configuration setting with |
| <code class="inline-code">String</code>-<code class="inline-code">String</code> key-value |
| pairs (like with <code class="inline-code">Configuration.setSetting(String, |
| String)</code> or in a <code class="inline-code">.properties</code> file), |
| it's now possible to specify the standard output formats by |
| short name (like <code class="inline-code">output_format=HTML</code>) rather |
| than by class name. (Custom formats still has to be referred by |
| class name, as FreeMarker can't discover what their names are, |
| since it's not aware of the custom classes.)</p> |
| </li> |
| |
| <li> |
| <p>Added a new |
| <code class="inline-code">Configuration.removeTemplateFromCache</code> |
| overload that has a <code class="inline-code">Object |
| customLookupCondition</code> parameter. This is useful to |
| manually evacuate a template from the cache that was get with a |
| non-<code class="inline-code">null</code> custom lookup condition.</p> |
| </li> |
| |
| <li> |
| <p>Added new property to |
| <code class="inline-code">BeansWrapper.MethodAppearanceDecision</code>: |
| <code class="inline-code">replaceExistingProperty</code>. This is useful when |
| a method like <code class="inline-code">size()</code> is exposed as a JavaBean |
| property via |
| <code class="inline-code">MethodAppearanceDecision.exposeAsProperty</code>, |
| but there's also a "real" JavaBean property (like |
| <code class="inline-code">getSize()</code>) with identical name. By default |
| the real property isn't replaced, but now with |
| <code class="inline-code">replaceExistingProperty</code> it can be.</p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code">DirectiveCallPlace</code> now has a |
| <code class="inline-code">Template getTemplate()</code> method, so you can |
| query if from which template was your |
| <code class="inline-code">TemplateDirectiveModel</code> called. (This has |
| similar role as <code class="inline-code">.caller_template_name</code> for |
| macros/functions.)</p> |
| </li> |
| |
| <li> |
| <p>Added |
| <code class="inline-code">Environment.rootBasedToAbsoluteTemplateName(String)</code>, |
| which converts the root based names typically used for the |
| FreeMarker Java API-s (such as |
| <code class="inline-code">Configuration.getTemplate(name)</code>) to an |
| absolute path, which can be safely passed to |
| <code class="inline-code"><#include |
| <em class="code-color">path</em>></code> and such, as it |
| won't be misinterpreted to be relative to the directory of the |
| template.</p> |
| </li> |
| |
| <li> |
| <p>Fixes in exception handling when calling JSP tags:</p> |
| |
| <ul> |
| <li> |
| <p>Bug fixed (<a href="https://issues.apache.org/jira/browse/FREEMARKER-88">FREEMARKER-88</a>): |
| If a <code class="inline-code">TemplateException</code> that's not a |
| <code class="inline-code">TemplateModelExceptoin</code> has occurred in |
| the body (nested content) of a JSP |
| <code class="inline-code">SimpleTag</code> (typically, an |
| <code class="inline-code">InvalidReferenceException</code>), that has |
| caused a <code class="inline-code">ClassCastException</code> in the |
| exception handling code, thus the template processing has |
| thrown that instead of the original exception.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed: For JSP Tag based custom tags, if an |
| exception has occurred in the body (nested content), an |
| <code class="inline-code">IndexOutOfBoundsException</code> might have |
| occurred, replacing the original exception.</p> |
| </li> |
| |
| <li> |
| <p>Wrapping of |
| non-<code class="inline-code">TemplateModelException</code> |
| <code class="inline-code">TemplateException</code>-s (typically |
| <code class="inline-code">InvalidReferenceException</code>-s) into |
| <code class="inline-code">TemplateModelException</code>-s is now avoided |
| when the <code class="inline-code">TemplateException</code> occurs in the |
| body of a JSP tag.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>The default arithmetic engine |
| (<code class="inline-code">ArithmeticEngine.BIGDECIMAL_ENGINE</code>) can now |
| compare infinite (both positive and negative) to any other |
| standard numerical type. Earlier, since |
| <code class="inline-code">BigDecimal</code> can't represent infinite, it was |
| only working in certain special cases. Also there were some |
| performance optimizations to slightly decrease the impact and |
| number of conversions to <code class="inline-code">BigDecimal</code>.</p> |
| </li> |
| |
| <li> |
| <p>Avoided possible performance bottleneck when executing |
| templates on many threads, caused by that |
| <code class="inline-code">java.beans.PropertyDescriptor.getReadMethod()</code> |
| is synchronized (<a href="https://issues.apache.org/jira/browse/FREEMARKER-80">FREEMARKER-80</a>).</p> |
| </li> |
| |
| <li> |
| <p>Added |
| <code class="inline-code">TemplateModelUtils.getKeyValuePairIterator(TemplateHashModelEx)</code> |
| static utility class, which can be used to get a |
| <code class="inline-code">TemplateHashModelEx2.KeyValuePairIterator</code> |
| even for a non-<code class="inline-code">TemplateHashModelEx2</code> object. |
| This simplifies Java code that iterates through key-value |
| pairs.</p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code">freemarker.template.utility.DeepUnwrap</code> |
| (a rarely used utility) now utilizes when the unwrapped |
| <code class="inline-code">TemplateModel</code> implements |
| <code class="inline-code">TemplateHashModelEx2.getKeyValuePairIterator()</code>, |
| and thus can unwrap such a hash value even if it has non-string |
| keys. Also, it nows keeps the iteration order of the hashes, as |
| it unwraps into a <code class="inline-code">LinkedHashMap</code> instead of |
| into a plain <code class="inline-code">HashMap</code>.</p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code">freemarker.ext.beans.HashAdapter.size()</code> |
| was overridden for better performance.</p> |
| </li> |
| |
| <li> |
| <p>When the <a href="pgui_config_incompatible_improvements.html#pgui_config_incompatible_improvements_how_to_set"><code>incompatible_improvements</code> |
| setting</a> is set to 2.3.28 (or greater): Fixed legacy |
| parser glitch where a tag can be closed with an illegal |
| <code class="inline-code">]</code> (when it's not part of an expression) |
| despite that the tag syntax is set to angle brackets. For |
| example <code class="inline-code"><#if x]</code> worked just like |
| <code class="inline-code"><#if x></code>. Note that this legacy glitch |
| didn't affect the legal usage of <code class="inline-code">]</code>, like |
| <code class="inline-code"><#if x[0]></code> has always worked |
| correctly.</p> |
| </li> |
| |
| <li> |
| <p>Fixed parser bug that disallowed using |
| <code class="inline-code">></code> as the top-level expression inside an |
| interpolation (<code class="inline-code">${...}</code>). It had the same |
| reason why <code class="inline-code"><#if x > y></code> doesn't work |
| as naively expected, but there's no real ambiguity in |
| <code class="inline-code">${x > y}</code>, so now it's allowed. Note that |
| <code class="inline-code">${(x > y)?c}</code> and <code class="inline-code">${(x > |
| y)?string('y', 'n')}</code>, which are how booleans are |
| commonly printed, have always worked, as the |
| <code class="inline-code">></code> operation is not on the top-level inside |
| the interpolation.</p> |
| </li> |
| |
| <li> |
| <p>Fixed incorrect listing of valid |
| <code class="inline-code">roundingMode</code>-s in <a href="ref_builtins_number.html#topic.extendedJavaDecimalFormat">extended Java decimal |
| format</a> parsing error message</p> |
| </li> |
| </ul> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_160">Other changes</h2> |
| |
| |
| <ul> |
| <li> |
| <p>FreeMarker has graduated from the Apache Incubator (as of |
| 2018-03-21), and now is a normal top-level project at Apache. |
| Therefore, the version number doesn't contain |
| "-incubating" anymore.</p> |
| </li> |
| </ul> |
| <div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="versions_2_3_29.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_3_27.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> |