Apache Velocity - 1.0

Extension Id

com.castsoftware.java.velocity

What’s new?

Please see Apache Velocity - 1.0 - Release Notes for more information.

Description

This extension provides support for Apache Velocity Framework. Apache Velocity is a Java-based templating engine, used to create dynamic web pages by parsing data model to template.

In what situation should you install this extension?

If your Java application uses the Apache Velocity Framework.

Technology support

Component Version Supported Supported Technology
velocity-engine-core 2.x ✔️ JAVA
velocity-tools-view 3.x ✔️ JAVA
spring-velocity-support 2.x ✔️ JAVA
spring-context-support <= 4.3.x ✔️ JAVA
spring-webmvc <= 4.3.x ✔️ JAVA
spring-context <= 4.3.x ✔️ JAVA

AIP Core compatibility

This extension is compatible with:

AIP Core release Supported
8.3.x ✔️

Download and installation instructions

The extension will not be automatically downloaded and installed in CAST Console. If you need to use it, you should manually install the extension using the Application - Extensions interface.

What results can you expect?

Objects

Icon Description
Java Velocity VTL Parameter
Java Velocity Call To VTLContext
Link Type Source and destination of link Supported Velocity Engine Core Methods
relyonLink Between Java Velocity VTL Parameter and respective Context JAVA class.
Velocity Engineorg.apache.velocity.app.Velocity.mergeTemplate
org.apache.velocity.app.VelocityEngine.mergeTemplate
org.apache.velocity.Template.merge

Velocity Toolsorg.apache.velocity.tools.view.VelocityViewServlet.mergeTemplate
org.apache.velocity.tools.view.VelocityLayoutServlet.mergeTemplate
org.apache.velocity.tools.view.VelocityView.merge

Velocity Springorg.springframework.ui.velocity.VelocityEngineUtils.mergeTemplateIntoString
org.springframework.ui.velocity.VelocityEngineUtils.mergeTemplate
org.apache.velocity.spring.VelocityEngineUtils.mergeTemplateIntoString
org.apache.velocity.spring.VelocityEngineUtils.mergeTemplate
org.springframework.web.servlet.view.velocity.VelocityView.mergeTemplate
relyonLink Between Java Velocity VTL Parameter and respective Context JAVA class. org.apache.velocity.tools.view.VelocityViewServlet.getTemplate
org.apache.velocity.app.Velocity.getTemplate
org.apache.velocity.app.VelocityEngine.getTemplate
org.apache.velocity.tools.view.VelocityView.getTemplate
org.apache.velocity.context.Context.put
org.apache.velocity.VelocityContext.put
org.apache.velocity.context.AbstractContext.put

NOTE: Java Velocity VTL Parameter object is created, only if the above APIs are called from overridden handleRequest method of VelocityViewServlet/VelocityLayoutServlet derived class.
relyonLink Between Java Velocity VTL Parameter and respective Context JAVA class.
Model Attributeorg.springframework.ui.Model.addAttribute
org.springframework.ui.ModelMap.addAttribute

Velocity Configurationorg.apache.velocity.spring.VelocityEngineFactory.VelocityEngineFactory
org.apache.velocity.spring.VelocityEngineFactory.setResourceLoaderPath
org.apache.velocity.spring.VelocityEngineFactory.setResourceLoader
org.apache.velocity.spring.VelocityEngineFactoryBean.VelocityEngineFactoryBean
org.springframework.ui.velocity.VelocityEngineFactory.VelocityEngineFactory
org.springframework.ui.velocity.VelocityEngineFactory.setResourceLoaderPath
org.springframework.ui.velocity.VelocityEngineFactory.setResourceLoader
org.springframework.ui.velocity.VelocityEngineFactoryBean.VelocityEngineFactoryBean
org.springframework.web.servlet.view.velocity.VelocityConfigurer.VelocityConfigurer
org.springframework.web.servlet.view.velocity.VelocityConfigurer.setVelocityEngine
org.springframework.web.servlet.view.velocity.VelocityView.setVelocityEngine

Velocity View and Resolverorg.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver.VelocityLayoutViewResolver
org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver.setLayoutUrl
org.springframework.web.servlet.view.velocity.VelocityViewResolver.VelocityViewResolver
org.springframework.web.servlet.view.velocity.VelocityViewResolver.setToolboxConfigLocation
org.springframework.web.servlet.view.velocity.VelocityToolboxView.VelocityToolboxView
org.springframework.web.servlet.view.velocity.VelocityToolboxView.setToolboxConfigLocation

NOTE: Java Velocity VTL Parameter object will be created, if the Model Attribute APIs are called from Spring Controller methods which returns template name string and Velocity Config is defined using above mentioned Velocity Configuration, View and Resolver APIs, either using Java Config or XML Config Methods
callLink Between HTML source code objects and Java Velocity Call To VTLContext objects.
callLink Between Java Velocity Call To VTLContext objects and JAVA methods.

Code Examples

Velocity Engine Core

Velocity Engine code - Test6.java
package test.velocity;

import org.apache.velocity.app.Velocity;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.context.Context;

import java.io.Writer;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;

import bean.Product;

class Test6 {

    public Test6() throws Exception {

        Velocity.init("src/main/java/velocity.properties");

        Context context = new VelocityContext();

        final Collection<Product> products = new ArrayList<>();
        //context.put("test", "test");

        products.add(new Product("Widget", 12.99));
        products.add(new Product("Wotsit", 13.99));
        products.add(new Product("Thingy", 11.99));

        context.put("products", products);

        Template template2 = Velocity.getTemplate("Test7.vm");

        Writer writer2 = new StringWriter();
        template2.merge(context, writer2);
        System.out.println(writer2.toString());
    }
}
Context Class - product.java
package bean;

public class Product {

    private String name;
    private double price;

    public Product(String aName, double aPrice) {
        name = aName;
        price = aPrice;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public void setName(String val) {
        name = val;
    }

    public void setPrice(double val) {
        price = val;
    }

    public String getNameAndPrice() {
        return "Name: " + getName() + " Price: " + getPrice();
    }
}
Velocity Template - Test7.vm
#macro (writeTable $productList)
    #set ($rowCount = 1)
    #foreach($product in $productList)
    #if ($rowCount % 2 == 0)
        #set ($bgcolor = "#FFFFFF")
    #else
        #set ($bgcolor = "#CCCCCC")
    #end
        <tr>
            <td bgcolor="$bgcolor">$product.name</td>
            <td bgcolor="$bgcolor">$product.price</td>
        </tr>
        #set ($rowCount = $rowCount + 1)
    #end
#end


<html>
    <head>
        <title>Macros Test</title>
    </head>
    <body>
        <table>
            #writeTable($products)
        </table>
    </body>
</html>

Velocity Tools View

VelocityViewServlet - ProductServlet.java
package com.test.apache.velocity.servlet;

import com.test.apache.velocity.model.Product;
import com.test.apache.velocity.service.ProductService;
import org.apache.velocity.Template;
import org.apache.velocity.context.Context;
import org.apache.velocity.tools.view.VelocityViewServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

public class ProductServlet extends VelocityViewServlet {

    ProductService service = new ProductService();

    @Override
    public Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) {

        Logger logger= LoggerFactory.getLogger(ProductServlet.class);

        List<Product> products = service.getProducts();

        context.put("products", products);

        Template template = null;

        try {
            template = getTemplate("templates/index.vm");
            response.setHeader("Template Returned", "Success");
        } catch (Exception e) {
            logger.error("Error while reading the template ", e);
        }

        return template;

    }
}
Context Class - Product.java
package com.test.apache.velocity.model;

public class Product {

    private String name;
    private double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Product{" + "name='" + name + '\'' + ", price=" + price + '}';
    }
}
Velocity Template - index.vm
<HTML>
<HEAD>
    <TITLE>Online Electronic Store</TITLE>
    <style>
        body {background-color: powderblue;}
        h1   {color: blue;}
        p    {color: red;}
        table.gridtable {
            font-family: verdana,arial,sans-serif;
            font-size:11px;
            color:#333333;
            border-width: 1px;
            border-color: #666666;
            border-collapse: collapse;
        }
        table.gridtable th {
            border-width: 1px;
            padding: 8px;
            border-style: solid;
            border-color: #666666;
            background-color: #dedede;
        }
        table.gridtable td {
            border-width: 1px;
            padding: 8px;
            border-style: solid;
            border-color: #666666;
            background-color: #ffffff;
        }

    </style>

</HEAD>
<BODY>
<CENTER>
    <h1>Today's Offers</h1>
    <BR/>
    <BR/>
    <h2>$products.size() Products on Sale!</h2>
    <BR/>
    We are proud to offer these fine products
    at these amazing prices.
    <BR/>
    <BR/>
    #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>

Velocity Spring

Velocity Java Config - WebConfig.java
package com.baeldung.mvc.velocity.spring.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
import org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.baeldung.mvc.velocity.controller", "com.baeldung.mvc.velocity.service" })
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public ViewResolver viewResolver() {
        final VelocityLayoutViewResolver bean = new VelocityLayoutViewResolver();
        bean.setCache(true);
        bean.setPrefix("/WEB-INF/views/");
        bean.setLayoutUrl("/WEB-INF/layouts/layout.vm");
        bean.setSuffix(".vm");
        return bean;
    }

    @Bean
    public VelocityConfigurer velocityConfig() {
        VelocityConfigurer velocityConfigurer = new VelocityConfigurer();
        velocityConfigurer.setResourceLoaderPath("/");
        return velocityConfigurer;
    }
}
Velocity XML Config - mvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-4.1.xsd">


    <!-- Register the annotated components in the container eg : annotated controllers -->
    <context:component-scan base-package="com.baeldung.mvc.velocity.*"/>

    <!-- Tell the container that we are going to use annotations -->
    <context:annotation-config/>


    <bean id="velocityConfig"
          class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        <property name="resourceLoaderPath">
            <value>/</value>
        </property>
    </bean>


    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver">
        <property name="cache" value="true"/>
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="layoutUrl" value="/WEB-INF/layouts/layout.vm"/>
        <property name="suffix" value=".vm"/>
    </bean>

</beans>
Context Class - Tutorial.java
package com.baeldung.mvc.velocity.domain;

public class Tutorial {

    private final Integer tutId;
    private final String title;
    private final String description;
    private final String author;

    public Tutorial(Integer tutId, String title, String description, String author) {
        this.tutId = tutId;
        this.title = title;
        this.description = description;
        this.author = author;
    }

    public Integer getTutId() {
        return tutId;
    }

    public String getTitle() {
        return title;
    }

    public String getDescription() {
        return description;
    }

    public String getAuthor() {
        return author;
    }

}
Spring Controller Class - MainController.java
package com.baeldung.mvc.velocity.controller;

import com.baeldung.mvc.velocity.domain.Tutorial;
import com.baeldung.mvc.velocity.service.ITutorialsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.List;

@Controller
@RequestMapping("/")
public class MainController {

    @Autowired
    private ITutorialsService tutService;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String welcomePage() {
        return "index";
    }

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public String listTutorialsPage(Model model) {
        List<Tutorial> list = tutService.listTutorials();
        model.addAttribute("tutorials", list);
        return "list";
    }

    public ITutorialsService getTutService() {
        return tutService;
    }

    public void setTutService(ITutorialsService tutService) {
        this.tutService = tutService;
    }

}
Velocity Template - list.vm
<h1>Index</h1>
 
<h2>Tutorials list</h2>
<table border="1">
<tr>
 <th>Tutorial Id</th>
 <th>Tutorial Title</th>
 <th>Tutorial Description</th>
 <th>Tutorial Author</th>
</tr>
#foreach($tut in $tutorials)
  <tr>
   <td id="tutId_$foreach.count">$tut.tutId</td>
   <td id="title_$foreach.count">$tut.title</td>
   <td id="desc_$foreach.count">$tut.description</td>
   <td id="auth_$foreach.count">$tut.author</td>
  </tr>
#end
</table>