The new Certification Class of REST With Spring is out:

>> CHECK OUT THE COURSE

1. Overview

Velocity is a Java-based templating engine.

It’s an open source web framework designed to be used as a view component in the MVC architecture, and it provides an alternative to some existing technologies such as JSP.

Velocity can be used to generate XML files, SQL, PostScript and most other text-based formats.

In this article, we will explore how it can be used to create dynamic web pages.

2. How Velocity Works

The core class of Velocity is the VelocityEngine.

It orchestrates the whole process of reading, parsing and generating content using data model and velocity template.

Simply put, here are the steps we need to follow for any typical velocity application:

  • Initialize the velocity engine
  • Read the template
  • Put the data model in context object
  • Merge the template with context data and render the view

Let’s go through an example following these simple steps:

VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.init();
   
Template t = velocityEngine.getTemplate("index.vm");
    
VelocityContext context = new VelocityContext();
context.put("name", "World");
    
StringWriter writer = new StringWriter();
t.merge( context, writer );

3. Maven Dependencies

To work with Velocity, we need to add following dependencies to our Maven project:

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity</artifactId>
    <version>1.7</version>
    </dependency>
<dependency>
     <groupId>org.apache.velocity</groupId>
     <artifactId>velocity-tools</artifactId>
     <version>2.0</version>
</dependency>

The latest version of both these dependencies can be here: velocity and velocity-tools.

4. Velocity Template Language

Velocity Template Language (VTL) provides the simplest and cleanest way of incorporating the dynamic content in a web page by using VTL references.

VTL reference in velocity template starts with a and is used for getting the value associated with that reference. VTL provides also a set of directives which can be used for manipulating the output of the Java code. Those directives start with #. 

4.1. References

There are three types of references in Velocity, variables, properties and methods:

  • variables – defined within the page using #set directive or value returned from Java object’s field:
    #set ($message="Hello World")
  • properties – refer to fields within an object; they can also refer to a getter method of the property:
    $customer.name
  • methods – refer to the method on Java object:
    $customer.getName()

The final value resulting from every reference is converted to a string when it is rendered into the final output.

4.2. Directives

VTL provides a rich set of directives:

  • set – it can be used for setting the value of a reference; this value can be assigned to a variable or a property reference:
    #set ($message = "Hello World")
    #set ($customer.name = "Brian Mcdonald")
  • conditionals – #if, #elseif and #else directives provide a way to generate the content based on conditional checks:
    #if($employee.designation == "Manager")
        <h3> Manager </h3>
    #elseif($employee.designation == "Senior Developer")
        <h3> Senior Software Engineer </h3>
    #else
        <h3> Trainee </h3>
    #end
  • loops – #foreach directive allows looping over a collection of objects:
    <ul>
        #foreach($product in $productList)
            <li> $product </li>
        #end
    </ul>
  • include – #include element provides the ability to import files into the template:
    #include("one.gif","two.txt","three.html"...)
  • parse – #parse statement allows the template designer to import another local file which contains VTL; Velocity will then parse the content and render it:
    #parse (Template)
  • evaluate – #evaluate directive can be used to evaluate VTL dynamically; this allows the template to evaluate a String at render time, for example to internationalise the template:
    #set($firstName = "David")
    #set($lastName = "Johnson")
    
    #set($dynamicsource = "$firstName$lastName")
    
    #evaluate($dynamicsource)
  • break – #break directive stops any further rendering of current execution scope (i.e. #foreach#parse)
  • stop –  #stop directive stops any further rendering and execution of the template.
  • velocimacros – #macro directive allows the template designer to define a repeated segment of VTL:
    #macro(tablerows)
        <tr>
            <td>
            </td>
        </tr>
    #end

    This macro now can be put in any place in the template as #tablerows():

    #macro(tablerows $color $productList)
        #foreach($product in $productList)
            <tr>
                <td bgcolor=$color>$product.name</td>
            </tr>
        #end
    #end

4.3. Other Features

  • math – a handful built-in mathematical functions, which can be used in templates:
    #set($percent = $number / 100)
    #set($remainder = $dividend % $divisor)
  • range operator – that can be used in conjunction with #set and #foreach:
    #set($array = [0..10])
    
    #foreach($elem in $arr)
        $elem
    #end

5. Velocity Servlet

The primary job of the Velocity Engine is to generate content based on a template.

The Engine doesn’t contain any web related functionalities in itself. To implement a web application, we need to use a servlet or servlet-based framework.

Velocity provides one out of the box implementation VelocityViewServlet, which is a part of the velocity-tools subproject.

To make use of the built-in functionality provided by VelocityViewServlet, we can extend our servlet from VelocityViewServlet and override the handleRequest() method:

public class ProductServlet extends VelocityViewServlet {

    ProductService service = new ProductService();

    @Override
    public Template handleRequest(
      HttpServletRequest request, 
      HttpServletResponse response,
      Context context) throws Exception {
      
        List<Product> products = service.getProducts();
        context.put("products", products);

        return getTemplate("index.vm");
    }
}

6. Configuration

6.1. Web Configuration

Let’s now see how to configure the VelocityViewServlet in the web.xml.

We need to specify the optional initialization parameters which include velocity.properties and toolbox.xml:

<web-app>
    <display-name>apache-velocity</display-name>
      //...
       
    <servlet>
        <servlet-name>velocity</servlet-name>
        <servlet-class>org.apache.velocity.tools.view.VelocityViewServlet</servlet-class>

        <init-param>
            <param-name>org.apache.velocity.properties</param-name>
            <param-value>/WEB-INF/velocity.properties</param-value>
        </init-param>
    </servlet>
        //...
</web-app>

We also need to specify the mapping for this servlet. All the requests for velocity templates (*.vm) need to be served by the velocity servlet:

<servlet-mapping>
    <servlet-name>velocityLayout</servlet-name>
    <url-pattern>*.vm</url-pattern>
</servlet-mapping>

6.2. Resource Loader

Velocity provides flexible resource loader system. It allows one or more resource loader to be in operation at the same time:

  • FileResourceLoader
  • JarResourceLoader
  • ClassPathResourceLoader
  • URLResourceLoader
  • DataSourceResourceLoader
  • WebappResourceLoader

These resource loaders are configured in velocity.properties:

resource.loader=webapp
webapp.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader
webapp.resource.loader.path = .
webapp.resource.loader.cache = true

7. Velocity Template

Velocity template is the place where all the view generation logic is written. These pages are written using Velocity Template Language (VTL):

<html>
    ...
    <body>
        <center>
        ...
        <h2>$products.size() Products on Sale!</h2>
        <br/>
            We are proud to offer these fine products
            at these amazing prices.
        ...
        #set( $count = 1 )
        <table class="gridtable">
            <tr>
                <th>Serial #</th>
                <th>Product Name</th>
                <th>Price</th>
            </tr>
            #foreach( $product in $products )
            <tr>
                <td>$count)</td>
                <td>$product.getName()</td>
                <td>$product.getPrice()</td>
            </tr>
            #set( $count = $count + 1 )
            #end
        </table>
        <br/>
        </center>
    </body>
</html>

8. Managing the Page Layout

Velocity provides a simple layout control and customizable error screens for Velocity Tool based application.

VelocityLayoutServlet encapsulates this capability to render the specified layouts. VelocityLayoutServlet is an extension to VelocityViewServlet. 

8.1. Web Configuration

Let’s see how to configure the VelocityLayoutServlet. The servlet is defined for intercepting the requests for velocity template pages and the layout specific properties are defined in velocity.properties file:

<web-app>
    ...
    <servlet>
        <servlet-name>velocityLayout</servlet-name>
        <servlet-class>org.apache.velocity.tools.view.VelocityLayoutServlet</servlet-class>

        <init-param>
            <param-name>org.apache.velocity.properties</param-name>
            <param-value>/WEB-INF/velocity.properties</param-value>
        </init-param>
    </servlet>
    ....
    <servlet-mapping>
        <servlet-name>velocityLayout</servlet-name>
        <url-pattern>*.vm</url-pattern>
    </servlet-mapping>
    ...
</web-app>

8.2. Layout Templates

Layout template defines the typical structure of a velocity page. By default, the VelocityLayoutServlet searches for Default.vm under the layout folder. Overriding few properties can change this location:

tools.view.servlet.layout.directory = layout/
tools.view.servlet.layout.default.template = Default.vm

The layout file consists of header template, footer template, and a velocity variable $screen_content which renders the contents of requested velocity page:

<html>
    <head>
        <title>Velocity</title>
    </head>
    <body>
        <div>
            #parse("/fragments/header.vm")
        </div>
        <div>
            <!-- View index.vm is inserted here -->
            $screen_content
        </div>
        <div>
            #parse("/fragments/footer.vm")
        </div>
    </body>
</html>

8.3. Layout Specification in the Requested Screen

Layout for a particular screen can be defined as a velocity variable at the beginning of a page. That is done by putting this line in the page:

#set($layout = "MyOtherLayout.vm")

8.4. Layout Specification in the Request Parameter

We can add a request parameter in the query string layout=MyOtherLayout.vm and VLS will find it and render the screen within that layout instead of searching for default layout.

8.5. Error Screens

Customized error screen can be implemented using velocity layout. VelocityLayoutServlet provides two variables $error_cause and $stack_trace to present the exception details.

Error page can be configured in velocity.properties file:

tools.view.servlet.error.template = Error.vm

9. Conclusion

In this article, we have learned how Velocity is a useful tool for rendering the dynamic web pages. Also, we have seen different ways of using velocity provided servlets.

We also have an article focused on a Velocity configuration with Spring MVC here at Baeldung.

The complete code for this tutorial is available over on GitHub.

Go deeper into building a REST API with Spring:

>> CHECK OUT THE COURSE