| <!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.21 - 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.21"> |
| <meta property="og:locale" content="en_US"> |
| <meta property="og:url" content="https://freemarker.apache.org/docs/versions_2_3_21.html"> |
| <link rel="canonical" href="https://freemarker.apache.org/docs/versions_2_3_21.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_21.html"><span itemprop="name">2.3.21</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.21"];</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_22.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_3_20.html"><span>Next</span></a></div><div class="title-wrapper"> |
| <h1 class="content-header header-section1" id="versions_2_3_21" itemprop="headline">2.3.21</h1> |
| </div></div><div class="page-menu"> |
| <div class="page-menu-title">Page Contents</div> |
| <ul><li><a class="page-menu-link" href="#autoid_179" data-menu-target="autoid_179">Changes on the FTL side</a></li><li><a class="page-menu-link" href="#autoid_180" data-menu-target="autoid_180">Changes on the Java side</a></li><li><a class="page-menu-link" href="#autoid_181" data-menu-target="autoid_181">Other changes</a></li></ul> </div><p>Date of release: 2014-10-12</p><p>Note that since 2.3.21 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.21 "incompatible |
| improvements"</em>, because they could, with very small |
| chance, break existing applications. If the dependent project is still |
| actively developed, allowing 2.3.21 "incompatible improvements" is |
| highly recommended. See <a href="pgui_config_incompatible_improvements.html#pgui_config_incompatible_improvements_how_to_set">how to set |
| "incomplatible improvements" here</a>.</p><p>Note that we have changed our proprietary BSD-style license to |
| Apache License, Version 2.0. See the <a href="app_license.html">new |
| license here</a>.</p><p>Note that the minimum required Java version was increased from |
| 1.2 to 1.4.</p> |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_179">Changes on the FTL side</h2> |
| |
| |
| <ul> |
| <li> |
| <p>Improved ranges:</p> |
| |
| <ul> |
| <li> |
| <p>Added ranges with exclusive end: |
| <code class="inline-code"><em class="code-color">start</em>..<<em class="code-color">end</em></code> |
| (also can be written as |
| <code class="inline-code"><em class="code-color">start</em>..!<em class="code-color">end</em></code>). |
| <a href="dgui_template_exp.html#dgui_template_exp_direct_ranges">More...</a></p> |
| </li> |
| |
| <li> |
| <p>Added length limited ranges: |
| <code class="inline-code"><em class="code-color">start</em>..*<em class="code-color">length</em></code>: |
| For example, <code class="inline-code">10..*4</code> gives <code class="inline-code">[10, |
| 11, 12, 13]</code>, <code class="inline-code">10..*-4</code> gives |
| <code class="inline-code">[10, 9, 8, 7]</code>, and |
| <code class="inline-code">10..*0</code> gives <code class="inline-code">[]</code>. When |
| these kind of ranges are used for slicing, the slice will |
| end without error if the end of the sliced sequence or |
| string is reached before the specified range length was |
| reached. Thus, for example, to take the first 10 characters |
| from the string <code class="inline-code">s</code>, or less if |
| <code class="inline-code">s</code> is shorter than 10 characters, you can |
| use <code class="inline-code">s[0..*10]</code>. <a href="dgui_template_exp.html#dgui_template_exp_seqenceop_slice">More...</a></p> |
| </li> |
| |
| <li> |
| <p>Square bracket now accepts range values from any |
| source, like <code class="inline-code"><#assign r = 1..3> |
| ${'foobar'[r]}</code> will print |
| <code class="inline-code">"oob"</code>. Earlier it has only supported |
| ranges that were specified directly inside the square |
| brackets, like <code class="inline-code">'foobar'[1..3]</code>.</p> |
| </li> |
| |
| <li> |
| <p>When slicing a sequence with a right-unbounded range, |
| it's now allowed to have a range start index that's one |
| higher than the last index of the sliced sequence. For |
| example, <code class="inline-code">['x', 'y'][2..]</code> is not an error |
| anymore, but an empty sequence. (Of course, <code class="inline-code">['x', |
| 'y'][3..]</code> is still an error.)</p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code"><em class="code-color">someString</em>?substring(<em class="code-color">from</em>, |
| <em class="code-color">toExclusive</em>)</code> and |
| <code class="inline-code"><em class="code-color">someString</em>?substring(<em class="code-color">from</em>)</code> |
| are now deprecated; use this slicing expression instead: |
| <code class="inline-code"><em class="code-color">someString</em>[<em class="code-color">from</em>..<<em class="code-color">toExclusive</em>]</code> |
| and |
| <code class="inline-code"><em class="code-color">someString</em>[<em class="code-color">from</em>..]</code>. |
| A warning if you are processing XML: Since slicing |
| expressions work both for sequences and strings, and XML |
| nodes in FTL are typically both sequences and strings at the |
| same time, there the equivalent expression is |
| <code class="inline-code"><em class="code-color">someXmlNode</em>?string[<em class="code-color">from</em>..<<em class="code-color">toExclusive</em>]</code> |
| and |
| <code class="inline-code"><em class="code-color">exp</em>?string[<em class="code-color">from</em>..]</code>, |
| because without the <code class="inline-code">?string</code> it would |
| slice the node sequence instead of the text value of the |
| node.</p> |
| </li> |
| |
| <li> |
| <p>If the <code class="inline-code">incompatible_improvements</code> in |
| the FreeMarker configuration is set to at least 2.3.21, |
| right-unbounded ranges become readable (like |
| <code class="inline-code">#list</code>-able). Earlier they could only be |
| used for slicing, and behaved like empty sequences |
| otherwise.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>New built-in, <code class="inline-code">?url_path</code>: This is the |
| same as <a href="ref_builtins_string.html#ref_builtin_url">the |
| <code>url</code> built-in</a>, except that it doesn't |
| escape slash (<code class="inline-code">/</code>) characters. This meant to be |
| used for converting paths (like paths coming from the OS or some |
| content repository) that use slash (not backslash!) to a path |
| the can be inserted into the path part of an URL.</p> |
| </li> |
| |
| <li> |
| <p>New built-ins for string manipulation:</p> |
| |
| <ul> |
| <li> |
| <p><code class="inline-code"><em class="code-color">someString</em>?keep_before(<em class="code-color">substring</em>[, |
| <em class="code-color">flags</em>])</code>: <a href="ref_builtins_string.html#ref_builtin_keep_before">More...</a></p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code"><em class="code-color">someString</em>?keep_after(<em class="code-color">substring</em>[, |
| <em class="code-color">flags</em>])</code>: <a href="ref_builtins_string.html#ref_builtin_keep_after">More...</a></p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code"><em class="code-color">someString</em>?remove_beginning(<em class="code-color">substring</em>)</code>: |
| <a href="ref_builtins_string.html#ref_builtin_remove_beginning">More...</a></p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code"><em class="code-color">someString</em>?remove_ending(<em class="code-color">substring</em>)</code>: |
| <a href="ref_builtins_string.html#ref_builtin_remove_ending">More...</a></p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code"><em class="code-color">someString</em>?ensure_starts_with(<em class="code-color">substring</em>[, |
| <em class="code-color">substitution</em>[, |
| <em class="code-color">flags</em>]])</code>: <a href="ref_builtins_string.html#ref_builtin_ensure_starts_with">More...</a></p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code"><em class="code-color">someString</em>?ensure_ends_with(<em class="code-color">substring</em>)</code>: |
| <a href="ref_builtins_string.html#ref_builtin_ensure_ends_with">More...</a></p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p><code class="inline-code"><em class="code-color">someString</em>?number</code> |
| now recognizes all XML Schema number formats, like |
| <code class="inline-code">NaN</code>, <code class="inline-code">INF</code>, |
| <code class="inline-code">-INF</code>, plus the Java-native formats |
| <code class="inline-code">Infinity</code> and |
| <code class="inline-code">-Infinity</code>.</p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">incompatible_improvements</code> in the |
| FreeMarker configuration is set to at least 2.3.21, |
| <code class="inline-code"><em class="code-color">someNumber</em>?c</code> will |
| return <code class="inline-code">"INF"</code>, <code class="inline-code">"-INF"</code> and |
| <code class="inline-code">"NaN"</code> for positive/negative infinity and IEEE |
| floating point Not-a-Number, respectively. These are the XML |
| Schema compatible representations of these special values. |
| Earlier it has returned what |
| <code class="inline-code">java.text.DecimalFormat</code> did with US locale, |
| none of which was understood by any (common) computer |
| language.</p> |
| </li> |
| |
| <li> |
| <p>New built-in: |
| <code class="inline-code"><em class="code-color">someString</em>?boolean</code>. |
| This is for example useful for converting "true" and "false" |
| strings coming from XML to real boolean values. <a href="ref_builtins_string.html#ref_builtin_boolean">More...</a></p> |
| </li> |
| |
| <li> |
| <p>Date/time/date-time related changes:</p> |
| |
| <ul> |
| <li> |
| <p>Added new kind of |
| <code class="inline-code">date_format</code>/<code class="inline-code">datetime_format</code>/<code class="inline-code">time_format</code> |
| setting values: XML Schema formats, starting with |
| <code class="inline-code">"xs"</code> and ISO 8601:2004 formats, starting |
| with <code class="inline-code">"iso"</code>. The format string can be |
| continued with various space (or <code class="inline-code">_</code>) |
| separated options, like <code class="inline-code">h</code> or |
| <code class="inline-code">m</code> or <code class="inline-code">s</code> or |
| <code class="inline-code">ms</code> for setting shown accuracy, |
| <code class="inline-code">nz</code> or <code class="inline-code">fz</code> for setting |
| time zone offset visibility, and <code class="inline-code">u</code> or, |
| <code class="inline-code">fu</code> for using UTC time zone . For example, |
| to use ISO 8601 with minute precision and without the zone |
| offset being shown, set the |
| <code class="inline-code">datetime_format</code> setting to <code class="inline-code">"iso |
| m nz"</code>, so then the output will be like |
| <code class="inline-code">2014-09-03T20:56</code>. <a href="ref_directive_setting.html#topic.dateTimeFormatSettings">More...</a></p> |
| </li> |
| |
| <li> |
| <p>Because anything that's accepted as |
| <code class="inline-code">date_format</code>/<code class="inline-code">datetime_format</code>/<code class="inline-code">time_format</code> |
| setting value can also be used with the |
| <code class="inline-code">?string</code> and |
| <code class="inline-code">?date</code>/<code class="inline-code">?time</code>/<code class="inline-code">?datetime</code> |
| build-ins, you can use the new formats like |
| <code class="inline-code">someDate?string.xs</code> and |
| <code class="inline-code">someString?date.xs</code>. (For the |
| <code class="inline-code">"xs"</code> and <code class="inline-code">"iso"</code> |
| formats, <code class="inline-code">_</code> can be used instead of space, |
| which means that, for example, you can write |
| <code class="inline-code">lastModified?string.iso_m_u</code> instead of |
| the more verbose <code class="inline-code">lastModified?string["iso m |
| u"]</code>.)</p> |
| </li> |
| |
| <li> |
| <p>That <code class="inline-code">"iso"</code> and |
| <code class="inline-code">"xs"</code> are now possible |
| <code class="inline-code">date_format</code>/<code class="inline-code">datetime_format</code>/<code class="inline-code">time_format</code> |
| setting values also means that such values can now be parsed |
| too via |
| <code class="inline-code">?date</code>/<code class="inline-code">?time</code>/<code class="inline-code">?datetime</code>. |
| The main application is with processing XML DOM-s, as there |
| values are coming in as strings, and now you can do |
| something like <code class="inline-code">order.confirmDate?date.xs</code> |
| to convert them to real dates.</p> |
| </li> |
| |
| <li> |
| <p>The <a href="ref_builtins_date.html#ref_builtin_date_iso"><code>?iso_...</code> |
| built-ins</a> are now deprecated in favor of the new |
| setting values described above. They can be set as the |
| default date/time/date-time format, seamlessly fit into the |
| formatting architecture (and thus can parse strings too), |
| and has more/better options (<code class="inline-code">ms</code> always |
| shows 3 millisecond digits, <code class="inline-code">fz</code> for |
| forcing showing time zone offset).</p> |
| </li> |
| |
| <li> |
| <p>If the "incompatible improvements" |
| configuration setting is at least 2.3.21, the |
| <code class="inline-code">?iso_...</code> built-ins won't show time zone |
| offset for <code class="inline-code">java.sql.Time</code> values anymore. |
| Most databases store time values that aren't in any time |
| zone, but just store hour, minute, second, and decimal |
| second field values, so showing the time zone doesn't make |
| sense. (Notable exceptions are PostgreSQL "time with time |
| zone" columns, where |
| <code class="inline-code"><em class="code-color">mzTime</em>?string.iso_fz</code> |
| could be used.)</p> |
| </li> |
| |
| <li> |
| <p>Added <code class="inline-code">?is_time</code>, |
| <code class="inline-code">?is_datetime</code>, |
| <code class="inline-code">?is_date_only</code> (should be called |
| <code class="inline-code">?is_date</code>, but that was already taken) and |
| <code class="inline-code">?is_unknown_date_like</code> to check the exact |
| type of a date-like value.</p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code">?is_date</code> is now a deprecated name, |
| use <code class="inline-code">?is_date_like</code> instead. This is |
| because <code class="inline-code">?is_date</code> sounds like it checks if |
| the value is a date without time part, but actually it also |
| returns <code class="inline-code">true</code> for time, date-time, and |
| unknown date-like values.</p> |
| </li> |
| |
| <li> |
| <p>Added <code class="inline-code">?date_if_unknown</code>, |
| <code class="inline-code">?time_if_unknown</code> and |
| <code class="inline-code">?datetime_if_unknown</code> built-ins, which |
| mark a date-like value with some of the sub-types: date |
| without time, time, or date-time, respectively. However, if |
| the value already holds this information, the built-in has |
| no effect. That is, it will never convert the sub-type of a |
| value, it only adds the sub-type if it was unknown.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed: ISO 8601 dates (via |
| <code class="inline-code">?iso_...</code> and <code class="inline-code">"iso"</code> |
| format settings) now use proleptic Gregorian calendar for |
| the years before 1582, rather than Julian calendar. This is |
| (indirectly) required by the standard, and it's also how the |
| default Sun/Oracle Java XML Schema date/time/dateTime parser |
| works.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>Error message quality improvements (targeting frequent |
| support requests and some error message bugs):</p> |
| |
| <ul> |
| <li> |
| <p>Fixed glitch where if an <code class="inline-code">#if</code> had |
| and <code class="inline-code">#else</code> or <code class="inline-code">#elseif</code>, |
| the |
| <code class="inline-code">#if</code>/<code class="inline-code">#else</code>/<code class="inline-code">#elseif</code> |
| wasn't hidden in the FTL stack trace when the error was |
| inside its nested block.</p> |
| </li> |
| |
| <li> |
| <p>Some new context sensitive hints in undefined variable |
| exception error messages.</p> |
| </li> |
| |
| <li> |
| <p>Fixed unclosed directive error messages at end of file |
| where the wrong unclosed directive name was reported</p> |
| </li> |
| |
| <li> |
| <p>Better type error messages when accessing XML data |
| (applies when wrapped with |
| <code class="inline-code">freemarker.ext.dom</code>):</p> |
| |
| <ul> |
| <li> |
| <p>Trying to use |
| <code class="inline-code">node.<em class="code-color">noSuchChildNodes</em></code> |
| on a place where scalar value is expected will explain |
| that the problem is that you had no matches in the |
| constructing XML query.</p> |
| </li> |
| |
| <li> |
| <p>Trying to use |
| <code class="inline-code">node.<em class="code-color">multipleSuchChildNodes</em></code> |
| on a place where scalar value is expected will explain |
| that the problem is that you had multiple matches in the |
| constructing XML query.</p> |
| </li> |
| |
| <li> |
| <p>Trying to use |
| <code class="inline-code">node.<em class="code-color">exactlyOneChildNode</em></code> |
| as number, date/time/date-time or boolean will explain |
| that values coming from XML are always strings (text), |
| and must be converted explicitly via |
| <code class="inline-code">?number</code>, <code class="inline-code">?boolean</code>, |
| <code class="inline-code">?date.xs</code>, etc.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>Trying to use <code class="inline-code">obj.someMethod</code> |
| without <code class="inline-code">()</code> on a place where method value |
| is not expected will recommend calling the method.</p> |
| </li> |
| |
| <li> |
| <p>Trying to use methods like |
| <code class="inline-code">obj.getFoo</code> or |
| <code class="inline-code">obj.isFoo</code> without <code class="inline-code">()</code>on |
| a place where method value is not expected will recommend |
| using the <code class="inline-code">obj.foo</code> form.</p> |
| </li> |
| |
| <li> |
| <p>Messages are now much more readable when rendered in |
| environments that don't obey to line-breaks. (This often |
| happens in improperly implemented HTML error pages and logs |
| viewers.)</p> |
| </li> |
| |
| <li> |
| <p>Better FTL instruction stack traces:</p> |
| |
| <ul> |
| <li> |
| <p>Error messages now contain up to 10 lines of FTL |
| stack trace (unless it's on the top of a full FTL stack |
| trace), because the FTL stack trace wasn't printed at |
| all when the exception was a cause exception in a Java |
| stack trace, or when only the value of |
| <code class="inline-code">getMessage()</code> was printed instead of a |
| stack trace.</p> |
| </li> |
| |
| <li> |
| <p>The FTL stack trace is now more self explanatory |
| as it contains more text labels.</p> |
| </li> |
| |
| <li> |
| <p>Stack frames that belong to nestings are now |
| marked differently, and are filtered out when the stack |
| trace wouldn't fit into the error message |
| otherwise.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>Bug fixed: <code class="inline-code">?substring</code> has thrown |
| low level |
| <code class="inline-code">java.lang.IndexOutOfBoundsException</code>-s |
| instead of more descriptive |
| <code class="inline-code">TemplateModelException</code>-s with FTL stack |
| trace.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed: Slicing with ranges sometimes thrown low |
| level |
| <code class="inline-code">java.lang.IndexOutOfBoundsException</code>-s |
| instead of more descriptive |
| <code class="inline-code">TemplateModelException</code>-s with FTL stack |
| trace.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed [<a href="https://sourceforge.net/p/freemarker/bugs/402/">402</a>]: |
| Fixed misleading parser error message when a directive |
| called without its required parameters (like |
| <code class="inline-code"><#list></code>) was reported as unknown |
| directive.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/222/">222</a>]: |
| Poor quality error message when |
| <code class="inline-code"><em class="code-color">someString</em>[<em class="code-color">someIndex</em>]</code> |
| fails with string index out of bounds.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/27/">27</a>]: |
| Not very good quality error messages when |
| <code class="inline-code">#import</code>-ing a template whose parsing |
| fails.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>New <code class="inline-code">include</code> directive option, |
| <code class="inline-code">ignore_missing=<em class="code-color">boolean</em></code>. |
| When this is set to <code class="inline-code">true</code>, and the template to |
| include is missing, the error will be silently ignored, and |
| nothing will be included.</p> |
| </li> |
| |
| <li> |
| <p>The <code class="inline-code">setting</code> directive can now set the |
| <code class="inline-code">output_encoding</code> setting.</p> |
| </li> |
| |
| <li> |
| <p>New special variable: <code class="inline-code">.locale_object</code>. |
| This is like <code class="inline-code">.locale</code>, except that it's a |
| <code class="inline-code">java.util.Locale</code> object, not a string. This |
| is handy if you want to pass the current locale to Java |
| methods.</p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">incompatible_improvements</code> in the |
| FreeMarker configuration is set to at least 2.3.21, hash |
| <em>literals</em> that repeat keys now only have the |
| key once with <code class="inline-code">?keys</code>, and only has the last |
| value associated to that key with <code class="inline-code">?values</code>. |
| This is consistent with the behavior of |
| <code class="inline-code"><em class="code-color">hash</em>[<em class="code-color">key</em>]</code> |
| and how maps work in Java.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed: <code class="inline-code">?is_enumerable</code> has returned |
| <code class="inline-code">true</code> for Java methods get from Java objects, |
| despite that those values aren't <code class="inline-code"><#list |
| ...></code>-able. (This is actually a historical quirk of |
| <code class="inline-code">BeansWrapper</code>, not a bug in |
| <code class="inline-code">?is_enumerable</code>, but now |
| <code class="inline-code">?is_enumerable</code> is aware of this exceptional |
| case.)</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/257/">257</a>]: |
| The result value of <code class="inline-code">?matches</code> wasn't |
| "reentrant". For example, you couldn't list the |
| matches inside another listing where you are also listing |
| exactly the same result value (stored in a common variable), as |
| they would consume from the same iterator. Most importantly, |
| even accessing the <code class="inline-code">?size</code> of the same result |
| value has terminated the outer listing of the same value.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/229/">229</a>]: |
| If you set <code class="inline-code">incompatible_improvements</code> to |
| 2.3.21 (or higher), unclosed comments (<code class="inline-code"><#-- |
| <em class="code-color">...</em></code>) and |
| <code class="inline-code">#noparse</code>-s won't be silently closed at the |
| end of template anymore, but cause a parsing error |
| instead.</p> |
| </li> |
| </ul> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_180">Changes on the Java side</h2> |
| |
| |
| <ul> |
| <li> |
| <p>Added new <code class="inline-code">Configuration</code> constructor, |
| <code class="inline-code">Configuration(Version |
| incompatibleImprovements)</code>. This deprecates the vague |
| <code class="inline-code">Configuration()</code> constructor, and makes using |
| <code class="inline-code">setIncompatibleImprovements(Version)</code> needless |
| in most cases. See an example <a href="pgui_quickstart_createconfiguration.html">here...</a></p> |
| </li> |
| |
| <li> |
| <p>When setting the |
| <code class="inline-code">incompatible_improvements</code> setting (like with |
| the constructor above) to 2.3.21, two setting defaults |
| change:</p> |
| |
| <ul> |
| <li> |
| <p>The default of the <code class="inline-code">object_wrapper</code> |
| setting |
| (<code class="inline-code">Configuration.getObjectWrapper()</code>) |
| changes from |
| <code class="inline-code">ObjectWrapper.DEFAULT_WRAPPER</code> to another |
| almost identical <code class="inline-code">DefaultObjectWrapper</code> |
| singleton, returned by <code class="inline-code">new |
| DefaultObjectWrapperBuilder(Version).build()</code>. The |
| new default object wrapper's "incompatible |
| improvements" version is set to the same as of the |
| <code class="inline-code">Configuration</code>. (See later regarding the |
| 2.3.21 "incompatible improvements" of |
| <code class="inline-code">BeansWrapper</code> and |
| <code class="inline-code">DefaultObjectWrapper</code>). Furthermore, the |
| new default object wrapper doesn't allow changing its |
| settings; setter methods will throw |
| <code class="inline-code">IllegalStateException</code>. (If anything tries |
| to call setters on the old default in your application, |
| that's a dangerous bug that won't remain hidden now. As the |
| old default is a singleton too, potentially shared by |
| independently developed components, most of them expects the |
| out-of-the-box behavior from it (and the others are |
| necessarily buggy). Also, then concurrency glitches can |
| occur (and even pollute the class introspection cache) |
| because the singleton is modified after publishing.)</p> |
| </li> |
| |
| <li> |
| <p>The default of the <code class="inline-code">template_loader</code> |
| setting |
| (<code class="inline-code">Configuration.getTemplateLoader()</code>}) |
| changes to <code class="inline-code">null</code>, which means that |
| FreeMarker will not find any templates. Earlier the default |
| was a <code class="inline-code">FileTemplateLoader</code> that used the |
| current directory as the root. This was dangerous and |
| fragile as you usually don't have good control over what the |
| current directory will be. Luckily, the old default almost |
| never looked for the templates at the right place anyway, so |
| pretty much all applications had to set |
| <code class="inline-code">template_loader</code>, so it's unlikely that |
| changing the default breaks your application.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>New <code class="inline-code">BeansWrapper</code>, |
| <code class="inline-code">DefaultObjectWrapper</code> and |
| <code class="inline-code">SimpleObjectWrapper</code> constructor that takes a |
| <code class="inline-code">Version</code> |
| <code class="inline-code">incompatibleImprovements</code> argument. This has |
| the same role as the |
| <code class="inline-code">incompatible_improvements</code> setting of the |
| <code class="inline-code">Configuration</code>, but it applies to the |
| <code class="inline-code">ObjectWrapper</code> instead. (As |
| <code class="inline-code">ObjectWrapper</code>-s are often shared among |
| multiple <code class="inline-code">Configuration</code>-s, so they can't use |
| that setting of the <code class="inline-code">Configuration</code>.) In new or |
| actively developed projects it's recommended to use |
| <code class="inline-code">Configuration.VERSION_2_3_21</code> now. The |
| constructor without the <code class="inline-code">Version</code> parameter is |
| now deprecated.</p> |
| </li> |
| |
| <li> |
| <p>Safer and more memory-efficient way of managing singletons |
| of <code class="inline-code">DefaultObjectWrapper</code>-s and |
| <code class="inline-code">BeansWrapper</code>-s that are possibly shared by |
| independently developed subsystems:</p> |
| |
| <ul> |
| <li> |
| <p>Instead of <code class="inline-code">new |
| DefaultObjectWrapper(<em class="code-color">...</em>)</code> |
| and <code class="inline-code">new |
| BeansWrapper(<em class="code-color">...</em>)</code>, from |
| now on you should use <code class="inline-code">new |
| DefaultObjectWrapperBuilder(version).build()</code> and |
| <code class="inline-code">new BeansWrapperBuilder(version).build()</code>. |
| (The builder objects have properties (configuration |
| settings) like <code class="inline-code">BeansWrapper</code> has, which |
| specify the properties of the objects created.) The created |
| objects are <em>singletons</em> (VM-wide, or at |
| least Web-Application-wide) and read-only (means, |
| non-configurable, hence safe to share). The main benefit of |
| using these factories instead of creating new instances is |
| that it allows FreeMarker to share the class introspection |
| caches (an internal part of |
| <code class="inline-code">BeansWrapper</code>-s/<code class="inline-code">DefaultObjectWrapper</code>-s |
| that is expensive to populate) among the returned instances. |
| This allow sharing the caches (and the object wrappers) |
| between components that aren't aware of each other and use |
| FreeMarker internally.</p> |
| </li> |
| |
| <li> |
| <p>Deprecated the static fields |
| <code class="inline-code">ObjectWrapper.DEFAULT_WRAPPER</code>, |
| <code class="inline-code">BEANS_WRAPPER</code> and |
| <code class="inline-code">SIMPLE_WRAPPER</code>, because these |
| <code class="inline-code">ObjectWrapper</code>-s are configurable (not |
| read-only), and thus dangerous to use as singletons (a badly |
| behaving 3rd party component can mess them up). Use the |
| factories described above instead. They are also more |
| flexible, as you can specify the desired |
| incompatible-improvements version for them and various other |
| <code class="inline-code">BeansWrapper</code> settings.</p> |
| </li> |
| |
| <li> |
| <p>Deprecated all <code class="inline-code">SimpleHash</code>, |
| <code class="inline-code">SimpleCollection</code> and |
| <code class="inline-code">SimpleSequence</code> constructors that didn't |
| take an <code class="inline-code">ObjectWrapper</code> argument, as they |
| have usually used |
| <code class="inline-code">ObjectWrapper.DEFAULT_WRAPPER</code> as the |
| default, which itself is deprecated.</p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code">BeansWrapper</code>, |
| <code class="inline-code">DefaultObjectWrapper</code> and |
| <code class="inline-code">SimpleObjectWrapper</code> now implements the |
| <code class="inline-code">freemarker.template.utility.WriteProtectable</code> |
| interface with which the configuration properties of the |
| object wrapper can be set permanently to read-only by |
| calling <code class="inline-code">writeProtect()</code>. An attempt to |
| call a setter on a such <code class="inline-code">ObjectWrapper</code> |
| will immediately cause |
| <code class="inline-code">IllegalStateException</code>. (This is what's |
| used for the singletons returned by the |
| <code class="inline-code">getInstance</code> methods too; see |
| earlier).</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>The value of the <code class="inline-code">time_zone</code> setting, |
| when you specify it with a <code class="inline-code">String</code> (in a |
| <code class="inline-code">java.util.Properties</code> object, or via |
| <code class="inline-code"><#setting |
| <em class="code-color">...</em>></code>) can now be |
| <code class="inline-code">"JVM default"</code> to use the JVM default time |
| zone. The JVM default is the default value of that setting |
| anyway, but now you can state this explicitly, or restore this |
| value if it was overridden earlier.</p> |
| </li> |
| |
| <li> |
| <p>Added new configuration setting, |
| <code class="inline-code">sql_date_and_time_time_zone</code> |
| (<code class="inline-code">Configurable.setSQLDateAndTimeTimeZone(TimeZone)</code>). |
| When this is set to non-<code class="inline-code">null</code>, the time zone |
| used when dealing with <code class="inline-code">java.sql.Date</code> and |
| <code class="inline-code">java.sql.Time</code> values will be this time zone |
| instead of the value of the <code class="inline-code">time_zone</code> |
| FreeMarker configuration setting. This is useful because JDBC |
| will, usually, construct the Java <code class="inline-code">Date</code> |
| objects so that they will show the year-month-day and |
| hour-minute-seconds values from the database "as |
| is" if you render them using the JVM default time zone. |
| As time zone conversions for SQL date-only and SQL time-only |
| values doesn't make much sense (unlike for SQL timestamps), you |
| should certainly set this setting to the JVM default time zone |
| (<code class="inline-code">TimeZone.getDefault()</code>, or if you configure |
| FreeMarker via <code class="inline-code">java.util.Properties</code>, as |
| property value "JVM default"). The default value is |
| <code class="inline-code">null</code> for backward compatibility. For more |
| details see the JavaDoc of |
| <code class="inline-code">Configurable.setSQLDateAndTimeTimeZone(TimeZone)</code>.</p> |
| </li> |
| |
| <li> |
| <p>When configuring FreeMarker with |
| <code class="inline-code">java.util.Properties</code> (typically, when the |
| configuration is stored in a <code class="inline-code">.properties</code> |
| file), for the settings where you could specify a fully |
| qualified class name (most notably for the |
| <code class="inline-code">object_wrapper</code> setting) now you can also |
| specify constructor arguments and JavaBean property assignments. |
| For example, now you can write |
| <code class="inline-code">object_wrapper=com.example.MyObjectWrapper(1, 2, |
| exposeFields=true, cacheSize=5000)</code>that's nearly |
| equivalent with this Java code: <code class="inline-code">obj = new |
| com.example.MyObjectWrapper(1, 2); obj.setExposeFields(true); |
| obj.setCacheSize(5000); object_wrapper = obj;</code>. If you |
| are using this new syntax (i.e., if you have parentheses after |
| the class name, even if they are empty), and there's a builder |
| class for the requested class, that will be automatically used. |
| For example, |
| <code class="inline-code">object_wrapper=DefaultObjectWrapper(2.3.21)</code> |
| will create a <code class="inline-code">DefaultObjectWrapperBuilder</code> to |
| build the final instance, thus the object wrapper will be a |
| singleton instead of a new instance. The new syntax will also |
| look for a public static <code class="inline-code">INSTANCE</code> field if |
| there are 0 arguments and property assignments. For more details |
| see the Java API documentation of |
| <code class="inline-code">Configuration.setSetting</code>.</p> |
| </li> |
| |
| <li> |
| <p>Template not found exceptions now explain that the |
| template path is interpreted by a template loader, and show the |
| <code class="inline-code">toString</code> of the |
| <code class="inline-code">TemplateLoader</code>. The out-of-the-box |
| <code class="inline-code">TemplateLoader</code> implementations now have an |
| overridden <code class="inline-code">toString</code> to show the actual base |
| directory and such details. Custom |
| <code class="inline-code">TemplateLoader</code> implementations are encouraged |
| to override <code class="inline-code">toString</code>.</p> |
| </li> |
| |
| <li> |
| <p>Added |
| <code class="inline-code">Configuration.setSharedVariables(Map/*<String, |
| Object>*/)</code> for setting the shared variables from |
| Spring IoC and other IoC solutions. The already existing |
| <code class="inline-code">Configuration.setSharedVariable(String, |
| Object)</code> isn't a JavaBean property so it was hard to |
| use for that. Furthermore, the order in which |
| <code class="inline-code">Configuration.setObjectWrapper</code> and |
| <code class="inline-code">Configuration.setSharedVariables</code> are called |
| doesn't mater (unlike in the case of |
| <code class="inline-code">Configuration.setSharedVariable</code>), which is |
| essential in most IoC solutions.</p> |
| </li> |
| |
| <li> |
| <p>Mostly concerning tool (like IDE plugin) authors:</p> |
| |
| <ul> |
| <li> |
| <p><code class="inline-code">ParseException</code>-s now also store the |
| end-location of the error, not just its start-location. This |
| is useful if you want to underline the error in the source |
| code, not just point at it.</p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code">Configuration.getSupportedBuiltInDirectiveNames()</code> |
| can be used to return the names of directives supported by |
| FreeMarker.</p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code">TemplateExceptions</code> now expose the |
| position of the error (template name, line, column, end |
| line, end column) similarly to |
| <code class="inline-code">ParseException</code>-s. Where applicable, they |
| also expose the blamed expression in its canonical FTL |
| source form; this is mostly useful for |
| <code class="inline-code">InvalidReferenceException</code>-s.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>The concurrent performance of overloaded method lookups |
| (from the cache) was improved under Java 5 and later.</p> |
| </li> |
| |
| <li> |
| <p>The <code class="inline-code">Version</code> instances that are |
| "incompatible improvements" break points are now |
| available via constants like: |
| <code class="inline-code">Configuration.VERSION_2_3_21</code>.</p> |
| </li> |
| |
| <li> |
| <p>From now on, if you try to set the "incompatible |
| improvements" to greater than the current FreeMarker |
| version, or less than 2.3.0, an |
| <code class="inline-code">IllegalArgumentException</code> will be thrown. |
| Thus, <code class="inline-code">new |
| Configuration(<em class="code-color">someVersion</em>)</code> |
| not only activates the fixes up to that version, but ensures |
| that the application will not run in an environment with an |
| older FreeMarker version. (On an older FreeMarker version the |
| improvements that you have requested aren't implemented yet, so |
| you should get an exception.)</p> |
| </li> |
| |
| <li> |
| <p>Added new configuration setting, |
| <code class="inline-code">show_error_tips</code>, defaults to |
| <code class="inline-code">true</code>. Sets if tips should be shown in error |
| messages of errors arising during template processing.</p> |
| </li> |
| |
| <li> |
| <p>Instead of overriding |
| <code class="inline-code">BeansWrapper.finetuneMethodAppearance</code> (now |
| deprecated), now you can use |
| <code class="inline-code">BeansWrapper.setMethodAppearanceFineTuner(MethodAppearanceFineTuner)</code>, |
| so you don't need to extend the object wrapper class to |
| customize this aspect.</p> |
| </li> |
| |
| <li> |
| <p>Added |
| <code class="inline-code">Configuration.getCoreDirecticeNames()</code> which |
| returns the names of all directives that are provided by |
| FreeMarker. This can useful for IDE-s.</p> |
| </li> |
| |
| <li> |
| <p><code class="inline-code">template_loader</code> was added as possible |
| configuration setting <code class="inline-code">Properties</code> key.</p> |
| </li> |
| |
| <li> |
| <p>The standard <code class="inline-code">CacheStorage</code> |
| implementations now have a <code class="inline-code">getSize()</code> method |
| for monitoring the cache size. |
| <code class="inline-code">MruCacheStorage</code> also has |
| <code class="inline-code">getSoftSize()</code> and |
| <code class="inline-code">getStrongSize()</code>.</p> |
| </li> |
| |
| <li> |
| <p>Various smaller improvements in configuration setting |
| errors messages.</p> |
| </li> |
| |
| <li> |
| <p>With incompatible improvements 2.3.21 only: Empty ranges |
| return <code class="inline-code">Constants.EMPTY_SEQUENCE</code> instead of an |
| empty <code class="inline-code">SimpleSequence</code>. This is in theory |
| backward compatible, as the API only promises to give something |
| that implements <code class="inline-code">TemplateSequenceModel</code>.</p> |
| </li> |
| |
| <li> |
| <p>FreeMarker now requires Java version has changed from 1.2 |
| to 1.4.</p> |
| </li> |
| |
| <li> |
| <p>Bugs fixed and improvements in overloaded method |
| selection/invocation, but only if you create the |
| <code class="inline-code">BeansWrapper</code>/<code class="inline-code">DefaultObjectWrapper</code> |
| with constructor parameter |
| <code class="inline-code">Configuration.VERSION_2_3_21</code> (or if you are |
| using <code class="inline-code">Properties</code> to configure FreeMarker, you |
| can do that like |
| <code class="inline-code">object_wrapper=BeansWrapper(2.3.21)</code>), or if |
| you have a <code class="inline-code">Configuration</code> with similar |
| <code class="inline-code">incompatible_improvements</code> 2.3.21 |
| <em>and</em> you leave the |
| <code class="inline-code">object_wrapper</code> setting on its default value. |
| There's a little chance that because of these changes, a |
| different overloaded method will be chosen than before, or even |
| that ambiguity errors will arise where earlier they didn't |
| (although the opposite is far more frequent), hence the fixes |
| aren't automatically activated. But the fix mostly only effect |
| calls that were failing or have chosen then wrong method |
| earlier, so it's recommended to activate it for projects that |
| are still actively developed. This fix includes numerous |
| changes:</p> |
| |
| <ul> |
| <li> |
| <p>Earlier, <code class="inline-code">null</code> argument values has |
| only matched overloaded methods where the corresponding |
| parameter had <code class="inline-code">Object</code> type, not a subclass |
| of it. That's clearly a bug. Now it considers all overloads |
| where the parameter type is non-primitive, and just like the |
| Java language, it choses the one with the most specific type |
| among them. This is the most important fix, and also the |
| most risky one regarding backward-compatibility. Like if you |
| have <code class="inline-code">m(Object o)</code> and <code class="inline-code">m(String |
| s)</code> in a Java class, earlier for a |
| <code class="inline-code">m(null)</code> call in the template it has |
| chosen <code class="inline-code">m(Object o)</code>, but now it will |
| choose <code class="inline-code">m(String s)</code> instead (because |
| <code class="inline-code">String</code> is also |
| <code class="inline-code">null</code>-able and is more specific than |
| <code class="inline-code">Object</code>). Furthermore, if you also had |
| <code class="inline-code">m(File f)</code> in the same class, now it will |
| cause an ambiguity exception, since the specificity of |
| <code class="inline-code">File</code> and <code class="inline-code">String</code> can't |
| be compared (same rule as under Java language), while |
| earlier that wasn't a problem as only <code class="inline-code">m(Object |
| o)</code> was seen as applicable.</p> |
| </li> |
| |
| <li> |
| <p>The behavior of numbers with overloaded method |
| selection was heavily reworked:</p> |
| |
| <ul> |
| <li> |
| <p>If possible, it now always choses the overload |
| where overflow and truncation to integer (like 1.5 to 1) |
| is avoided. Among the methods where no such critical |
| loss occurs, it choses the overload with the least risk |
| of precision loss (unless other conditions with higher |
| priority suggest otherwise). Earlier, the method |
| selection was prone to do choices that led to overflow |
| or precision loss, especially when the parameter was a |
| literal with decimals.</p> |
| </li> |
| |
| <li> |
| <p>Overloaded method call can now convert to |
| non-primitive numerical types, like a |
| <code class="inline-code">Byte</code> or <code class="inline-code">byte</code> value |
| is automatically converted to <code class="inline-code">Integer</code> |
| if the parameter type is <code class="inline-code">Integer</code>. |
| (This has always worked for non-overloaded methods.) |
| Earlier where such conversion was needed, the method |
| wasn't seen seen applicable.</p> |
| </li> |
| |
| <li> |
| <p>Method selection is now not only based on the type |
| of the wrapped number, but also on its value. For |
| example, a <code class="inline-code">Long</code> with value |
| <code class="inline-code">1</code> is now seen as compatible with a |
| method with parameter type <code class="inline-code">int</code> or |
| <code class="inline-code">short</code> or <code class="inline-code">byte</code>, as |
| <code class="inline-code">1</code> can be stored in those without |
| loss. This is important as unlike in Java language, in |
| FTL you doesn't have strict control over the numerical |
| types (the type of the wrapped number, actually), as FTL |
| has no type declarations. (If multiple compatible |
| methods are available, it will still try to chose the |
| one with the same or bigger numerical type.)</p> |
| </li> |
| |
| <li> |
| <p>Conversion from/to <code class="inline-code">BigInteger</code> |
| is now supported.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>Method choice ambiguity errors now occur much less |
| often. Ambiguities was and are resolved by selecting the |
| compatible methods then choosing the one with the most |
| specific parameter types among them. The changes are:</p> |
| |
| <ul> |
| <li> |
| <p>When comparing the overall specificity of two |
| parameter lists: Earlier the parameter list seen as more |
| specific was the one that had some parameters that won |
| in specificity, and if both had such parameters then it |
| was an ambiguity. Now it's enough if a method has more |
| such parameters where it's a better match than the other |
| has, or if the two methods are still equal, if it has |
| the first better matching parameter. This can lead to |
| choices that seem arbitrary (but are still |
| deterministic), but as there's no automated way of |
| discovering method selection ambiguities in templates |
| (unlike in Java source code, where they will be detected |
| during compilation), especially as overloaded selection |
| has to rely on the <em>runtime</em> type of |
| the values which even make proper testing hard, this was |
| considered to be a better compromise than throwing an |
| exception whenever the choice of the method is not |
| obvious. Also note that in fact this mechanism is more |
| complicated than just counting the "winner" |
| parameter positions for each methods, as certain kind of |
| wins are stronger than any number of the others: wins |
| where the other possibility is risking of substantial |
| mantissa precision loss are the strongest (like dropping |
| decimals versus not to), wins where the primitive type |
| wins over the boxed class is the weakest (like |
| <code class="inline-code">int</code> versus |
| <code class="inline-code">Integer</code>), subclassing wins (like |
| <code class="inline-code">String</code> versus |
| <code class="inline-code">Object</code>) are between these two.</p> |
| </li> |
| |
| <li> |
| <p>When comparing the specificity of two parameters |
| types at the same parameter position: The algorithm now |
| considers a primitive type as more specific that its |
| corresponding boxing class (like <code class="inline-code">int</code> |
| is considered to be more specific than |
| <code class="inline-code">Integer</code>).</p> |
| </li> |
| |
| <li> |
| <p>There was a bug with overloaded varargs methods of |
| different parameter counts, where sometimes the last |
| parameters of the compared methods was ignored, which is |
| taking away a potential deciding factor and thus can |
| lead to ambiguity error. Whether this happened depends |
| on the order in which the Java reflection API has |
| returned the methods, which is undocumented and known to |
| change at least after some Java updates, breaking the |
| application.</p> |
| </li> |
| |
| <li> |
| <p>When comparing the specificity of two array types, |
| until now they were seen as equal. Now the component |
| types are compared, and then that with the less specific |
| component type is preferred. For example, among |
| <code class="inline-code">f(String[])</code> and |
| <code class="inline-code">f(Object[])</code>, the last will always |
| win. This might sounds controversial, but as we can't |
| efficiently tell the common type of all the items in a |
| sequence or <code class="inline-code">List</code>, and so we don't |
| know if both arrays are indeed valid targets, we go for |
| the safest choice.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>FTL sequence values (like Java |
| <code class="inline-code">List</code>-s or FTL |
| <code class="inline-code">[<em class="code-color">x</em>, |
| <em class="code-color">y</em>, |
| <em class="code-color">...</em>]</code> constants) were |
| not seen as applicable to a parameter with array type if |
| there were multiple overloaded methods with the same number |
| of parameters but with different types on the position of |
| the array parameter. That is, if you had |
| <code class="inline-code">f(String[])</code> and |
| <code class="inline-code">f(String)</code> in Java, then |
| <code class="inline-code">f(['foo', 'bar'])</code> in the template |
| reported no compatible overloads. Now it will choose |
| <code class="inline-code">f(String[])</code>. Note that if there's also an |
| <code class="inline-code">f(List)</code> or even an |
| <code class="inline-code">f(Collection)</code>, it will prefer those over |
| arrays. (For consistency, this conversion will work even if |
| the argument is a <code class="inline-code">List</code> that come directly |
| from Java (as opposed to be created inside FTL), i.e., when |
| it was wrapped then unwrapped to the original |
| <code class="inline-code">List</code> object.) For a multidimensional |
| array parameter type, this conversion works recursively, so |
| you can pass in a sequence-of-sequences as the |
| argument.</p> |
| </li> |
| |
| <li> |
| <p>FTL sequence values that wrapped a Java array (when |
| FreeMarker was also aware of that via |
| <code class="inline-code">AdapterTemplateModel</code> or |
| <code class="inline-code">WrapperTemplateModel</code>) were not seen as |
| applicable to a parameter with <code class="inline-code">List</code> type |
| if there were multiple overloaded methods with the same |
| number of parameters but with different types on the |
| position of the array parameter. So this is pretty much like |
| the issue described in the previous point, but for array to |
| <code class="inline-code">List</code> conversion. The array to |
| <code class="inline-code">List</code> conversion will be avoided if |
| possible, but it will be attempted if there's no other |
| alternative. Note that unlike with <code class="inline-code">List</code> |
| to array conversions, here FreeMarker can't cope with |
| multi-dimensional lists, that is, an array-of-arrays won't |
| be converted to a |
| <code class="inline-code">List</code>-of-<code class="inline-code">List</code>-s.</p> |
| </li> |
| |
| <li> |
| <p>FTL string to Java |
| <code class="inline-code">char</code>/<code class="inline-code">Character</code> |
| conversion now works for overloaded method parameters; |
| earlier it has worked for non-overloaded methods only. If |
| the string length is 1, it will be seen as compatible with |
| parameters with <code class="inline-code">char</code> or |
| <code class="inline-code">Character</code> type.</p> |
| </li> |
| |
| <li> |
| <p>Decreased the chance of choosing the wrong target Java |
| type when unwrapping multi-typed FTL values: When unwrapping |
| a parameter value that implements multiple FTL types (e.g. |
| string and hash) but doesn't implement |
| <code class="inline-code">AdapterTemplateModel</code> or |
| <code class="inline-code">WrapperTemplateModel</code>, a decision has to |
| be made if to what Java type the value should be unwrapped |
| to (e.g. to <code class="inline-code">String</code> or to |
| <code class="inline-code">Map</code>). In earlier versions that decision |
| was made based on the most specific common super type of the |
| parameters types of the given parameter position. However, |
| it's quite common that the common super type is too generic, |
| usually <code class="inline-code">Object</code>. Now |
| <code class="inline-code">BeansWrapper</code> stores "type |
| flags" for each parameter position of overloaded |
| methods, from which it can tell whether a potential target |
| Java type occurs in any of the overloads on the given |
| parameter position.</p> |
| </li> |
| |
| <li> |
| <p>In many cases, less specific hint class was used for |
| unwrapping than that was possible within the limitations of |
| the applied hint generation algorithm. (The unwrapping hint |
| has influence when there's an ambiguity regarding how to |
| create a Java object form an FTL value. In the vast majority |
| of the cases, a too generic hint has no effect.) (This is a |
| highly technical topic. The way it works is that a single |
| common unwrapping hint class is chosen for a given argument |
| position shared by the overloads that has the same number of |
| parameters, and that hint class has to be as specific as |
| possible while it must fit all those parameter types. The |
| issue with the too generic hints had several instances: (a) |
| When the most specific common class/interface of two |
| same-position parameter types was searched, if there was |
| multiple common classes/interfaces that had no relationship |
| (this is always at most one class and one or more unrelated |
| interfaces), due to the ambiguity it has felt back to using |
| <code class="inline-code">Object</code> as the unwrapping hint. Now if |
| there's a non-<code class="inline-code">Object</code> class among them in |
| such case, it will be chosen as the hint (i.e., we ignore |
| the common interfaces). Otherwise if only a single interface |
| remains by removing <code class="inline-code">Cloneable</code>, |
| <code class="inline-code">Serializable</code>, and |
| <code class="inline-code">Comparable</code> (in that order), that will be |
| chosen. Only then it falls back to |
| <code class="inline-code">Object</code>. (b) The common most specific |
| class of a primitive type and the corresponding boxing class |
| was sometimes <code class="inline-code">Object</code> instead of the |
| boxing class. This has depended on Java's internal ordering |
| of the methods, and so were quite unpredictable, like the |
| result could change after upgrading Java under the |
| application. (c) The common superclass of a numerical |
| primitive value and a numerical non-primitive value was |
| always <code class="inline-code">Object</code>, now if they are a |
| primitive-boxing class pair, then it's the boxing class, |
| otherwise it's <code class="inline-code">Number</code>. (d) If the varags |
| parameter position was not the same in all the overloaded |
| varargs methods, sometimes some varargs arguments where |
| unwrapped with too generic hints. When this happened was |
| unpredictable as it depended on Java's internal method |
| ordering again.)</p> |
| </li> |
| |
| <li> |
| <p>When unwrapping method call arguments before calling a |
| Java method, if the argument was an |
| <code class="inline-code">AdapterTemplateModel</code> and the target |
| parameter type was primitive, |
| <code class="inline-code">AdapterTemplateModel.getAdaptedObject(Class |
| hint)</code> has received the primitive type of the |
| target parameter (like <code class="inline-code">int</code> instead of |
| <code class="inline-code">Integer</code>) as the hint. This did not make |
| sense since <code class="inline-code">getAdaptedObject</code> can only |
| return <code class="inline-code">Object</code>-s, not primitive values. |
| Yet, <code class="inline-code">BeansWrapper</code> has expected the |
| returned value to be of the primitive type, otherwise it has |
| discarded it. Exactly the same problem occurs with |
| <code class="inline-code">WrapperTemplateModel</code>. Thus, ultimately, |
| if the target parameter type was primitive and some of these |
| interfaces were implemented, their return value was always |
| discarded and FreeMarker has felt back to other means of |
| unwrapping. Now <code class="inline-code">BeansWrapper</code> always |
| passes in and expects the boxing type (like |
| <code class="inline-code">Integer</code>) instead of the primitive |
| type.</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/373/">373</a>]: |
| These are three bugs actually, which can cause problems when |
| FreeMarker re-loads a template because of a charset override |
| with <code class="inline-code"><#ftl encoding="..."></code>: First, if |
| the template loader was a <code class="inline-code">URLTemplateLoader</code>, |
| when <code class="inline-code">TemplateLoader.getReader()</code> was called |
| for the second time, and the <code class="inline-code">Reader</code> returned |
| for the first time was already used, it might returned an empty |
| or corrupted template, depending on the backing URL |
| implementation. Secondly, when FreeMarer has decided if a |
| template file has to be re-loaded because its encoding specified |
| with <code class="inline-code"><#ftl encoding="..."></code> differs from |
| the encoding used for loading the template first, it has used |
| case-sensitive comparison, thus often re-loaded needlessly (like |
| "UTF-8" and "utf-8" mean the same). Now this comparison is |
| case-insensitive. Last not least, when retrying with the second |
| charset, the <code class="inline-code">TemplateCache</code> has forgotten to |
| close the first <code class="inline-code">Reader</code>, which can be a handle |
| leak.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/411/">411</a>]: |
| Invalid and redundant execution environment names from the OSGi |
| bundle manifest were removed. It looks like this now: |
| <code class="inline-code">Bundle-RequiredExecutionEnvironment: J2SE-1.5, |
| J2SE-1.4</code>. That is, we prefer (and compile against) |
| 1.5, but only require 1.4.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/409/">409</a>]: |
| <code class="inline-code">SimpleHash</code>'s internal <code class="inline-code">Map</code> |
| is concurrently modified on a non-safe way when getting length-1 |
| <code class="inline-code">String</code> key that exists but maps to |
| <code class="inline-code">null</code>. This operation will accidentally add a |
| <code class="inline-code">Character</code> key to the internal map, which is |
| not a thread-safe operation.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/273/">273</a>]: |
| <code class="inline-code">TemplateLoader</code>-s that use |
| <code class="inline-code">java.net.URLConnection</code>-s should set |
| <code class="inline-code">URLConnection.useCaches</code> to |
| <code class="inline-code">false</code>, or else it won't detect template |
| caches on certain configurations.</p> |
| |
| <ul> |
| <li> |
| <p><code class="inline-code">URLTemplateLoader</code> and its |
| subclasses and |
| <code class="inline-code">WebApplicationTemplateLoader</code> now has a |
| <code class="inline-code">setURLConnectionUsesCaches(Boolean)</code> |
| method. It's recommended to set this property to |
| <code class="inline-code">false</code> from its default backward |
| compatible value, <code class="inline-code">null</code>. As FreeMarker has |
| its own template cache with its own update delay setting |
| (<code class="inline-code">template_update_delay</code>, |
| <code class="inline-code">Configuration.setTemplateUpdateDelay(int)</code>), |
| it shouldn't cause performance problems. The |
| <code class="inline-code">null</code> value will leave the caching of the |
| <code class="inline-code">java.net.URLConnection</code> on its default, |
| which is usually <code class="inline-code">true</code>.</p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">incompatible_improvements</code> is set |
| to 2.3.21 (or higher) and templates are loaded through |
| <code class="inline-code">Configuration.getTemplate</code>, and the |
| <code class="inline-code">TemplateLoader</code> in use has |
| <code class="inline-code">URLConnectionUsesCaches</code> left on |
| <code class="inline-code">null</code>, it will behave as if it was set to |
| <code class="inline-code">false</code>. Note that this |
| <code class="inline-code">incompatible_improvements</code> trick only |
| works if the template is loaded through |
| <code class="inline-code">Configuration.getTemplate</code> (or |
| <code class="inline-code">TemplateCache</code>).</p> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <p>Bug fixed: When changing the properties of |
| <code class="inline-code">DefaultObjectWrapper</code> or |
| <code class="inline-code">BeansWrapper</code> that influenced class |
| introspection results (like <code class="inline-code">exposureLevel</code> or |
| <code class="inline-code">exposeFields</code>), the introspection cache wasn't |
| cleared, and thus returned stale information for the classes |
| that were introspected before those properties were changed. Now |
| changing such properties always clears the introspection |
| caches.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed: Constants used for empty sequence, empty hash, |
| empty collection and empty iterator weren't |
| <code class="inline-code">Serializable</code>.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/311/">300</a>]: |
| Logger class availability check was incorrect in that it has |
| checked the availability of logger libraries with the thread |
| context class loader, then later it tried to link to them with |
| the defining class loader of the FreeMarker classes. With some |
| class loader setups (notably under Netbeans sometimes) this led |
| to <code class="inline-code">ClassDefNotFoundError</code>-s that made |
| FreeMarker unusable. (The check itself was also not very |
| durable, as it didn't expected <code class="inline-code">LinakeError</code>-s, |
| only <code class="inline-code">ClassNotFoundException</code>.)</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed: <code class="inline-code">ClassUtil.forName</code>, used |
| inside FreeMarker everywhere to resolve class names to classes, |
| if the thread context class loader is <code class="inline-code">null</code>, |
| no longer tries to load with the bootstrap class loader before |
| loading with the defining class loader of FreeMarker.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/311/">311</a>]: |
| <code class="inline-code">TemplateBooleanModel.TRUE</code> and |
| <code class="inline-code">FALSE</code> are now serializable</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed: Various issues in <code class="inline-code">Version</code> |
| class, such as wrong <code class="inline-code">hashCode</code>, possible |
| concurrency glitches, and acceptance of some malformed version |
| strings.</p> |
| </li> |
| |
| <li> |
| <p>Bug fixed [<a href="https://sourceforge.net/p/freemarker/bugs/414/">414</a>]: |
| Eclipse debug mode running was suspended during FreeMarker |
| static initialization on the JRebel availability checked if |
| JRebel wasn't available.</p> |
| </li> |
| </ul> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_181">Other changes</h2> |
| |
| |
| <ul> |
| <li> |
| <p>The license has changed from our proprietary BSD-Style |
| license to the well know "Apache License, Version 2.0". |
| Furthermore, the copyright owner has changed from "Visigoth |
| Software Society" (which was founded by Jonathan Revusky) to the |
| three main FreeMarker 2 developers/contributors, "Attila |
| Szegedi, Daniel Dekany, and Jonathan Revusky". See the <a href="app_license.html">new license here</a>.</p> |
| </li> |
| |
| <li> |
| <p>The required minimum Java version was raised from 1.2 to |
| 1.4. FreeMarker will not work on Java 1.2 or 1.3.</p> |
| </li> |
| |
| <li> |
| <p>Many smaller improvements and fixes in the Manual and API |
| JavaDocs.</p> |
| </li> |
| </ul> |
| <div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="versions_2_3_22.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_3_20.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> |