blob: 2b00d8bfaba613885d2ef44d74e037d4efd2a4a6 [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>Error handling - 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="FreeMarker Manual">
<meta property="og:title" content="Error handling">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="http://example.com/pgui_config_errorhandling.html">
<link rel="canonical" href="http://example.com/pgui_config_errorhandling.html">
<link rel="icon" href="favicon.png" type="image/png">
<link rel="stylesheet" type="text/css" href="docgen-resources/docgen.min.css?1594338519184">
</head>
<body itemscope itemtype="https://schema.org/Code">
<meta itemprop="url" content="http://example.com/">
<meta itemprop="name" content="FreeMarker Manual">
<!--[if lte IE 9]>
<div style="background-color: #C00; color: #fff; padding: 12px 24px;">Please use a modern browser to view this website.</div>
<![endif]--><div class="header-top-bg"><div class="site-width header-top"><a class="logo" href="http://example.com" role="banner"> <img itemprop="image" src="logo.png" alt="My Logo">
</a></div></div><div class="header-bottom-bg"><div class="site-width search-row"><a href="index.html" class="navigation-header">FreeMarker Manual</a><div class="navigation-header"></div></div><div class="site-width breadcrumb-row"><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">FreeMarker Manual</span></a></li><li class="step-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="pgui.html"><span itemprop="name">Programmer&#39;s Guide</span></a></li><li class="step-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="pgui_config.html"><span itemprop="name">The Configuration</span></a></li><li class="step-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="pgui_config_errorhandling.html"><span itemprop="name">Error handling</span></a></li></ul><div class="bookmarks" title="Bookmarks"><span class="sr-only">Bookmarks:</span><ul class="bookmark-list"><li><a href="alphaidx.html">Index</a></li><li><a href="gloss.html">Glossary</a></li><li><a href="ref.html">Reference</a></li><li><a href="app_faq.html">FAQ</a></li><li><a href="preface.html#test_target">Bőregér</a></li><li><a href="api/index.html">API</a></li><li><a href="../index.html">Home</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 = ["FreeMarker Manual","Programmer\'s Guide","The Configuration","Error handling"];</script>
<script src="toc.js?1594338519184"></script>
<script src="docgen-resources/main.min.js?1594338519184"></script>
</div>
<div class="col-right"><div class="page-content"><div class="page-title"><div class="pagers top"><a class="paging-arrow previous" href="pgui_config_templateloading.html"><span>Previous</span></a><a class="paging-arrow next" href="pgui_misc.html"><span>Next</span></a></div><div class="title-wrapper">
<h1 class="content-header header-section1" id="pgui_config_errorhandling" itemprop="headline">Error handling</h1>
</div></div><div class="page-menu">
<div class="page-menu-title">Page Contents</div>
<ul><li><a class="page-menu-link" href="#autoid_43" data-menu-target="autoid_43">The possible exceptions</a></li><li><a class="page-menu-link" href="#autoid_44" data-menu-target="autoid_44">Customizing the behavior regarding TemplatException-s</a></li><li><a class="page-menu-link" href="#autoid_45" data-menu-target="autoid_45">Explicit error handling in templates</a></li></ul> </div>
<h2 class="content-header header-section2" id="autoid_43">The possible exceptions</h2>
<p>The exceptions that can occur regarding FreeMarker could be
classified like this:</p>
<ul>
<li>
<p>Exceptions occurring when you configure FreeMarker:
Typically you configure FreeMarker only once in your
application, when your application initializes itself. Of
course, during this, exceptions can occur, as it is obvious from
the FreeMarker API...</p>
</li>
<li>
<p>Exceptions occurring when loading and parsing templates:
When you call
<code class="inline-code">Configuration.getTemplate(<em class="code-color">...</em>)</code>,
FreeMarker has to load the template file into the memory and
parse it (unless the template is already <a href="pgui_config_templateloading.html#pgui_config_templateloading_caching">cached</a> in
that <code class="inline-code">Configuration</code> object). During this, two
kind of exceptions can occur:</p>
<ul>
<li>
<p><code class="inline-code">IOException</code> because the template
file was not found, or other I/O problem occurred while
trying to read it, for example you have no right to read the
file, or there are disk errors. The emitter of these errors
is the <a href="pgui_config_templateloading.html"><code>TemplateLoader</code>
object</a>, which is plugged into the
<code class="inline-code">Configuration</code> object. (For the sake of
correctness: When I say ``file&#39;&#39; here, that&#39;s a
simplification. For example, templates can be stored in a
table of a relational database as well. This is the business
of the <code class="inline-code">TemplateLoader</code>.)</p>
</li>
<li>
<p><code class="inline-code">freemarker.core.ParseException</code>
because the template file is syntactically incorrect
according the rules of the FTL language. The point is that
this error occurs when you obtain the
<code class="inline-code">Template</code> object
(<code class="inline-code">Configuration.getTemplate(<em class="code-color">...</em>)</code>),
and not when you execute
(<code class="inline-code">Template.process(<em class="code-color">...</em>)</code>)
the template. This exception is an
<code class="inline-code">IOException</code> subclass.</p>
</li>
</ul>
</li>
<li>
<p>Exceptions occurring when executing (processing)
templates, that is, when you call
<code class="inline-code">Template.process(<em class="code-color">...</em>)</code>.
Two kind of exceptions can occur:</p>
<ul>
<li>
<p><code class="inline-code">IOException</code> because there was an
error when trying to write into the output writer.</p>
</li>
<li>
<p><code class="inline-code">freemarker.template.TemplatException</code>
because other problem occurred while executing the template.
For example, a frequent error is when a template refers to a
variable which is not existing. Be default, when a
<code class="inline-code">TemplatException</code> occurs, FreeMarker
prints the FTL error message and the stack trace to the
output writer with plain text format, and then aborts the
template execution by re-throwing the
<code class="inline-code">TemplatException</code>, which then you can
catch as
<code class="inline-code">Template.process(<em class="code-color">...</em>)</code>
throws it. But this behavior can be customized. FreeMarker
always <a href="pgui_misc_logging.html">logs</a>
<code class="inline-code">TemplatException</code>-s.</p>
</li>
</ul>
</li>
</ul>
<h2 class="content-header header-section2" id="autoid_44">Customizing the behavior regarding TemplatException-s</h2>
<p><code class="inline-code">TemplateException</code>-s thrown during the
template processing are handled by the
<code class="inline-code">freemarker.template.TemplateExceptionHandler</code>
object, which is plugged into the <code class="inline-code">Configuration</code>
object with its
<code class="inline-code">setTemplateExceptionHandler(<em class="code-color">...</em>)</code>
mehod. The <code class="inline-code">TemplateExceptionHandler</code> contains 1
method:</p>
<div class="code-wrapper"><pre class="code-block code-unspecified">void handleTemplateException(TemplateException te, Environment env, Writer out)
throws TemplateException;</pre></div>
<p>Whenever a <code class="inline-code">TemplateException</code> occurs, this
method will be called. The exception to handle is passed with the
<code class="inline-code">te</code> argument, the runtime environment of the
template processing is accessible with the <code class="inline-code">env</code>
argument, and the handler can print to the output using the
<code class="inline-code">out</code> argument. If the method throws exception
(usually it re-throws <code class="inline-code">te</code>), then the template
processing will be aborted, and
<code class="inline-code">Template.process(<em class="code-color">...</em>)</code>
will throw the same exception. If
<code class="inline-code">handleTemplateException</code> doesn&#39;t throw exception,
then template processing continues as if nothing had happen, but the
statement that caused the exception will be skipped (see more
later). Of course, the handler can still print an error indicator to
the output.</p>
<p>In any case, before the
<code class="inline-code">TemplateExceptionHandler</code> is invoked, FreeMarker
will <a href="pgui_misc_logging.html">log</a> the
exception.</p>
<p>Let&#39;s see how FreeMarker skips ``statements&#39;&#39; when the error
handler doesn&#39;t throw exception, through examples. Assume we are
using this template exception handler:</p>
<div class="code-wrapper"><pre class="code-block code-unspecified">class MyTemplateExceptionHandler implements TemplateExceptionHandler {
public void handleTemplateException(TemplateException te, Environment env, java.io.Writer out)
throws TemplateException {
try {
out.write(&quot;[ERROR: &quot; + te.getMessage() + &quot;]&quot;);
} catch (IOException e) {
throw new TemplateException(&quot;Failed to print error message. Cause: &quot; + e, env);
}
}
}
<em>...</em>
cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());</pre></div>
<p>If an error occurs in an interpolation which is not inside an
FTL tag (that is, not enclosed into
<code class="inline-code">&lt;#<em class="code-color">...</em>&gt;</code> or
<code class="inline-code">&lt;@<em class="code-color">...</em>&gt;</code>), then
the whole interpolation will be skipped. So this template (assuming
that <code class="inline-code">badVar</code> is missing from the
data-model):</p>
<div class="code-wrapper"><pre class="code-block code-template">a${badVar}b</pre></div>
<p>will print this if we use the
<code class="inline-code">MyTemplateExceptionHandler</code>:</p>
<div class="code-wrapper"><pre class="code-block code-output">a[ERROR: Expression badVar is undefined on line 1, column 4 in test.ftl.]b</pre></div>
<p>This template will print the same (except that the column
number will differ...):</p>
<div class="code-wrapper"><pre class="code-block code-template">a${&quot;moo&quot; + badVar}b</pre></div>
<p>since, as it was written, the whole interpolation is skipped
if any error occurs inside it.</p>
<p>If an error occurs when evaluating the value of a parameter
for a directive call, or if there are other problems with the
parameter list, or if an error occurs when evaluating
<code class="inline-code"><em class="code-color">exp</em></code> in
<code class="inline-code">&lt;@<em class="code-color">exp</em>
<em class="code-color">...</em>&gt;</code>, or if the value of
<code class="inline-code"><em class="code-color">exp</em></code> is not an
user-defined directive, then the whole directive call is skipped.
For example this:</p>
<div class="code-wrapper"><pre class="code-block code-template">a&lt;#if badVar&gt;Foo&lt;/#if&gt;b</pre></div>
<p>will print this:</p>
<div class="code-wrapper"><pre class="code-block code-output">a[ERROR: Expression badVar is undefined on line 1, column 7 in test.ftl.]b</pre></div>
<p>Note that the error occurred in the <code class="inline-code">if</code>
start-tag (<code class="inline-code">&lt;#if badVar&gt;</code>), but the whole
directive call was skipped. Logically, the nested content
(<code class="inline-code">Foo</code>) was skipped with this, since the nested
content is handled (printed) by the enclosing directive
(<code class="inline-code">if</code>).</p>
<p>The output will be the same with this (except that the column
number will differ...):</p>
<div class="code-wrapper"><pre class="code-block code-template">a&lt;#if &quot;foo${badVar}&quot; == &quot;foobar&quot;&gt;Foo&lt;/#if&gt;b</pre></div>
<p>since, as it was written, the whole directive calling will be
skipped if any error occurs during the parameter evaluation.</p>
<p>The directive call will not be skipped if the error occurs
after the execution of the directive was already started. That is,
if an error occurs in the nested content:</p>
<div class="code-wrapper"><pre class="code-block code-template">a
&lt;#if true&gt;
Foo
${badVar}
Bar
&lt;/#if&gt;
c</pre></div>
<p>or in the macro definition body:</p>
<div class="code-wrapper"><pre class="code-block code-template">a
&lt;@test /&gt;
b
&lt;#macro test&gt;
Foo
${badVar}
Bar
&lt;/#macro&gt;</pre></div>
<p>the output will be something like:</p>
<div class="code-wrapper"><pre class="code-block code-output">a
Foo
[ERROR: Expression badVar is undefined on line 4, column 5 in test.ftl.]
Bar
c</pre></div>
<p>FreeMarker comes with these prewritten error handlers:</p>
<ul>
<li>
<p><code class="inline-code">TemplateExceptionHandler.DEBUG_HANDLER</code>:
Prints stack trace (includes FTL error message and FTL stack
trace) and re-throws the exception. This is the default handler
(that is, it is initially prugged into all new
<code class="inline-code">Configuration</code> objects).</p>
</li>
<li>
<p><code class="inline-code">TemplateExceptionHandler.HTML_DEBUG_HANDLER</code>:
Same as <code class="inline-code">DEBUG_HANDLER</code>, but it formats the
stack trace so that it will be readable with Web browsers.
Recommended over <code class="inline-code">DEBUG_HANDLER</code> when you
generate HTML pages.</p>
</li>
<li>
<p><code class="inline-code">TemplateExceptionHandler.IGNORE_HANDLER</code>:
Simply suppresses all exceptions (but remember, FreeMarker will
still log them). It does nothing to handle the event. It does
not re-throw the exception.</p>
</li>
<li>
<p><code class="inline-code">TemplateExceptionHandler.RETHROW_HANDLER</code>:
Simply re-throws all exceptions, it doesn&#39;t do anything else.
This handler can be good for Web applications (assuming you
don&#39;t want to continue template processing after exception),
because it gives the most control to the Web application over
page generation on error conditions (since FreeMarker doesn&#39;t
print anything to the output about the error). For more
information about handling errors in Web applications <a href="app_faq.html#misc.faq.niceErrorPage">see the FAQ</a>.</p>
</li>
</ul>
<h2 class="content-header header-section2" id="autoid_45">Explicit error handling in templates</h2>
<p>Although it has nothing to do with the FreeMarker
configuration (the topic of this chapter), for the sake of
completeness it is mentioned here that you can handle errors
directly in templates as well. This is usually a bad practice (try
keep templates simple and non-technical), but nonetheless necessary
sometimes:</p>
<ul>
<li>
<p>Handling missing/null variables: <a href="dgui_template_exp.html#dgui_template_exp_missing">Template Author&#39;s Guide/The Template/Expressions/Handling missing values</a></p>
</li>
<li>
<p>Surviving malfunctioning ``portlets&#39;&#39; and such expendable
page sections: <a href="ref_directive_attempt.html">Reference/Directive Reference/attempt, recover</a></p>
</li>
</ul>
<div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="pgui_config_templateloading.html"><span>Previous</span></a><a class="paging-arrow next" href="pgui_misc.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><div class="col-right"><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="2020-07-09T23:48:39Z" title="Thursday, July 9, 2020 11:48:39 PM GMT">2020-07-09 23:48:39 GMT</time> </p>
<p class="copyright">
© <span itemprop="copyrightYear">1999</span>–2020
<a itemtype="http://schema.org/Organization" itemprop="copyrightHolder" href="https://apache.org/">The Apache Software Foundation</a> </p>
</div></div></div></body>
</html>