blob: e792f202a2fe028f5d01781c8bad5214155bce2b [file] [log] [blame]
<!doctype html>
<!-- Generated by FreeMarker/Docgen from DocBook -->
<html lang="en" class="page-type-section">
<head prefix="og: http://ogp.me/ns#">
<meta charset="utf-8">
<title>2.3.27 (incubating at Apache) - 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.27 (incubating at Apache)">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="https://freemarker.apache.org/docs/versions_2_3_27.html">
<link rel="canonical" href="https://freemarker.apache.org/docs/versions_2_3_27.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_27.html"><span itemprop="name">2.3.27 (incubating at Apache)</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.27 (incubating at Apache)"];</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_28.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_3_26.html"><span>Next</span></a></div><div class="title-wrapper">
<h1 class="content-header header-section1" id="versions_2_3_27" itemprop="headline">2.3.27 (incubating at Apache)</h1>
</div></div><div class="page-menu">
<div class="page-menu-title">Page Contents</div>
<ul><li><a class="page-menu-link" href="#autoid_161" data-menu-target="autoid_161">Changes on the FTL side</a></li><li><a class="page-menu-link" href="#autoid_162" data-menu-target="autoid_162">Changes on the Java side</a></li></ul> </div><p>Release date: 2017-11-03</p><p><strong>This is a stable, final
release.</strong> The "incubating" suffix is required
by the Apache Software Foundation until the project becomes a fully
accepted (graduated) Apache project.</p>
<h2 class="content-header header-section2" id="autoid_161">Changes on the FTL side</h2>
<ul>
<li>
<p>New directive: <code class="inline-code">continue</code> (<a href="https://sourceforge.net/p/freemarker/feature-requests/79/">sf.net
#79</a>, <a href="https://issues.apache.org/jira/browse/FREEMARKER-37">FREEMARKER-37</a>).
This can be used inside the <code class="inline-code">list</code> directive to
skip to the next iteration (similarly as in Java). <a href="ref_directive_list.html#ref.directive.list.continue">See more...</a></p>
</li>
<li>
<p>Added alternative syntaxes for the
<code class="inline-code">&amp;&amp;</code> (logical "and")
operator: <code class="inline-code">\and</code> and
<code class="inline-code">&amp;amp;&amp;amp;</code>. These are to work around
issues in applications where the template must be valid XML
(<code class="inline-code">&amp;&amp;</code> is not valid XML/HTML, at most
places), or where the template entered is stored after XML or
HTML escaping. Note that lonely <code class="inline-code">&amp;amp;</code>,
and <code class="inline-code">and</code> without <code class="inline-code">\</code> is not
recognized for backward compatibility.</p>
</li>
<li>
<p>New built-in, <code class="inline-code">sequence</code> (<a href="https://issues.apache.org/jira/browse/FREEMARKER-73">FREEMARKER-73</a>).
This can be used to work around situations where a listable
value lacks some features that you need in the template (like it
can&#39;t be listed twice, it can&#39;t tell its size, etc.), and you
can&#39;t modify the data-model to fix the problem. <a href="ref_builtins_expert.html#ref_builtin_sequence">See more...</a></p>
</li>
<li>
<p>Bug fixed (<a href="https://issues.apache.org/jira/browse/FREEMARKER-70">FREEMARKER-70</a>):
The usage of loop variable built-ins, like
<code class="inline-code"><em class="code-color">loopVar</em>?index</code>, was
disallowed by the parser inside interpolations that are inside a
string literal expression (as in <code class="inline-code">&lt;#list 1..3 as
loopVar&gt;${&#39;${loopVar?index}&#39;}&lt;/#list&gt;</code>),
saying that there&#39;s no loop variable in scope with
<code class="inline-code"><em class="code-color">loopVar</em></code>
name.</p>
</li>
<li>
<p>Bug fixed: Comments were not allowed by the parser between
the <code class="inline-code">switch</code> tag and the first
<code class="inline-code">case</code> tag.</p>
</li>
<li>
<p>Bug fixed (<a href="https://issues.apache.org/jira/browse/FREEMARKER-71">FREEMARKER-71</a>):
When using
<code class="inline-code"><em class="code-color">exp</em>?eval</code>, if the
expression inside the evaluated string throws an exception, the
cause exception of that exception was lost.</p>
</li>
</ul>
<h2 class="content-header header-section2" id="autoid_162">Changes on the Java side</h2>
<ul>
<li>
<p>Added new configuration setting (<a href="https://issues.apache.org/jira/browse/FREEMARKER-48">FREEMARKER-48</a>),
<code class="inline-code">wrap_unchecked_exceptions</code>
(<code class="inline-code">Configurable.setWrapUncheckedExceptions(boolean)</code>).
When this is <code class="inline-code">true</code>, unchecked exceptions
thrown during evaluating an expression or during executing a
custom directive will be wrapped into a
<code class="inline-code">TemplateException</code>-s. The advantage of that is
that thus the exception will include the location in the
template (not just the Java stack trace), and the
<code class="inline-code">TemplateExceptionHandler</code> will be invoked for
it as well. When this setting is <code class="inline-code">false</code> (which
is the default for backward compatibility), the the unchecked
exception will bubble up and thrown by
<code class="inline-code">Template.process</code>, just as in earlier
versions. (Note that plain Java methods called from templates
have always wrapped the thrown exception into
<code class="inline-code">TemplateException</code>, regardless of this
setting.)</p>
</li>
<li>
<p>Added new configuration setting,
<code class="inline-code">attempt_exception_reporter</code>
(<code class="inline-code">Configurable.setAttemptExceptionReporter(AttemptExceptionReporter)</code>),
to allow the customization of how the exceptions handled (and
thus suppressed) by the <a href="ref_directive_attempt.html#ref.directive.attempt"><code>attempt</code>
directive</a> are reported. The default
<code class="inline-code">AttemptExceptionReporter</code> logs the exception
as an error, just as it was in earlier versions, though now the
error message will indicate that the exception was thrown inside
an <code class="inline-code">attempt</code> directive block.</p>
</li>
<li>
<p>Added new <code class="inline-code">BeansWrapper</code> setting,
<code class="inline-code">preferIndexedReadMethod</code>. This was added to
address a Java 8 compatibility problem; see the bug fix entry
below for more information.</p>
</li>
<li>
<p>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.27 (or higher), the following unchecked exceptions
(but not their subclasses) will be wrapped into
<code class="inline-code">TemplateException</code>-s when thrown during
evaluating expressions or calling directives:
<code class="inline-code">NullPointerException</code>,
<code class="inline-code">ClassCastException</code>,
<code class="inline-code">IndexOutOfBoundsException</code>, and
<code class="inline-code">InvocationTargetException</code>. The goal of this
is the same as of setting the
<code class="inline-code">wrap_unchecked_exceptions</code> setting to
<code class="inline-code">true</code> (see that earlier), but this is more
backward compatible, as it avoids wrapping unchecked exceptions
that some application is likely to catch specifically (like
application-specific unchecked exceptions). (This is related to
<a href="https://issues.apache.org/jira/browse/FREEMARKER-48">FREEMARKER-48</a>.)</p>
</li>
<li>
<p>Bug fixed: Starting from Java 8, when the same JavaBeans
property has both non-indexed read method (like
<code class="inline-code">String[] getFoos()</code>) and indexed read method
(like <code class="inline-code">String getFoos(int index)</code>),
<code class="inline-code">BeansWrapper</code> and
<code class="inline-code">DefaultObjectWrapper</code> have mistakenly used the
indexed read method to access the property. This is a problem
because then the array size was unknown, and thus the property
has suddenly become unlistable on Java 8 (that is,
<code class="inline-code">&lt;#list myObject.foos as foo&gt;</code> fails). To
enable the fix (where it will use the non-indexed read method),
you should increase the value of the
<code class="inline-code">incompatibleImprovements</code> constructor argument
of the used <code class="inline-code">DefaultObjectWrapper</code> or
<code class="inline-code">BeansWrapper</code> to 2.3.27. Note that if you
leave the <code class="inline-code">object_wrapper</code> setting of the
<code class="inline-code">Configuration</code> on its default, it&#39;s enough to
increase the <a href="pgui_config_incompatible_improvements.html#pgui_config_incompatible_improvements_how_to_set"><code>incompatibleImprovements</code>
setting</a> of the <code class="inline-code">Configuration</code> to
2.3.27, as that&#39;s inherited by the default
<code class="inline-code">object_wrapper</code>. In case increasing the
<code class="inline-code">incompatibleImprovements</code> is not an option
(because of the other changes it brings), you can instead set
the <code class="inline-code">preferIndexedReadMethod</code> property of the
object wrapper to <code class="inline-code">false</code>. Note that this bug
haven&#39;t surfaced before Java 8, as then
<code class="inline-code">java.beans.Inrospector</code> has only exposed the
non-indexed method when both kind of read method was
present.</p>
</li>
<li>
<p>Bug fixed (affects Java 8 and later): Regardless of the
value of the <code class="inline-code">preferIndexedReadMethod</code> setting
(see previous point), if one of the indexed read method and the
non-indexed read method is inaccessible (i.e., it&#39;s declared in
a non-public type, and wasn&#39;t inherited by a public type), while
the other read method is accessible, we will use the accessible
one. Earlier, if there was an indexed read method but it was
inaccessible, we have given up, and that bean property wasn&#39;t
visible. Such properties will now be visible again, just as
before Java 8. (Before Java 8
<code class="inline-code">java.beans.Inrospector</code> has only exposed the
non-indexed read method in this case, so we didn&#39;t have this
problem.)</p>
</li>
<li>
<p>Bug fixed: On OpenJDK 9 (but not on earlier versions, nor
on Oracle Java 9 (tested with "build 9+181")), when
you try to use the DOM-based XML support
(<code class="inline-code">freemarker.ext.dom.NodeModel</code>), unless you
happen to have Apache Xalan in the class path, the
<code class="inline-code">NodeModel</code> constructor will fail with
<code class="inline-code">IllegalAccessError</code> because "java.xml
does not export com.sun.org.apache.xml.internal.utils".
Note that while the exception is not thrown anymore in 2.3.27,
FreeMarker can&#39;t use the XPath support included in OpenJDK 9,
and so templates that try to use XPath expressions (like
<code class="inline-code">doc[&#39;//foo&#39;]</code>) will still fail, <a href="xgui_imperative_learn.html#xgui_imperative_learn_xpath">unless 3rd party XPath
support is present</a>.</p>
</li>
<li>
<p>Bug fixed: When the
<code class="inline-code">TemplateExceptionHandler</code> suppresses (i.e.,
doesn&#39;t re-throw) an exception, the <a href="ref_directive_attempt.html#ref.directive.attempt"><code>attempt</code>
directive</a> won&#39;t log it anymore. (To be precise, the
<code class="inline-code">AttemptExceptionReporter</code> won&#39;t be invoked for
it anymore; the default one logs as error.)</p>
</li>
<li>
<p>Bug fixed (part of <a href="https://issues.apache.org/jira/browse/FREEMARKER-48">FREEMARKER-48</a>):
When an arithmetic exception has occurred in an expression
(typically division by zero), the template processing has thrown
the <code class="inline-code">ArithmeticException</code> as is, without
packaging it into a <code class="inline-code">TemplateException</code>. Thus,
the error location in the template wasn&#39;t visible in the
exception.</p>
</li>
<li>
<p>When logging error due to an error in an <a href="ref_directive_attempt.html#ref.directive.attempt"><code>attempt</code>
directive</a> block, the log message now indicates that the
error was inside an <code class="inline-code">attempt</code> block.</p>
</li>
<li>
<p>Bug fixed (<a href="https://issues.apache.org/jira/browse/FREEMARKER-52">FREEMARKER-52</a>):
When setting the <code class="inline-code">output_format</code> from
<code class="inline-code">Properties</code> or the <code class="inline-code">setSetting(String,
String)</code> API, the <code class="inline-code">XHTMLOutputFormat</code>
abbreviation wasn&#39;t recognized (for example in a
<code class="inline-code">.properties</code> file,
<code class="inline-code">output_format=XHTMLOutputFormat</code> didn&#39;t work,
only
<code class="inline-code">output_format=freemarker.core.XHTMLOutputFormat()</code>
did).</p>
</li>
<li>
<p>Bug fixed: When setting the
<code class="inline-code">new_builtin_resolver</code> from
<code class="inline-code">Properties</code> or the <code class="inline-code">setSetting(String,
String)</code> API, it didn&#39;t recognize the camel case form
of the <code class="inline-code">allowed_classes</code> and
<code class="inline-code">trusted_templates</code> keywords, and throw
exception for them. Now <code class="inline-code">allowedClasses</code> and
<code class="inline-code">trustedTemplates</code> can be used as well.</p>
</li>
<li>
<p>Bug fixed: JSP support haven&#39;t tried using the thread
context class-loader to load the TLD, instead, it has only used
the defining class loader of the FreeMarker classes. This can
cause problem in the rare case where
<code class="inline-code">freemarker.jar</code> is installed on higher scope
than the web application (like on the Servlet container level),
but the web application contains the TLD.</p>
</li>
<li>
<p><code class="inline-code">Constants.EMPTY_HASH</code> and
<code class="inline-code">GeneralPurposeNothing</code> (the value of
<code class="inline-code">missingVar!</code>) now implements
<code class="inline-code">TemplateHashModelEx2</code>. Earlier they were only
a <code class="inline-code">TemplateHashModelEx</code>-s.</p>
</li>
<li>
<p>Added
<code class="inline-code">Constants.EMPTY_KEY_VALUE_PAIR_ITERATOR</code></p>
</li>
<li>
<p>Somewhat less synchronization when accessing JavaBean
properties (<a href="https://issues.apache.org/jira/browse/FREEMARKER-80">FREEMARKER-80</a>).
The problem was that the
<code class="inline-code">java.beans.PropertyDescriptor.getReadMethod</code>
method is synchronized, and
<code class="inline-code">freemarer.ext.beans.BeanModel</code> has called it
each time a property was read. Now that method is only called
when the class is first introspected.</p>
</li>
<li>
<p>Improved/fixed <code class="inline-code">TemplateTransformModel</code>
behavior (this is a legacy interface that&#39;s not used much in
user code):</p>
<ul>
<li>
<p><code class="inline-code">Writer
TemplateTransformModel.getWriter(Writer out, Map
args)</code> can now return the <code class="inline-code">out</code>
parameter as is, as FreeMarker now recognizes that it&#39;s the
same object and so won&#39;t call <code class="inline-code">close()</code> on
it after the end tag.</p>
</li>
<li>
<p>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.27 (or higher), and the returned
<code class="inline-code">Writer</code> implements
<code class="inline-code">TransformControl</code>, exceptions that are
used internally for flow control (for
<code class="inline-code">&lt;#return&gt;</code>,
<code class="inline-code">&lt;#break&gt;</code>, etc.) won&#39;t be passed to
<code class="inline-code">TransformControl.onError(Throwable)</code>
anymore. Earlier, if <code class="inline-code">onError</code> didn&#39;t
rethrow the exception (though almost all implementation
does), you couldn&#39;t use said directives inside the
transformed block.</p>
</li>
</ul>
</li>
<li>
<p>Added workaround against "IllegalStateException: zip
file closed" and "ZipException: ZipFile
closed" issues (caused by bugs outside of FreeMarker)
when loading resources included in the FreeMarker jar (see
<code class="inline-code">freemarker.template.utility.ClassUtil.loadProperties</code>).</p>
</li>
</ul>
<div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="versions_2_3_28.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_3_26.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>