Apache Pluto & Velocity Integration Tutorial Example

Filed Under: Portal and Portlets

Velocity is a Project of Apache Software Foundation, it’s released under Apache Velocity Engine where it’s considered as a Template Engine that provides a Template language to reference objects defined in the Java code.

The major aim of Velocity is to ensure clean separation between the presentation tier and business tier in the web application, similar for numerous presentation technologies that we had used before.

However, you’re developed a Portlet using a JSP & Servlet for registering employees and that you were used a JSP as a presentation tier, Standard Portlet as a controller and a Servlet for handling registration business.

The same example would be used this time, with one difference, in that a Velocity Templates and Velocity Portlet would replace your used JSPs and Standard Portlet, respectively.

This tutorial is going to provide you a full-fledged scenario for how you can use Velocity Templates for getting full functional Portlet that can be used for saving your employees against your database.

Project Structure

Here, you’ll get a full depiction for the whole created project:

Velocity Portlet - Project Structure

Employee Table

Before getting started looking into the way in which you can integrate a Velocity templates inside your application, take a glance for the Employee Table that would be used for retaining the employees and the SQL statement that’s used for creating the Table into your database.
Employee Table

Employee.SQL


CREATE TABLE `employee` (
  `EMP_ID` int(11) NOT NULL AUTO_INCREMENT,
  `EMP_NAME` varchar(45) DEFAULT NULL,
  `EMP_JOB` varchar(45) DEFAULT NULL,
  `EMP_SALARY` int(11) DEFAULT NULL,
  PRIMARY KEY (`EMP_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

Employee Model

According for MVC (Model-View-Controller) design pattern, the data must be retained inside a model, since it will be sent back and forth between the different components in the application (i.e. View & Controller). Since, we have single Employee Table, an Employee model will look like below:

Employee.java


package com.journaldev.data;

public class Employee {
	private int id;
	private String name;
	private String job;
	private int salary;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public String getJob() {
		return job;
	}

	public void setJob(String job) {
		this.job = job;
	}

	public int getSalary() {
		return salary;
	}

	public void setSalary(int salary) {
		this.salary = salary;
	}
}

RegisterEmployeePortlet Velocity Portlet

Creating of Velocity Portlet isn’t much complicated mission, as you may be familiar with many types of Portlets were introduced here. Like any normal Portlet, your Velocity one should look like below:

RegisterEmployeePortlet.java


package com.journaldev.portlet;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class RegisterEmployeePortlet extends org.apache.portals.bridges.velocity.GenericVelocityPortlet {

	public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
		// Check the status parameter
		if(request.getParameter("status") == null){
			// In case it's null, return into default view that's already defined in the portlet.xml viewPage
			super.doView(request, response);
		}
		else {
			// In case, the status value is success
			if(request.getParameter("status").equals("success")){
				PortletRequestDispatcher dispatcher = this.getPortletContext().getRequestDispatcher("/register/success.vm");
				// delegate the view into success.vm
				dispatcher.include(request, response);
			}
			else {
				// In case, the status value is failure
				PortletRequestDispatcher dispatcher = this.getPortletContext().getRequestDispatcher("/register/failure.vm");
				// delegate the view into failure.vm
				dispatcher.include(request, response);
			}
		}
	}

	public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException{
		// Create request dispatcher
		PortletRequestDispatcher dispatcher =  this.getPortletContext().getNamedDispatcher("RegisterEmployeeServlet");
		try {
			// Include
			dispatcher.include(request, response);
			// Set render parameter
			response.setRenderParameter("status", "success");
		}
		catch(Exception ex){
			// Set render parameter
			response.setRenderParameter("status", "failed");
			response.setRenderParameter("exception", ex.getMessage());
		}
	}
}

Here’s detailed explanation for the code mentioned above:

  • Your Portlet should extend org.apache.portals.bridges.velocity.GenericVelocityPortlet.
  • Like any standard Portlet, you have a chance of overriding required methods.
  • Typically, you have an access for different types of requests/responses.
  • As you may delegate the request into your JSP view as it happened in JSP & Servlet Tutorial, you have the ability to do the same thing with the Velocity markup Templates.
  • Since we have a default ViewPage value as init param, the calling of super.doView will give the registerEmployee.vm a chance to handle the request.
  • According for status parameter, you may get accessed success.vm or failure.vm.
  • You can reference your Velocity templates by using their defined path within your project, since they’re considered like any presentation technology you have dealt with. The path that we’ve suggested is /register/registerEmployee.vm, /register/success.vm and /register/faliure.vm.

RegisterEmployeePortlet Velocity Portlet Descriptor

Fortunately, there is not much details that you must be aware of when it comes to define your Portlet inside your Portlet deployment descriptor (Portlet.xml). However, like any Standard Portlet, your Portlet.xml should look like:

portlet.xml


<?xml version="1.0" encoding="UTF-8"?>

<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
	version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd">
	<portlet>
		<display-name>Register Employee</display-name>
		<portlet-name>RegisterEmployee</portlet-name>
		<portlet-class>com.journaldev.portlet.RegisterEmployeePortlet
		</portlet-class>
		<description>Employee Registration</description>
		<init-param>
			<name>ViewPage</name>
			<value>/register/registerEmployee.vm</value>
		</init-param>
		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
		</supports>
		<portlet-info>
			<title>Employee Registration</title>
			<keywords>employee, registration</keywords>
			<short-title>Employee Registration</short-title>
		</portlet-info>
	</portlet>
</portlet-app>

Here’s detailed explanation for the code typed above:

  • You should define ViewPage init param for getting registerEmployee.vm displayed once the Portlet accessed through its contained page.
  • Similar for ViewPage, you can add EditPage and HelpPage.
  • Supporting different views require you to tune your supports element.

Application Deployment Descriptor & Maven Build File

You may be asking about how the defined Velocity Templates got executed since no explicit declaration for the way in which that is done. In fact and indeed, a defined Servlet will handle the Velocity Templates interpretation process, so once your Portlet had delegated the request into any Velocity resources that ends with the *.vm, the Velocity Servlet get executed and the HTML output has returned. Look below at the deployment descriptor (web.xml):

web.xml


<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
	<display-name>Employee Registration</display-name>
	<servlet>
		<servlet-class>com.journaldev.servlet.RegisterEmployeeServlet</servlet-class>
		<servlet-name>RegisterEmployeeServlet</servlet-name>
	</servlet>
	<servlet-mapping>
		<servlet-name>RegisterEmployeeServlet</servlet-name>
		<url-pattern>/registerEmployeeServlet</url-pattern>
	</servlet-mapping>

	<!-- Define Velocity Servlet -->
	<servlet>
		<servlet-name>velocity</servlet-name>
		<servlet-class>org.apache.portals.bridges.velocity.BridgesVelocityViewServlet</servlet-class>
	</servlet>

	<!-- Map *.vm files to Velocity -->
	<servlet-mapping>
		<servlet-name>velocity</servlet-name>
		<url-pattern>*.vm</url-pattern>
	</servlet-mapping>

</web-app>

As you can notice, BridgesVelocityServlet has used in conjunction with the mapping element. Let’s glance the used Maven build file:

pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.journaldev</groupId>
	<artifactId>VelocityBridge</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>VelocityBridge</name>
	<url>http://maven.apache.org</url>
	<properties>
		<deployFolder>D:/Apache Pluto/pluto-2.0.3/webapps</deployFolder>
	</properties>
	<dependencies>
		<!-- Java Portlet Specification V2.0 -->
		<dependency>
			<groupId>org.apache.portals</groupId>
			<artifactId>portlet-api_2.0_spec</artifactId>
			<version>1.0</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.4</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.0</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
			<version>1.7.0</version>
		</dependency>
		<dependency>
			<groupId>commons-collections</groupId>
			<artifactId>commons-collections</artifactId>
			<version>3.1</version>
		</dependency>
		<dependency>
			<groupId>commons-digester</groupId>
			<artifactId>commons-digester</artifactId>
			<version>1.7</version>
		</dependency>
		<dependency>
			<groupId>commons-digester</groupId>
			<artifactId>commons-digester</artifactId>
			<version>1.7</version>
		</dependency>
		<dependency>
			<groupId>org.apache.velocity</groupId>
			<artifactId>velocity</artifactId>
			<version>1.5</version>
		</dependency>
		<dependency>
			<groupId>org.apache.velocity</groupId>
			<artifactId>velocity-tools</artifactId>
			<version>2.0</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>org.apache.pluto</groupId>
			<artifactId>pluto-taglib</artifactId>
			<version>1.1.7</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.32</version>
		</dependency>
		<dependency>
			<groupId>org.apache.portals.bridges</groupId>
			<artifactId>portals-bridges-velocity</artifactId>
			<version>2.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.portals.bridges</groupId>
			<artifactId>portals-bridges-common</artifactId>
			<version>2.0</version>
		</dependency>

	</dependencies>
	<build>
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<!-- bind 'pluto2:assemble' goal to 'process-resources' lifecycle -->
			<!-- This plugin will read your portlet.xml and web.xml and injects required
				lines -->
			<plugin>
				<groupId>org.apache.portals.pluto</groupId>
				<artifactId>maven-pluto-plugin</artifactId>
				<version>2.1.0-M3</version>
				<executions>
					<execution>
						<phase>generate-resources</phase>
						<goals>
							<goal>assemble</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<!-- configure maven-war-plugin to use updated web.xml -->
			<!-- This plugin will make sure your WAR will contain the updated web.xml -->
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.1.1</version>
				<configuration>
					<webXml>${project.build.directory}/pluto-resources/web.xml</webXml>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-antrun-plugin</artifactId>
				<executions>
					<execution>
						<id>copy</id>
						<phase>integration-test</phase>
						<configuration>
							<tasks>
								<copy file="target/${project.artifactId}.war" tofile="${deployFolder}/${project.artifactId}.war" />
							</tasks>
						</configuration>
						<goals>
							<goal>run</goal>
						</goals>
					</execution>
					<execution>
						<id>delete</id>
						<phase>clean</phase>
						<configuration>
							<tasks>
								<delete file="${deployFolder}/${project.artifactId}.war" />
								<delete dir="${deployFolder}/${project.artifactId}" />
							</tasks>
							<detail>true</detail>
						</configuration>
						<goals>
							<goal>run</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Velocity Templates (Views)

As we’ve stated earlier, you can use a Velocity Templates instead of using default JSP for rendering your requested view. Similar for JSP, an implicit objects have been defined inside your Velocity Templates for getting used while you’re developing your views. Let’s look at the created views and see the major things that must be noticed.

registeremployee.vm


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Register Employee</title>
</head>
<body>
	<form action="$renderResponse.createActionURL()" method="POST">
		<table width="100%">
			<tr width="60%">
				<td>Enter Employee ID:</td>
				<td><input name="employeeID" /></td>
			</tr>
			<tr width="60%">
				<td>Enter Employee Name:</td>
				<td><input name="employeeName" /></td>
			</tr>
			<tr width="60%">
				<td>Enter Employee Job:</td>
				<td><input name="employeeJob" /></td>
			</tr>
			<tr width="60%">
				<td>Enter Employee Salary:</td>
				<td><input name="employeeSalary" /></td>
			</tr>
			<tr width="60%" align="center">
				<td colspan="2"><input type="submit" value="Register" /></td>
			</tr>
		</table>
	</form>
</body>
</html>

Here’s detailed explanation for the code listed above:

  • Implicit objects that you may need are, RenderRequest, RenderResponse & PortletConfig.
  • You should use $renderRequest, $renderResponse & $portletConfig for getting referenced these objects, respectively.
  • Since these objects are Java Objects, so you have them with all accompanies relevant functions, just like you’re invoked them from within your Standard Portlet.
  • We created an actionUrl by calling $renderResponse.createActionURL().

success.vm


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Register Employee</title>
</head>
	<portlet:renderURL var="registerAnother">
		<portlet:param name="status" value="initiate"/>
	</portlet:renderURL>
	<img src="$renderRequest.getContextPath()/images/success.jpg" name="$renderResponse.getNamespace()Success"/>
	<body>
		<span>Congratulations ! you've just add a new employee</span><br/><a href="$renderResponse.createRenderURL()">Register Another</a>
	</body>
</html>

failure.vm


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Register Employee</title>
</head>
	<body>
		<span>Unfortunately ! you may not be able of registering a new employee cause the reason below</span>
		<br/>
		<br/>
		<img src="$renderRequest.getContextPath()/images/failed.jpg" name="$renderResponse.getNamespace()Failed"/>
		<span style="font-size:small ;font-style: italic;color: red;font-weight: bold;">
			$renderRequest.getParameter("exception")
		</span>
		<br/>
		<br/>
		<a href="$renderResponse.createRenderURL()">Try Again</a>
	</body>
</html>

Here’s detailed explanation for both of success and failure velocity templates:

  • We used $renderRequest.getContextPath() for specifying the context of the running application.
  • For getting safe code, since the Velocity Templates may contain the same JavaScript variable/code, you have the opportunity of making a unique identifier using $renderReponse.getNamespace().
  • You have the ability to get accessed specific request attributes by calling of $renderRequest.getParamater().
  • $renderResponse().createRenderURL() is used for rendering a render request against your Portlet.

Register Employee Business Handler

Handling of employee registration business isn’t a Portlet mission, as it’s considered like controller when it comes to map your components into MVC design. Regardless, of the type of Portlet you were used, we have a separate Servlet that’s responsible of handling the registration process; extract the request’s parameters and calling the database utilities for got employee saved.

RegisterEmployeeServlet.java


package com.journaldev.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import com.journaldev.dao.EmployeeDAO;
import com.journaldev.data.Employee;

public class RegisterEmployeeServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	Logger logger = Logger.getLogger(RegisterEmployeeServlet.class);

    public RegisterEmployeeServlet() {
        super();
    }

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// Create employee
		Employee employee = new Employee();
		// Fill in required data from the request sent
		employee.setId(Integer.parseInt(request.getParameter("employeeID")));
		employee.setName(request.getParameter("employeeName"));
		employee.setJob(request.getParameter("employeeJob"));
		employee.setSalary(Integer.parseInt(request.getParameter("employeeSalary")));
		try {
			// Asking employeeDAO creating the employee against registered database
			Employee createdEmployee = EmployeeDAO.getInstance().createEmployee(employee);
			// Print out the created employee information
			logger.info("Employee Created"+createdEmployee);
		} catch (Exception e) {
			// Log the exception
			logger.error("Employee Creation Failed", e);
			// Throw another exception for notifying the Portlet
			throw new ServletException(e);
		}
	}

}

Database Utility

Since our application has accessed the database for getting employee instance persisted, it’s important to handle the database code with the best practice we have own, EmployeeDAO ConnectionUtility are both classes used for accessing the database, safely and asynchronously.

EmployeeDAO.java


package com.journaldev.dao;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import com.journaldev.dao.utility.ConnectionUtility;
import com.journaldev.data.Employee;

public class EmployeeDAO {

	public static EmployeeDAO employeeDAO = null;

	private EmployeeDAO(){

	}

	public static EmployeeDAO getInstance(){
		synchronized(EmployeeDAO.class){
			if(employeeDAO == null){
				employeeDAO = new EmployeeDAO();
			}

		}
		return employeeDAO;
	}

	public Employee createEmployee(Employee employee) throws SQLException, IllegalAccessException, IOException, ClassNotFoundException{
		// Get connection instance
		Connection connection = ConnectionUtility.getInstance().getConnection();
		// Create Prepared Statement
		PreparedStatement query = connection.prepareStatement("INSERT INTO EMPLOYEE VALUES (?,?,?,?)");
		// Set variables
		query.setInt(1, employee.getId());
		query.setString(2, employee.getName());
		query.setString(3, employee.getJob());
		query.setInt(4, employee.getSalary());

		try {
			// Execute
			query.execute();
			// Return employee instance
			return employee;
		}
		catch(Exception e){
			// Close statement
			query.close();
			// Close connection
			connection.close();
			// Throw another exception for notifying the Servlet
			throw new SQLException(e);
		}
	}

	public boolean deleteEmployee(Employee employee){
		return false;
	}

	public boolean updateEmployee(Employee employee, int employeeId){
		return false;
	}
}

ConnectionUtility.java


package com.journaldev.dao.utility;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public class ConnectionUtility {

	private static ConnectionUtility connectionUtiliy = null;

	private Connection connection = null;

	private ConnectionUtility() {
	}

	public static ConnectionUtility getInstance() throws IOException, IllegalAccessException, SQLException, ClassNotFoundException{
		// Synchronized against connectionUtility instance
		synchronized(ConnectionUtility.class){
			// Check whether the connectionUtility is null or not
			if(connectionUtiliy == null){
				// Create a properties instance
				Properties properties = new Properties();
				// Load properties from classpath
				properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("connection.properties"));
				// Set connection with connectionUtility
				connectionUtiliy = new ConnectionUtility();
				// Load driver class
				Class.forName("com.mysql.jdbc.Driver");
				// Create connection
				connectionUtiliy.setConnection(DriverManager.getConnection("jdbc:mysql://localhost:3306/journaldev", properties));
			}
			return connectionUtiliy;
		}
	}

	public Connection getConnection() throws ClassNotFoundException, SQLException, IOException {
		if(connection.isClosed()){
			// Create a properties instance
			Properties properties = new Properties();
			// Load properties from classpath
			properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("connection.properties"));
			// Load driver class
			Class.forName("com.mysql.jdbc.Driver");
			// Create connection
			connectionUtiliy.setConnection(DriverManager.getConnection("jdbc:mysql://localhost:3306/journaldev", properties));
		}
		return connection;
	}

	public void setConnection(Connection connection) {
		this.connection = connection;
	}

}

Employee Registration Demo

We assumed that you have a running instance of Apache Pluto as you are also created a Portal page named JournalDev and you’re also familiar with the way which can be used for deploying your Portlet into your Portal page. In case, you’ve heard this for the first time, it’s worth for you to return back into our Apache Pluto Introduction for get everything relevant done.

Velocity Portlet - Initial View

Once the user has activated the register action, the Portlet’s processAction method has been executed and the Register Servlet would be invoked. The user will be informed instantly with the result of registration operation and whether it’s got finished successfully or not.

Velocity Portlet - Success ResultVelocity Portlet - Database RecordNow, what’s happened just in case you’ve tried to register another employee with the same identifier:

Velocity Portlet - Failure Result

Summary

It’s fantastic, as you can create whatever you want of Portlets using the standard Portlet container specification. You’ve already faced a JSP & Servlet, PHP, JSF, Struts & now a Velocity Templates one. Your comments or notes are highly appreciated as you can find the downloaded source listed below for your practice.

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages