Error handling

Page Contents

The possible exceptions

The exceptions that can occur regarding FreeMarker could be classified like this:

Customizing the behavior regarding TemplatException-s

TemplateException-s thrown during the template processing are handled by the freemarker.template.TemplateExceptionHandler object, which is plugged into the Configuration object with its setTemplateExceptionHandler(...) mehod. The TemplateExceptionHandler contains 1 method:

void handleTemplateException(TemplateException te, Environment env, Writer out) 
        throws TemplateException;  

Whenever a TemplateException occurs, this method will be called. The exception to handle is passed with the te argument, the runtime environment of the template processing is accessible with the env argument, and the handler can print to the output using the out argument. If the method throws exception (usually it re-throws te), then the template processing will be aborted, and Template.process(...) will throw the same exception. If handleTemplateException doesn'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.

In any case, before the TemplateExceptionHandler is invoked, FreeMarker will log the exception.

Let's see how FreeMarker skips ``statements'' when the error handler doesn't throw exception, through examples. Assume we are using this template exception handler:

class MyTemplateExceptionHandler implements TemplateExceptionHandler {
    public void handleTemplateException(TemplateException te, Environment env, java.io.Writer out)
            throws TemplateException {
        try {
            out.write("[ERROR: " + te.getMessage() + "]");
        } catch (IOException e) {
            throw new TemplateException("Failed to print error message. Cause: " + e, env);
        }
    }
}

...

cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());  

If an error occurs in an interpolation which is not inside an FTL tag (that is, not enclosed into <#...> or <@...>), then the whole interpolation will be skipped. So this template (assuming that badVar is missing from the data-model):

a${badVar}b  

will print this if we use the MyTemplateExceptionHandler:

a[ERROR: Expression badVar is undefined on line 1, column 4 in test.ftl.]b  

This template will print the same (except that the column number will differ...):

a${"moo" + badVar}b  

since, as it was written, the whole interpolation is skipped if any error occurs inside it.

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 exp in <@exp ...>, or if the value of exp is not an user-defined directive, then the whole directive call is skipped. For example this:

a<#if badVar>Foo</#if>b  

will print this:

a[ERROR: Expression badVar is undefined on line 1, column 7 in test.ftl.]b  

Note that the error occurred in the if start-tag (<#if badVar>), but the whole directive call was skipped. Logically, the nested content (Foo) was skipped with this, since the nested content is handled (printed) by the enclosing directive (if).

The output will be the same with this (except that the column number will differ...):

a<#if "foo${badVar}" == "foobar">Foo</#if>b  

since, as it was written, the whole directive calling will be skipped if any error occurs during the parameter evaluation.

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:

a
<#if true>
  Foo
  ${badVar}
  Bar
</#if>
c  

or in the macro definition body:

a
<@test />
b
<#macro test>
  Foo
  ${badVar}
  Bar
</#macro>  

the output will be something like:

a
  Foo
  [ERROR: Expression badVar is undefined on line 4, column 5 in test.ftl.]
  Bar
c  

FreeMarker comes with these prewritten error handlers:

Explicit error handling in templates

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:

FreeMarker Manual -- For FreeMarker 2.3.20
HTML generated: 2013-06-27 20:54:33 GMT
Edited with XMLMind XML Editor
Here!