Template configurations

"Template configurations" refers to the template_configurations setting of Configuration (Configuration.setTemplateConfigurations(...)). This setting lets you override individual settings coming from the common Configuration object, depending on the name (path) of the template.

It's important to understand, however, that this setting only has effect if you get templates with Configuration.getTemplate(...), not when you create templates directly with the Template constructors. In that case it's up to you to invoke this mechanism (see TemplateCache source code as an example).

You will use these kind of objects to declare your template configuration rules:

  • TemplateConfiguration-s: These store the actual setting assignments that you want to apply. For example, this TemplateConfiguration will set the encoding and the output format of the matched template (and leave all other settings of it alone):

    TemplateConfiguration tcUTF8XML = new TemplateConfiguration();
    tc.setEncoding("utf-8");
    tc.setOutputFormat(XMLOutputFormat.INSTANCE);
  • TemplateSourceMatcher (abstract) subclasses: These define a rule that matches templates based on their source name (their source path; as in Template.getSourceName()), and possibly on other TemplateLoader-dependent properties. For example, new FileExtensionMatcher("xml") matches templates that has xml file extension. See all the subclasses in the Java API documentation.

  • TemplateConfigurationFactory-es: This is what connects TemplateConfiguration-s and TemplateSourceMatcher-s together. This is the Java type of the template_configurations setting. See the examples below for more.

Example 1

This setup combines our earlier two example objects with a ConditionalTemplateConfigurationFactory, causing all templates with xml extension to get UTF-8 encoding and XML output format:

cfg.setTemplateConfigurations(
        new ConditionalTemplateConfigurationFactory(
                new FileExtensionMatcher("xml"),
                tcUTF8XML));

The same configuring is also doable if you don't have access to the configuring Java code, but only to a Java *.properties file or other kind of string-string key value pairs (the \-s are prescribed by the Java Properties file format for multi-line values):

templateConfigurations = \
    ConditionalTemplateConfigurationFactory( \
        FileExtensionMatcher("xml"), \
        TemplateConfiguration( \
            encoding = "utf-8", \
            outputFormat = XMLOutputFormat() \
        ) \
    )

Example 2

Let's say you only need to handle templates in the mail directory specially, other templates can use the setting coming from the shared Configuration singleton. The names of templates there must contain ".subject." or ".body.". Subject templates must get plainText output format, while body templates must get HTML output format. So we have to make a choice here, and that's when you need a FirstMatchTemplateConfigurationFactory.

Assuming cfg stores the shared Configuration singleton, you set this up like this:

cfg.setTemplateConfigurations(
        new ConditionalTemplateConfigurationFactory(
                new PathGlobMatcher("mail/**"),
                new FirstMatchTemplateConfigurationFactory(
                        new ConditionalTemplateConfigurationFactory(
                                new FileNameGlobMatcher("*.subject.*"),
                                tcSubject),
                        new ConditionalTemplateConfigurationFactory(
                                new FileNameGlobMatcher("*.body.*"),
                                tcBody)
                        )
                        .noMatchErrorDetails(
                                "Mail template names must contain \".subject.\" or \".body.\"!")
                ));

The equivalent configuration using a Java *.properties file or other kind of string-string key value pairs (the \-s are prescribed by the Java Properties file format only):

templateConfigurations = \
    ConditionalTemplateConfigurationFactory( \
        PathGlobMatcher("mail/**"), \
        FirstMatchTemplateConfigurationFactory( \
            ConditionalTemplateConfigurationFactory( \
                FileNameGlobMatcher("*.subject.*"), \
                TemplateConfiguration(outputFormat = PlainTextOutputFormat()) \
            ), \
            ConditionalTemplateConfigurationFactory( \
                FileNameGlobMatcher("*.body.*"), \
                TemplateConfiguration(outputFormat = HTMLOutputFormat()) \
            ), \
            noMatchErrorDetails = 'Mail template names must contain ".subject." or ".body."!' \
        ) \
    )

Example 3

Let's say you want the following deviations from the shared Configuration settings in your application:

  • All templates whose name contains ".stats." should use ISO date/time format and UTC time zone

  • All templates inside the mail directory should use UTF-8 encoding

  • Templates with xml file extension should use XML output_format, templates with html or htm extension should use HTML output format. For other templates, the shared Configuration can dictate the output_format.

Here we have 3 independent concerns, and possibly multiple (or none) of those apply to a template; that's when you need a MergingTemplateConfigurationFactory. The last point describes a rule where you have mutually exclusive choices; that's when you need a FirstMatchTemplateConfigurationFactory, but this time no choice is also allowed. Here's the source code, assuming cfg stores the shared Configuration instance:

TemplateConfiguration tcStats = new TemplateConfiguration();
tcStats.setDateTimeFormat("iso");
tcStats.setDateFormat("iso");
tcStats.setTimeFormat("iso");
tcStats.setTimeZone(DateUtil.UTC);

TemplateConfiguration tcMail = new TemplateConfiguration();
tcMail.setEncoding("utf-8");

TemplateConfiguration tcHTML = new TemplateConfiguration();
tcHTML.setOutputFormat(HTMLOutputFormat.INSTANCE);

TemplateConfiguration tcXML = new TemplateConfiguration();
tcXML.setOutputFormat(XMLOutputFormat.INSTANCE);

cfg.setTemplateConfigurations(
        new MergingTemplateConfigurationFactory(
                new ConditionalTemplateConfigurationFactory(
                        new FileNameGlobMatcher("*.stats.*"),
                        tcStats),
                new ConditionalTemplateConfigurationFactory(
                        new PathGlobMatcher("mail/**"),
                        tcMail),
                new FirstMatchTemplateConfigurationFactory(
                        new ConditionalTemplateConfigurationFactory(
                                new FileExtensionMatcher("xml"),
                                tcXML),
                        new ConditionalTemplateConfigurationFactory(
                                new OrMatcher(
                                        new FileExtensionMatcher("html"),
                                        new FileExtensionMatcher("htm")),
                                tcHTML)
                ).allowNoMatch(true)
        )
);

The equivalent configuration using a Java *.properties file or other kind of string-string key value pairs (the \-s are prescribed by the Java Properties file format only):

templateConfigurations = \
    MergingTemplateConfigurationFactory( \
        ConditionalTemplateConfigurationFactory( \
            FileNameGlobMatcher("*.stats.*"), \
            TemplateConfiguration( \
                dateTimeFormat = "iso", \
                dateFormat = "iso", \
                timeFormat = "iso", \
                timeZone = TimeZone("UTC") \
            ) \
        ), \
        ConditionalTemplateConfigurationFactory( \
            PathGlobMatcher("mail/**"), \
            TemplateConfiguration(encoding = "utf-8") \
        ), \
        FirstMatchTemplateConfigurationFactory( \
            ConditionalTemplateConfigurationFactory( \
                FileExtensionMatcher("xml"), \
                TemplateConfiguration(outputFormat = XMLOutputFormat()) \
            ), \
            ConditionalTemplateConfigurationFactory( \
                OrMatcher( \
                    FileExtensionMatcher("html"), \
                    FileExtensionMatcher("htm") \
                ), \
                TemplateConfiguration(outputFormat = HTMLOutputFormat()) \
            ), \
            allowNoMatch = true \
        ) \
    )