Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id E641B200C28 for ; Mon, 13 Mar 2017 11:58:14 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id E4BE3160B85; Mon, 13 Mar 2017 10:58:14 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 9BE9A160B6C for ; Mon, 13 Mar 2017 11:58:12 +0100 (CET) Received: (qmail 33708 invoked by uid 500); 13 Mar 2017 10:58:11 -0000 Mailing-List: contact notifications-help@freemarker.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@freemarker.incubator.apache.org Delivered-To: mailing list notifications@freemarker.incubator.apache.org Received: (qmail 33698 invoked by uid 99); 13 Mar 2017 10:58:11 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 13 Mar 2017 10:58:11 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id 2B2FCC9B3D for ; Mon, 13 Mar 2017 10:58:11 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -3.569 X-Spam-Level: X-Spam-Status: No, score=-3.569 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001, SPF_NEUTRAL=0.652] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id SDvjV74fDEGi for ; Mon, 13 Mar 2017 10:58:02 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id ADBB560D3E for ; Mon, 13 Mar 2017 10:57:39 +0000 (UTC) Received: (qmail 32296 invoked by uid 99); 13 Mar 2017 10:57:38 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 13 Mar 2017 10:57:38 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B97B6E178B; Mon, 13 Mar 2017 10:57:38 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: ddekany@apache.org To: notifications@freemarker.incubator.apache.org Date: Mon, 13 Mar 2017 10:58:11 -0000 Message-Id: In-Reply-To: <7c7bb85c51cd427a82fbb5dcdcdfa7b1@git.apache.org> References: <7c7bb85c51cd427a82fbb5dcdcdfa7b1@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [35/50] incubator-freemarker-site git commit: 2.3.26-nightly docs preview archived-at: Mon, 13 Mar 2017 10:58:15 -0000 http://git-wip-us.apache.org/repos/asf/incubator-freemarker-site/blob/52c070a9/builds/2.3.26-nightly/pgui_config_errorhandling.html ---------------------------------------------------------------------- diff --git a/builds/2.3.26-nightly/pgui_config_errorhandling.html b/builds/2.3.26-nightly/pgui_config_errorhandling.html new file mode 100644 index 0000000..1d88582 --- /dev/null +++ b/builds/2.3.26-nightly/pgui_config_errorhandling.html @@ -0,0 +1,391 @@ + + + + + +Error handling - Apache FreeMarker Manual + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+
+

Error handling

+
+ + + + +

The possible exceptions

+ + +

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

+ +
    +
  • +

    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.

    +
  • + +
  • +

    Exceptions occurring when loading and parsing templates: + When you call + Configuration.getTemplate(...), + FreeMarker has to load the template into the memory and parse it + (unless the template is already cached in + that Configuration object). During this, + these kind of exceptions can occur:

    + +
      +
    • +

      TemplateNotFoundException because + the requested template doesn't exist. Note this extends + IOException.

      +
    • + +
    • +

      freemarker.core.ParseException + because the template is syntactically incorrect according + the rules of the FTL language. Note that this error occurs + when you obtain the Template object + (Configuration.getTemplate(...)), + not later when you execute + (Template.process(...)) + the template. . Note this extends + IOException (legacy).

      +
    • + +
    • +

      Any other kind of IOException + because an error has occurred while reading an existing + template. For example you have no right to read the file, or + the connection through which you read the template is + broken. The emitter of these is the TemplateLoader + object, which is plugged into the + Configuration object.

      +
    • +
    +
  • + +
  • +

    Exceptions occurring when executing (processing) + templates, that is, when you call + Template.process(...). + Two kind of exceptions can occur:

    + +
      +
    • +

      IOException because there was an + error when trying to write into the output writer.

      +
    • + +
    • +

      freemarker.template.TemplatException + because other problem occurred while executing the template. + For example, a frequent error is referring to a variable + that doesn't exist in the data-model. By default, when a + TemplatException 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 + TemplatException, which then you can + catch as + Template.process(...) + throws it. This behavior can be customized, and in fact, it + should be; see the recommended configuration here. + By default FreeMarker also logs + TemplatException-s.

      +
    • +
    +
  • +
+ + + + + +

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(...) + method. These are the TemplateExceptionHandler + implementations with FreeMarker comes with:

+ +
    +
  • +

    TemplateExceptionHandler.DEBUG_HANDLER: + Prints stack trace (includes FTL error message and FTL stack + trace) and re-throws the exception. This is the default handler, + however, you should be careful not using it in production + environment, as it shows technical information about your + system.

    +
  • + +
  • +

    TemplateExceptionHandler.HTML_DEBUG_HANDLER: + Same as DEBUG_HANDLER, but it formats the + stack trace so that it will be readable with Web browsers. + Recommended over DEBUG_HANDLER when you + generate HTML pages, but it should only be used for development + as it shows technical information about your system.

    +
  • + +
  • +

    TemplateExceptionHandler.IGNORE_HANDLER: + Simply suppresses all exceptions (though FreeMarker will still + log them if + Configuration.getLogTemplateExceptions is + true). It does nothing to handle the event. + It does not re-throw the exception.

    +
  • + +
  • +

    TemplateExceptionHandler.RETHROW_HANDLER: + Simply re-throws all exceptions; it doesn't do anything else. + This should be used in most applications today. It doesn't print + anything to the output about the error, which makes it safe, and + the developers can still get the error details from the logs. + It's not as convenient during template development as + HTML_DEBUG_HANDLER or + DEBUG_HANDLER though. For more information + about handling errors in Web applications see the FAQ.

    +
  • +
+ +

You can also write a custom + TemplateExceptionHandler by implementing that + interface, which contains this 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 in the + te argument, the runtime environment of the + template processing is in the env argument, and + the handler can print to the output using the out + argument. If this 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.

+ +

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
+ +

because 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.ftlh.]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
+ +

because 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.ftlh.]
+  Bar
+c
+ + + + + +

TemplateException logging

+ + +

By default FreeMarker logs all + TemplateException-s under the + freemarker.runtime log category, even when it + will throw it at you from its public API. As logging has become + common practice in Java applications, this usually leads to double + logging of exceptions now, so it's recommended to disable this + legacy behavior by + cfg.setLogTemplateExceptions(false) (or + log_template_exceptions=false) where you + configure FreeMarker.

+ + + + + +

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's mentioned here that you can handle errors directly + inside the templates as well:

+ + +
+
+ + http://git-wip-us.apache.org/repos/asf/incubator-freemarker-site/blob/52c070a9/builds/2.3.26-nightly/pgui_config_incompatible_improvements.html ---------------------------------------------------------------------- diff --git a/builds/2.3.26-nightly/pgui_config_incompatible_improvements.html b/builds/2.3.26-nightly/pgui_config_incompatible_improvements.html new file mode 100644 index 0000000..01c060d --- /dev/null +++ b/builds/2.3.26-nightly/pgui_config_incompatible_improvements.html @@ -0,0 +1,173 @@ + + + + + +The "incompatible improvements" setting - Apache FreeMarker Manual + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+
+

The "incompatible improvements" setting

+
+ + + + +

What does it do

+ + +

This setting specifies the FreeMarker version number where the + not 100% backward compatible bug fixes and improvements + that you want to enable were already + implemented. Usually, it's a bad idea to left it on its default, + which is 2.3.0 (maximum backward compatibility).

+ +

In new projects you should set this to the FreeMarker version + that you are actually using. In older projects it's also usually + better to keep this high, however you better check the changes + activated (find them in the + API JavaDoc of the Configuration(Version) + constructor), at least if not only the 3rd version number + (the micro version) of "incompatible improvements" + setting is increased. Generally, as far as you only increase the + last version number of this setting, the changes are low + risk.

+ +

Bug fixes and improvements that are fully backward compatible, + also those that are important security fixes, are enabled regardless + of the "incompatible improvements" setting.

+ +

An important consequence of setting this setting is that now + your application will check if the stated minimum FreeMarker version + requirement is met. Like if you set this setting to 2.3.22, but + accidentally the application is deployed with FreeMarker 2.3.21, + then FreeMarker will fail, telling that a higher version is + required. After all, the fixes/improvements you have requested + aren't available on a lower version.

+ + + + + +

How to set it

+ + +

The incompatible improvements setting exists on the + Configuration level. It can be set on multiple + ways:

+ +
    +
  • +

    Create the + freemarker.template.Configuration object + like:

    + + + +
    ... = new Configuration(Configuration.VERSION_2_3_25)
    +
  • + +
  • +

    Or, alter the Configuration singleton + where you initialize its other settings like:

    + + + +
    cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_25)
    +
  • + +
  • +

    Or, if you are configuring FreeMarker with properties + (*.properties file or + java.util.Properties object), add:

    + + + +
    incompatible_improvements=2.3.25
    +
  • + +
  • +

    Or, if you are configuring FreeMarker through + FreemarkerServlet, add this + init-param to it in the + web.xml:

    + + + +
    <init-param>
    +    <param-name>incompatible_improvements</param-name>
    +    <param-value>2.3.25</param-value>
    +</init-param>
    +
  • +
+ +

But, if you set the + object_wrapper setting (same as + Configuration.setObjectWrapper(ObjectWrapper)) of + your configuration, then it's important to know that + BeansWrapper and its subclasses (most + importantly, DefaultObjectWrapper) has its own + independent incompatibleImprovements property, + and some fixes/improvements are activated by that, not by + Configuration's similar setting. You don't have + to be aware of this complication if you aren't setting the + object_wrapper configuration setting anywhere, + because the default object_wrapper has the same + "incompatible improvements" as of the + Configuration. But if you are setting the + object_wrapper, then you must not forget to set + the incompatibleImprovements property of the + ObjectWrapper itself, in additionally to that of + the Configuration. (Note that it's fine to have + different "incompatible improvements" for the + Configuration and for the + ObjectWrapper, only it should be a conscious + decision.) See here how + to set it in the case of + DefaultObjectWrapper (for + BeansWrapper it's the same, only with different + class name of course).

+
+
+ + http://git-wip-us.apache.org/repos/asf/incubator-freemarker-site/blob/52c070a9/builds/2.3.26-nightly/pgui_config_outputformatsautoesc.html ---------------------------------------------------------------------- diff --git a/builds/2.3.26-nightly/pgui_config_outputformatsautoesc.html b/builds/2.3.26-nightly/pgui_config_outputformatsautoesc.html new file mode 100644 index 0000000..2aff9d5 --- /dev/null +++ b/builds/2.3.26-nightly/pgui_config_outputformatsautoesc.html @@ -0,0 +1,210 @@ + + + + + +Associating output formats with templates - Apache FreeMarker Manual + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+
+

Associating output formats with templates

+

The output format associated to a template decides if and what + kind of auto-escaping is used in that template (unless the template + overrides that + with directives). By default, templates have + "undefined" output format associated, which does no + escaping, and in general gives the behavior that you would expect from + a template engine that doesn't care about output formats and escaping. + However, if the recognize_standard_file_extensions + setting is + true (which is the default with the + incompatible_improvements setting set to + 2.3.24 or higher), templates whose source name ends with + ".ftlh" gets "HTML" output format, and + those with ".ftlx" get "XML" output + format. Using the ftlh and ftlx + file extensions is the recommended way of activating HTML and XML + auto-escaping. You can also associate output formats to templates + based on arbitrary name patterns with the template_configurations + setting; see some examples of that below.

There's another a related setting, called + auto_escaping_policy, which can be used to disable + auto-escaping even if the current output format supports it, or enable + auto-escaping even if the format by default doesn't escape (but it + supports it). Using this setting rarely advisable, as it's potentially + confusing for the template authors. (Instead, escaping can be turned + on/off explicitly inside the templates with the + auto_esc parameter of the ftl directive, + or with the noautoesc + and autoesc + directives.)

To check if you have configured FreeMarker properly, you can use + this template:

+ +
<p>Output format: ${.output_format}
+<p>Auto-escaping: ${.auto_esc?c}

See the table of + predefined output formats here...

Configuration examples:

    +
  • +

    To enable automatic output format associations to + *.ftlh and *.ftlx, + either:

    + +
      +
    • +

      Use incompatible_improvements 2.3.24 + or higher; see how + to set + incompatible_improvements

      +
    • + +
    • +

      Or, enable standard file extension recognizing + explicitly:

      + + + +
      // Where you initalize the Configuration singletion, add:
      +cfg.setRecognizeStandardFileExtensions(true);
      + +

      or if you configure FreeMarker with Java + *.properties file:

      + + + +
      recognizeStandardFileExtensions = true
      +
    • +
    +
  • + +
  • +

    Let's say that you want to associate all templates in the + mail directory to the HTML output format. You + could achieve that like this (assuming that you are getting the + templates with + cfg.getTemplate(...), + and not instantiating them yourself):

    + + + +
    // Where you initalize the Configuration singletion, add:
    +
    +TemplateConfiguration tcHTML = new TemplateConfiguration();
    +tcHTML.setOutputFormat(HTMLOutputFormat.INSTANCE);
    +
    +cfg.setTemplateConfigurations(
    +        new ConditionalTemplateConfigurationFactory(
    +                new PathGlobMatcher("mail/**"),
    +                tcHTML));
    + +

    or if you are configuring FreeMarker from Java + *.properties file (the \-s + are required for the Java Properties file format only):

    + + + +
    templateConfigurations = \
    +    ConditionalTemplateConfigurationFactory( \
    +        PathGlobMatcher("mail/**"), \
    +        TemplateConfiguration(outputFormat = HTMLOutputFormat()))
    +
  • + +
  • +

    Let's say you want to associate templates with + xml file extension to the XML output format, + templates with html and htm + extension to the HTML output format, and templates with + rtf extension to the RTF + output format. You could achieve that like this (assuming that you + are getting the templates with + cfg.getTemplate(...), + and not instantiating them yourself):

    + + + +
    TemplateConfiguration tcHTML = new TemplateConfiguration();
    +tcHTML.setOutputFormat(HTMLOutputFormat.INSTANCE);
    +
    +TemplateConfiguration tcXML = new TemplateConfiguration();
    +tcXML.setOutputFormat(XMLOutputFormat.INSTANCE);
    +
    +TemplateConfiguration tcRTF = new TemplateConfiguration();
    +tcRTF.setOutputFormat(RTFOutputFormat.INSTANCE);
    +
    +cfg.setTemplateConfigurations(
    +        new FirstMatchTemplateConfigurationFactory(
    +                new ConditionalTemplateConfigurationFactory(
    +                        new FileExtensionMatcher("xml"),
    +                        tcXML),
    +                new ConditionalTemplateConfigurationFactory(
    +                        new OrMatcher(
    +                                new FileExtensionMatcher("html"),
    +                                new FileExtensionMatcher("htm")),
    +                        tcHTML),
    +                new ConditionalTemplateConfigurationFactory(
    +                        new FileExtensionMatcher("rtf"),
    +                        tcRTF)
    +        ).allowNoMatch(true)
    +);
    + +

    or if you are configuring FreeMarker from Java + *.properties file (the \-s + are required for the Java Properties file format only):

    + + + +
    templateConfigurations = \
    +    FirstMatchTemplateConfigurationFactory( \
    +        ConditionalTemplateConfigurationFactory( \
    +            FileExtensionMatcher("xml"), \
    +            TemplateConfiguration(outputFormat = XMLOutputFormat())), \
    +        ConditionalTemplateConfigurationFactory( \
    +            OrMatcher( \
    +                FileExtensionMatcher("html"), \
    +                FileExtensionMatcher("htm")), \
    +            TemplateConfiguration(outputFormat = HTMLOutputFormat())), \
    +        ConditionalTemplateConfigurationFactory( \
    +            FileExtensionMatcher("rtf"), \
    +            TemplateConfiguration(outputFormat = RTFOutputFormat())), \
    +        allowNoMatch = true)
    +
  • +

(You can find some more complex + template_configurations setups here...)

+
+ + http://git-wip-us.apache.org/repos/asf/incubator-freemarker-site/blob/52c070a9/builds/2.3.26-nightly/pgui_config_settings.html ---------------------------------------------------------------------- diff --git a/builds/2.3.26-nightly/pgui_config_settings.html b/builds/2.3.26-nightly/pgui_config_settings.html new file mode 100644 index 0000000..322f062 --- /dev/null +++ b/builds/2.3.26-nightly/pgui_config_settings.html @@ -0,0 +1,378 @@ + + + + + +Settings - Apache FreeMarker Manual + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+
+

Settings

+

Settings are named values that + influence the behavior of FreeMarker. Examples of settings are: + locale, number_format, + default_encoding, + template_exception_handler. The full list of + settings can be found in the Java + API documentation of + Configuration.setSetting(...).

The settings coming from the Configuration + can be overridden in a Template instance. For + example, if you set the locale setting to + "en_US" in the configuration, then the + locale in all templates that use this configuration + will be "en_US", except in templates where the + locale was explicitly specified differently (see + localization). + Thus, the setting values in the Configuration serve + as defaults that can be overridden in a per template manner. The value + coming from the Configuration instance or + Template instance can be further overridden for a + single Template.process call. For each such call a + freemarker.core.Environment object is created + internally that holds the runtime environment of the template + processing, including the setting values that were overridden on that + level. The values stored there can even be changed during the template + processing, so a template can set settings itself, like switching + locale at the middle of the ongoing + processing.

This can be imagined as 3 layers + (Configuration, Template, + Environment) of settings, where the topmost layer + that contains the value for a certain setting provides the effective + value of that setting. For example (settings A to F are just imaginary + settings for this example):

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Setting ASetting BSetting CSetting DSetting ESetting F
Layer 3: Environment1--1--
Layer 2: Template22--2-
Layer 1: Configuration3333--
+
+

The effective value of settings will be: A = 1, B = 2, C = 3, D + = 1, E = 2. The F setting is probably null, or it + throws exception when you try to get it.

Let's see exactly how to set settings:

    +
  • +

    Configuration layer: In principle you set + the settings with the setter methods of the + Configuration object, fore example:

    + + + +
    Configuration myCfg = new Configuration(Configuration.VERSION_2_3_25);
    +myCfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
    +myCfg.setDefaultEncoding("UTF-8");
    +DefaultObjectWrapperBuilder owb = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
    +owb.setForceLegacyNonListCollections(false);
    +owb.setDefaultDateType(TemplateDateModel.DATETIME);
    +myCfg.setObjectWrapper(owb.build());
    + +

    You do this before you start to actually use the + Configuration object (typically, when you + initialize the application); you should treat the object as + read-only after that.

    + +

    In practice, in most frameworks you have to specify the + settings in some kind of framework-specific configuration file + that require specifying settings as String + name-value pairs (like in a .properties file). + In that case the authors of the frameworks most probably use the + Confguration.setSetting(String name, String + value) method; see available setting names and the + format of the values in the API + documentation of setSetting. Example for + Spring Framework:

    + + + +
    <bean id="freemarkerConfig"
    +    class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
    +  <property name="freemarkerSettings">
    +    <props>
    +      <prop key="incompatible_improvements">2.3.25</prop>
    +      <prop key="template_exception_handler">rethrow</prop>
    +      <prop key="default_encoding">UTF-8</prop>
    +      <prop key="object_wrapper">
    +        DefaultObjectWrapper(
    +                2.3.25,
    +                forceLegacyNonListCollections = false,
    +                defaultDateType = freemarker.template.TemplateDateModel.DATETIME)
    +      </prop>
    +    </props>
    +  </property>
    +</bean>
    + +

    Here's the same when configuring FreeMarker for Struts, + which looks for a freemarker.properties in the + classpath:

    + + + +
    incompatible_improvements=2.3.25
    +template_exception_handler=rethrow
    +default_encoding=UTF-8
    +object_wrapper=DefaultObjectWrapper( \
    +        2.3.25, \
    +        forceLegacyNonListCollections = false, \
    +        defaultDateType = freemarker.template.TemplateDateModel.DATETIME)
    + +

    As demonstrated above with + object_wrapper, some settings can accept quite + complex values, which can be used to instantiate objects of + arbitrary classes and set their properties. Still, configuring + with String key-value pairs is limited compared + to directly using the Java API, so in some cases you have to find + a way to do this in Java.

    +
  • + +
  • +

    Template layer: Settings on individual + templates are normally set by template + configurations (see them in their own chapter), which + basically associate setting assignments to template name (template + path) patterns. There's a deviation from this approach with the + locale setting, because that you can also + specify to Configuration.getTemplate(...) as + parameter, to get the template for the requested locale (so called + localized lookup).

    + +
    + Warning! + +

    You should never set settings directly on the + Template object that you get from + Configuration.getTemplate(...)! Those objects + should be treated as already initialized and read-only.

    +
    + + +

    When a template includes or imports another template, most + of the settings (like locale, + number_format, etc.) will remain those + specified by the top-level template. The exceptions are the + settings that affect the parsing of the template (like + tag_syntax, + whitespace_stripping, etc.), as these are not + inherited from the top-level template, instead each template + always uses its own values, no mater how it was invoked.

    + +
    + Note: + +

    If you are going to use template layer settings, you + should set the + incompatible_improvements setting to + 2.3.22 or higher, to avoid some confusing legacy bugs.

    +
    + +
  • + +
  • +

    Environment layer: There are two ways of + doing it:

    + +
      +
    • +

      With Java API: Use the setter methods of the + Environment object. You may run into the + API problem that myTemplate.process(...) + both creates the Environment object + internally and processes the template, so you have no + opportunity to adjust the Environment in + between. The solution is that those two steps can be separated + like this:

      + + + +
      Environment env = myTemplate.createProcessingEnvironment(root, out);
      +env.setLocale(java.util.Locale.ITALY);
      +env.setNumberFormat("0.####");
      +env.process();  // process the template
      +
    • + +
    • +

      Directly in the Template (considered as bad style, + usually): Use the setting + directive, for example:

      + + + +
      <#setting locale="it_IT">
      +<#setting number_format="0.####">
      +
    • +
    + +

    There are no restriction regarding when can you change the + settings in this layer.

    +
  • +

To see the list of supported settings and their meaning, please + read the following parts of the FreeMarker Java API + documentation:

    +
  • +

    Setter methods of + freemarker.core.Configurable for the settings + that are in all three layers

    +
  • + +
  • +

    Setter methods of + freemarker.template.Configuration for the + settings that are available only in the + Configuration layer

    +
  • + +
  • +

    freemarker.core.Configurable.setSetting(String, + String) for settings that are available in all three + layers and are writable with String key-value + pairs.

    +
  • + +
  • +

    freemarker.template.Configuration.setSetting(String, + String) for settings that are available only in the + Configuration layer and are writable with + String key-value pairs.

    +
  • +
+
+ +