Velocity Engine

Intro

The Velocity Engine is robust template engine for java.
It has a good documentation for the template-syntax (User Guide) and how do integratate (Developer’s Guide ) the engine in your application.
What I missed is a very short Quick-Starter-Guide to integrate the engine into your application.

Dependency

For a quick start you will need the velocity library itself in you maven pom.xml:

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.3</version>
</dependency>

Quick Start

The smalest java code to get velocity to work is using Velocity.evaluate(…) method:

VelocityContext context = new VelocityContext();
context.put("name", "Velocity");

StringWriter sw = new StringWriter();
Velocity.evaluate(context, sw, "on-the-fly-template", new StringReader("Hi, ${name}... this is some on-the-fly template!"));
System.out.println("Result: " + sw.toString()); // prints: Hi, Velocity... this is some on-the-fly template!

With that there are two Problems:

  • Static Singleton of Velocity (should realy not be used in shared libraries to prevent conflicts).
  • If the template is used multiple times, the Velocity.evaluate(…) will parse (costly) the template every time.

Use non-singleton Velocity RuntimeInstance

Instead of the ‘org.apache.velocity.app.Velocity’-Singleton you can create your own instance with ‘org.apache.velocity.runtime.RuntimeInstance’.

RuntimeInstance velicityRuntime = new RuntimeInstance();

VelocityContext context = new VelocityContext();
context.put("name", "Velocity");

StringWriter sw = new StringWriter();
velicityRuntime.evaluate(context, sw, "on-the-fly-template", new StringReader("Hi, ${name}... this is some on-the-fly template!"));
System.out.println("Result: " + sw.toString()); // prints: Hi, Velocity... this is some on-the-fly template!

Re-Use templates

To prevent the costly parsing of the Template on each evaluation, you should use the Velocity.template(…) method and then call template.merge(…).
For that you need to configure your template-Repository and Loader. There are mutlipe implementation evailable (see package ‘org.apache.velocity.runtime.resource.loader’ ).
I found the StringResourceLoader the simplest and most flexible one.

RuntimeInstance velicityRuntime = new RuntimeInstance();
// configure StringResourceLoader:
UUID stringRepoName = UUID.randomUUID(); // unique name is needed for the RuntimeInstance instead of the Singleton Velocity instance.
Properties props = new Properties();
props.setProperty("resource.loaders", "string");
props.setProperty("resource.loader.string.repository.name", stringRepoName.toString()); // each RuntimeInstance should have his own unique name
props.setProperty("resource.loader.string.class", StringResourceLoader.class.getName());

velicityRuntime.init(props);

// put your template into the StringResourceRepository:
StringResourceRepository repo = StringResourceLoader.getRepository(stringRepoName.toString());
repo.putStringResource("mytemplate.vm", "Hi, ${name}... this is some template!");

VelocityContext context = new VelocityContext();
context.put("name", "Velocity");

// get parsed template (no Velocity can cache the template)
Template template = velicityRuntime.getTemplate("mytemplate.vm");

// use template.merge(...) instead of Velocity.evaluate(...)
StringWriter sw = new StringWriter();
template.merge(context, sw);
System.out.println("Result: " + sw.toString()); // print: Hi, Velocity... this is some template!