Open In App

How to Create Dynamic Web Pages using Apache Velocity?

Last Updated : 09 Jan, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Apache Velocity is an open-source java-based templating engine that can play as an alternative to JSP (Jakarta server pages). It is helpful to generate XML files, SQL, etc., In this article, let us see the creation of dynamic web pages.

Working way of Velocity:

  • Velocity engine initialization
  • Reading the template
  • Putting the data model in the context object
  • Finally merging the template with context data and rendering the view

Essentially we need to see what are dependencies needed to use apache velocity

<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>

Velocity Template Language (VTL) reference starts with $ for getting a value and for setting the value # is used. Let us see how to use variables, properties, and methods

variables

#set ($<your message>="Welcome to GeeksForGeeks") // To set a message

properties

$product.productName  //(To get a product name)

methods

$product.getProductName()

Finally, the result is rendered as a string. Let us see the whole concept by using a sample maven project.

Example Maven Project

Project Structure:

Project Structure

 

Let us start with pom.xml as all dependencies need to be given there

pom.xml

XML




<?xml version="1.0" encoding="UTF-8"?>
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                        http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <artifactId>apache-velocity</artifactId>
    <version>0.1-SNAPSHOT</version>
    <name>apache-velocity</name>
    <packaging>war</packaging>
 
    <parent>
        <groupId>com.gfg</groupId>
        <artifactId>parent-modules</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
 
    <dependencies>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>${velocity-version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-tools</artifactId>
            <version>${velocity-tools-version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>${org.apache.httpcomponents.version}</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <artifactId>commons-logging</artifactId>
                    <groupId>commons-logging</groupId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
 
    <build>
        <finalName>apache-velocity</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
 
        </plugins>
    </build>
 
    <properties>
        <org.apache.httpcomponents.version>4.5.2</org.apache.httpcomponents.version>
        <velocity-version>1.7</velocity-version>
        <velocity-tools-version>2.0</velocity-tools-version>
    </properties>
 
</project>


Let us write the java code involving model, service, and servlet classes first

OnlineProductSale.java

Java




public class OnlineProductSale {
   
    private String productName;
    private double productPrice;
   
    public OnlineProductSale(String productName, double productPrice) {
        this.productName = productName;
        this.productPrice = productPrice;
    }
 
    public String getProductName() {
        return productName;
    }
 
    public void setProductName(String productName) {
        this.productName = productName;
    }
 
    public double getProductPrice() {
        return productPrice;
    }
 
    public void setProductPrice(double productPrice) {
        this.productPrice = productPrice;
    }
 
    @Override
    public String toString() {
        return "OnlineProductSale{" + "productName='" + productName + '\'' + ", productPrice=" + productPrice + '}';
    }
}


OnlineProductService.java

Java




import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import com.gfg.model.OnlineProductSale;
 
import java.util.Arrays;
import java.util.List;
 
public class OnlineProductService {
 
    Logger logger = LoggerFactory.getLogger(OnlineProductService.class);
 
    public List<OnlineProductSale> getOnlineProductsForSale() {
        logger.debug("Product service returning list of products");
 
        return Arrays.asList(new OnlineProductSale("Dell Laptop", 31000.00), new OnlineProductSale("Samsung Mobile", 16000.00),
                new OnlineProductSale("Samsung Tablet", 15000.00), new OnlineProductSale("Sony Camera", 23000.00));
    }
}


OnlineProductServlet.java

Java




package com.gfg.servlet;
 
import com.gfg.model.OnlineProductSale;
import com.gfg.service.OnlineProductService;
 
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 OnlineProductServlet extends VelocityViewServlet {
 
    OnlineProductService service = new OnlineProductService();
 
    @Override
    public Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) {
 
        Logger logger= LoggerFactory.getLogger(OnlineProductServlet.class);
 
        List<OnlineProductSale> onlineProductsForSale = service.getOnlineProductsForSale();
 
        context.put("products", onlineProductsForSale);
 
        Template template = null;
 
        try {
            // Referring the index.vm present
              // under templates directory
            template = getTemplate("templates/index.vm");
            response.setHeader("Template Returned", "Success");
        } catch (Exception e) {
            logger.error("Error while reading the template ", e);
        }
 
        return template;
 
    }
}


SampleLayoutServlet.java

Java




import com.gfg.model.OnlineProductSale;
import com.gfg.service.OnlineProductService;
 
import org.apache.velocity.Template;
import org.apache.velocity.context.Context;
import org.apache.velocity.tools.view.VelocityLayoutServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
 
public class SampleLayoutServlet extends VelocityLayoutServlet {
   
    OnlineProductService service = new OnlineProductService();
 
    @Override
    public Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) {
 
        Logger logger= LoggerFactory.getLogger(SampleLayoutServlet.class);
 
        List<OnlineProductSale> onlineProductsForSale = service.getOnlineProductsForSale();
 
        context.put("products", onlineProductsForSale);
 
        Template template = null;
 
        try {
            // Referring layoutdemo.vm from templates folder
            template = getTemplate("templates/layoutdemo.vm");
 
            response.setHeader("Template Returned", "Success");
        } catch (Exception e) {
            logger.error("Error while reading the template ",e);
        }
 
        return template;
 
    }
}


index.vm

HTML




<HTML>
<HEAD>
    <TITLE>Online Electronic Store</TITLE>
    <style>
        body {background-color: Aqua;}
        h1   {color: green;}
        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 are available for Sale today!</h2>
    <BR/>
    Welcome to our store for exiting 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.getProductName()</TD>
                <TD>$product.getProductPrice()</TD>
            </TR>
            #set( $count = $count + 1 )
        #end
    </TABLE>
    <BR/>
</CENTER>
 
</BODY>
</HTML>


If we look at the vm file, we are seeing the ways of setting the value by using

#set( $count = 1 )  -- Here count is a variable assigned with value 1

Similarly to display the retrieved value (i.e. get values, by using

$product.getProductName() // To get the product name
$product.getProductPrice() // To get the product price

In order to run the loop, we have to do the following

// almost it is similar like java code only
#foreach( $product in $products ) 
            <TR>
                <TD>$count)</TD>
                <TD>$product.getProductName()</TD>
                <TD>$product.getProductPrice()</TD>
            </TR>
            #set( $count = $count + 1 )
        #end

Let us see the important web.xml (configuration file) and then run the program. VelocityViewServlet configuration in web.xml has to be done

web.xml

XML




<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 
<web-app>
    <display-name>apache-velocity</display-name>
    <servlet>
        <servlet-name>OnlineProductServlet</servlet-name>
        <servlet-class>com.gfg.servlet.OnlineProductServlet</servlet-class>
    </servlet>
 
    <servlet>
        <servlet-name>SampleLayoutServlet</servlet-name>
        <servlet-class>com.gfg.servlet.SampleLayoutServlet</servlet-class>
    </servlet>
       
      <!-- This is much required to use VelocityViewServlet in the web.xml.-->
    <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>
   
      <!-- This is much required to use VelocityViewServlet in the web.xml.-->
    <servlet-mapping>
        <servlet-name>OnlineProductServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
 
    <servlet-mapping>
        <servlet-name>SampleLayoutServlet</servlet-name>
        <url-pattern>/layout</url-pattern>
    </servlet-mapping>
   
      <!-- This is much required to use VelocityViewServlet in the web.xml.-->
    <servlet-mapping>
        <servlet-name>velocityLayout</servlet-name>
          <!-- we need to see .vm file to be referred -->
        <url-pattern>*.vm</url-pattern>
    </servlet-mapping>
   
      <!-- This is much required to use VelocityViewServlet in the web.xml.-->
    <!-- session timeout -->
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
 
    <!-- welcome file -->
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
 
</web-app>


WEB-INF/layout.properties

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

On running the program on tomcat, we can see the below output

XML




<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 
<web-app>
    <display-name>apache-velocity</display-name>
    <servlet>
        <servlet-name>OnlineProductServlet</servlet-name>
        <servlet-class>com.gfg.servlet.OnlineProductServlet</servlet-class>
    </servlet>
 
    <servlet>
        <servlet-name>SampleLayoutServlet</servlet-name>
        <servlet-class>com.gfg.servlet.SampleLayoutServlet</servlet-class>
    </servlet>
       
      <!-- This is much required to use VelocityViewServlet in the web.xml.-->
    <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>
   
      <!-- This is much required to use VelocityViewServlet in the web.xml.-->
    <servlet-mapping>
        <servlet-name>OnlineProductServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
 
    <servlet-mapping>
        <servlet-name>SampleLayoutServlet</servlet-name>
        <url-pattern>/layout</url-pattern>
    </servlet-mapping>
   
      <!-- This is much required to use VelocityViewServlet in the web.xml.-->
    <servlet-mapping>
        <servlet-name>velocityLayout</servlet-name>
          <!-- we need to see .vm file to be referred -->
        <url-pattern>*.vm</url-pattern>
    </servlet-mapping>
   
      <!-- This is much required to use VelocityViewServlet in the web.xml.-->
    <!-- session timeout -->
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
 
    <!-- welcome file -->
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
 
</web-app>


As a good practice let us test the same via our testcases as well

OnlineProductServletLiveTest.java

Java




import static org.junit.Assert.assertEquals;
 
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.junit.Test;
 
public class OnlineProductServletLiveTest {
 
    @Test
    public void whenRequestUsingHttpClient_thenCorrectResponse() throws Exception {
 
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet method= new HttpGet("http://localhost:8080/apache-velocity/");
 
        HttpResponse httpResponse = httpClient.execute(method);
 
        assertEquals("Success", httpResponse.getHeaders("Template Returned")[0].getValue());
 
    }
}


Output of JUnit:

Output of JUnit

 

Conclusion

Rendering of dynamic web pages is easier via Apache Velocity and in the software industry, it is widely used.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads