Synopsis
<#attempt>
attempt block
<#recover>
recover block
</#attempt>
Where:
-
attempt block
: Template block with any content. This will be always executed, but if an error occurs during that, all output from this block is rolled back, and therecover block
will be executed. -
recover block
: Template block with any content. This will be executed only if there was an error during the execution of theattempt block
. You may print an error messages here and such.
The recover
is
mandatory. attempt
/recover
can
be nested freely into other attempt
block
s or recover
block
s.
The format shown here is supported starting from 2.3.3;
earlier it was
<#attempt>...<#recover>...</#recover>
,
which is still supported for backward compatibility. Furthermore,
these directives were introduced with FreeMarker 2.3.1, so they
aren't exist in 2.3.
Description
These directives are used if you want the page successfully
outputted even if the outputting of a certain part of the page
fails. If an error occurs during the execution of the
attempt block
, then
the output of the attempt
block
is rolled back (and the error is logged, with the default
configuration at least), and the
recover block
is
executed instead, then template execution continues normally after
the recover block
. If
no error occurs during the execution of the
attempt block
, then
the recover block
is
ignored. A simple example:
Primary content <#attempt> Optional content: ${thisMayFails} <#recover> Ops! The optional content is not available. </#attempt> Primary content continued
If the thisMayFails
variable doesn't exist
(or any other error occurs at that place), then the output
is:
Primary content Ops! The optional content is not available. Primary content continued
If the thisMayFails
variable exists and
it's value is 123
, then the output is:
Primary content Optional content: 123 Primary content continued
The attempt
block
has an all-or-none semantic: either
the entire content of the attempt
block
is output (when there was no error),
or no output at all results from the execution of the
attempt block
(when
there was an error). For example, above, the failure happens after
"Optional content: " was printed, still it is not there
in the output before the "Ops!". (This is implemented with the aggressive
buffering of the output inside the attempt
block
. Not even the flush
directive will send the output to the client.)
To prevent misunderstandings coming from the above example:
attempt
/recover
is not (only)
for handling undefined variables (for that use missing value handler
operators). It can handle all kind of errors that occurs when
the block is executed (i.e. not syntactical errors, which are
detected earlier). It meant to enclose bigger template fragments,
where error can occur at various points. For example, you have a
part in your template that deals with printing advertisements, but
that's not the primary content of the page, so you don't want your
whole page be down just because some error occurs with the printing
of the advertisements (say, because of a database server outage). So
you put the whole advertisement printing into an
attempt block
.
In some environments programmers configure FreeMarker so that
it doesn't abort template execution for certain errors, but
continues execution, possibly after printing some error indicator to
the output (see more here...). The
attempt
directive doesn't consider such
suppressed errors as errors.
Inside a recover
block
the error message of the error is
available with the error
special variable. Don't forget that
references to special variable are started with dot (for example:
${.error}
).
By default errors occurring
inside an attempt
block
are logged with
ERROR
level, despite that the template recovers
from them. This is because attempt
is not meant
to be a general purpose error handler mechanism, like
try
is in Java. It's for decreasing the impact of
unexpected errors on the visitors, by making it possible that only
part of the page is going down, instead of the whole page. But it's
still an error, something that needs the attention of the operators.
(The way this error is reported can be customized with the
attempt_exception_reporter
configuration setting,
since FreeMarker 2.3.27.)