Chapter 35. Template Engine Support

35.1. Introduction

The Spring Framework features integration classes for templating engine support. Spring 1.3 provides support for the NVelocity templating engine.

35.2. Dependencies

The Spring NVelocity support depends on the Castle project's NVelocity implementation which is located in the lib directory of the Spring release.

35.3. Configuring a VelocityEngine

The NVelocity template engine is set up using a IFactoryObject with optional configuration parameters to define where templates reside, define logging and more. For more information on IFactoryObjects see Section 5.9.3, “Customizing instantiation logic using IFactoryObjects”. A custom namespace parser is provided to simplify the configuration of a NVelocity template engine. For more information on custom namespace parser see Section 5.11.1, “Registering custom parsers”.

35.3.1. Simple file based template engine definition

You create a simple definition of the template engine that uses the default resource loader as follows:

<objects xmlns="http://www.springframework.net" xmlns:nv="http://www.springframework.net/nvelocity">

  <!-- Simple no arg file based configuration use's NVeclocity default file resource loader  -->
  <nv:engine id="velocityEngine" />

</objects>

The velocity engine could then be used to load and merge a local template using a simple relative path (the default resource loader path is the current execution directory):

StringWriter stringWriter = new StringWriter();
Hashtable modelTable = new Hashtable();
modelTable.Add("var1", TEST_VALUE);
VelocityContext velocityContext = new VelocityContext(modelTable);
velocityEngine.MergeTemplate("Template/Velocity/MyTemplate.vm", Encoding.UTF8.WebName, velocityContext, stringWriter);
string mergedContent = stringWriter.ToString();

To disable the use of NVelocity's file loader that tracks runtime changes, set the element prefer-file-system-access of <engine/> to false.

35.3.2. Configuration Options

You can define several attributes on the <engine> element to control how the factory is configured:

Table 35.1. Engine Factory Configuration Options
AttributeDescriptionRequiredDefault Value
config-file

A uri of a properties file defining the NVelocity configuration. This value accepts all spring resource loader uri (e.g., file://, http://). See Section 35.3.7, “Using a custom configuration file”

noN/A
prefer-file-system-access

Instructs the NVelocity engine factory to attempt use NVelocity's file loader. When set to false the provided SpringResourceLoader will be used (and the ResourceLoaderPath property must be set)

notrue
override-logging

Instructs the NVelocity engine factory to use the provided spring commons logging based logging system. See Section 35.3.8, “Logging”

notrue

35.3.3. Assembly based template loading

When templates are packaged in an assembly, NVelocity's assembly resource loader can be used to define where templates reside:

<nv:engine id="velocityEngine" >
    <nv:resource-loader>
        <nv:assembly name="MyAssembly" />
    </nv:resource-loader>
</nv:nvelocity>

Using the example above the template would be loaded using a namespace syntax for the template resource:

velocityEngine.MergeTemplate("MyAssembly.MyNamespace.MyTemplate.vm", Encoding.UTF8.WebName, velocityContext, stringWriter);

35.3.4. Using Spring's IResourceLoader to load templates

In some cases Spring's IResource abstraction can be beneficial to load templates from a variety of resources. A Spring IResource loader extension to the NVelocity resource loader implementation is provided for this use case. The following object definition loads the NVelocity templates from a single path

<nv:engine id="velocityEngine">
  <nv:resource-loader>
    <nv:spring uri="file://Template/Velocity/"/>
  </nv:resource-loader>
</nv:engine>

Or with multiple locations

<nv:engine id="velocityEngine">
  <nv:resource-loader>
    <nv:spring uri="file://Template/Velocity/"/>
    <nv:spring uri="assembly://MyAssembly/MyNameSpace"/>
  </nv:resource-loader>
</nv:engine>
[Note]Note

By default spring will attempt to load resources using NVelocity's file based template loading (useful for detection of template changes at runtime). If this is not desirable you set the prefer-file-system-access property of the factory object to false which will cause the factory to utilize the supplied spring resource loader.

Using the example above when resource loader paths are defined templates can be loaded using their name:

string mergedTemplate = VelocityEngineUtils.MergeTemplateIntoString(velocityEngine, "MyFileTemplate.vm", Encoding.UTF8.WebName, model); // template loaded from file://Template/Velocity/
string mergedTemplate = VelocityEngineUtils.MergeTemplateIntoString(velocityEngine, "MyAssemblyTemplate.vm", Encoding.UTF8.WebName, model); // template loaded from assembly://MyAssembly/MyNameSpace

35.3.5. Defining a custom resource loader

The following defines a custom resource loader (the type is an extension of NVelocity's ResourceLoader class):

<nv:engine id="velocityEngine">
    <nv:resource-loader>
        <nv:custom name="myResourceLoader" 
                   description="A custom resource loader" 
                   type="MyNamespace.MyResourceLoader, MyAssembly"  
                   path="Template/Velocity/"/>
    </nv:resource-loader>
</nv:engine>

35.3.6. Resource Loader configuration options

The <nv:resource-loader> element has additional attributes which define how NVelocity's resource manager and resource loader behave.

Table 35.2. Resource Loader Configuration Options
AttributeDescriptionRequiredDefault Value
default-cache-size

defines resource manager global cache size, applies when caching is turned on. This maps to NVelocity's resource manager resource.manager.defaultcache.size property

no89
template-caching

Enables template caching for the defined resource loader. This maps to NVelocity's resource loader <name>.resource.loader.cache property

nofalse
modification-check-interval

The modification check interval value (seconds) of the resource loader, applies only to resource loader with change detection capabilities (file or custom). This maps to NVelocity's resource loader <name>.resource.loader.modificationCheckInterval property

no2

35.3.7. Using a custom configuration file

If so desired one could provide a custom configuration resource to customize the NVelocity configuration:

<nv:engine id="velocityEngine" config-file="file://Template/Velocity/config.properties"/>

You can override specific properties by providing the VelocityProperties property to the NVelocity factory object (shown above)

<nv:engine id="velocityTemplate" >
  <nv:nvelocity-properties>
    <entry key="input.encoding"  value="ISO-8859-1"/>
    <entry key="output.encoding" value="ISO-8859-1"/>
  </nv:nvelocity-properties>
</nv:engine>

35.3.8. Logging

By default Spring will override NVelocity's default ILogSystem implementation with its own CommonsLoggingLogSystem implementation so that the logging stream of NVelocity will go to the same logging subsystem that Spring uses. If this is not desirable, you can specify the following property of the NVelocity factory object:

<template:nvelocity id="velocityEngine" override-logging="false" />

35.4. Merging a template

Spring provides the VelocityEngineUtils utility for merging templates using an engine instance:

string mergedTemplate = VelocityEngineUtils.MergeTemplateIntoString(velocityEngine, "MyTemplate.vm", Encoding.UTF8.WebName, model);

35.5. Configuring a VelocityEngine without a custom namespace

While most users will prefer to use the NVelocity custom namespace to configure a VelocityEngine, you can also use standard <object/> definition syntax as shown below:

To create a VelocityEngine using the default file resource loader use the definition:

<!-- Simple no arg file based configuration use's NVelocity default file resource loader  -->
<object id="velocityEngine" type="Spring.Template.Velocity.VelocityEngineFactoryObject, Spring.Template.Velocity" />

For convenience in defining NVelocity engine instances a custom namespace is provided, for example the resource loader definition could be done this way:

<objects xmlns="http://www.springframework.net" xmlns:nv="http://www.springframework.net/nvelocity">

<nv:nvelocity id="velocityEngine" >
    <nv:resource-loader>
        <nv:file path="Template/Velocity/" />
    </nv:resource-loader>
</nv:nvelocity>

</objects

When templates are packaged in an assembly, NVelocity's assembly resource loader can be used to define where templates reside:

<!-- Assembly based template loading with NVelocity assembly resource loader -->
<object id="velocityEngine" type="Spring.Template.Velocity.VelocityEngineFactoryObject, Spring.Template.Velocity">
    <property name="VelocityProperties">
        <dictionary key-type="string" value-type="object">
            <entry key="resource.loader" value="assembly"/>
            <entry key="assembly.resource.loader.class" value="NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader"/>
            <entry key="assembly.resource.loader.assembly" value="MyAssembly"/>
        </dictionary>
    </property>
</object>

To load NVelocity templates from a single path use the definition:

<object id="velocityEngine" type="Spring.Template.Velocity.VelocityEngineFactoryObject, Spring.Template.Velocity" >
    <property name="ResourceLoaderPath" value="file://MyTemplateFolder/AnotherFolder/" />
</object>

To load NVelocity templates from multiple paths use the definition:

<object id="velocityEngine" type="Spring.Template.Velocity.VelocityEngineFactoryObject, Spring.Template.Velocity" >
    <property name="ResourceLoaderPaths" >
        <list>
            <value>file://MyTemplateFolder/</value>
            <value>file://MyOtherTemplateFolder/</value>
        </list>
    </property>
</object>
[Note]Note

By default spring will attempt to load resources using NVelocity's file based template loading (useful for detection of template changes at runtime). If this is not desirable you set the preferFileSystemAccess property of the factory object to false which will cause the factory to utilize the supplied spring resource loader.

To refer to a property file based configuration of the TemplateEngine use the definition:

<object id="velocityEngine" type="Spring.Template.Velocity.VelocityEngineFactoryObject, Spring.Template.Velocity" >
    <property name="ConfigLocation " value="file://Template/Velocity/config.properties" />
</object>
[Note]Note

You can override specific properties by providing the VelocityProperties property.

To not integrate with the Common.Logging subsystem, set the OverrideLogging property to false:

<object id="velocityEngine" type="Spring.Template.Velocity.VelocityEngineFactoryObject, Spring.Template.Velocity" >
    <property name="OverrideLogging" value="false" />
</object>