In the previous tutorials that we’ve examined before, a RenderResponse writer is used mainly for writing the Portlets’ fragments into Portal page. This way of forming the Portlets’ contents isn’t used elegantly as it’s also doesn’t adhere the separation of concern (SoC) concept.
Combining the business code and UI fragments cohesively would lead us to code hard to maintain, hard to trace and less agility. As such, it’s important for you to make some sort of separation between your parts; UI and Business.
Portlet Servlet JSP
This tutorial will help you getting all of these concepts achieved as it’s would show you a full example of how can orchestrate between Portlets, JSPs and Servlets for making an employee registration mission so organized.
Registration form that we’re going to implement, is a full-fledged one, as you can fill in the all required information for the employee that you may want be registered. Information like employee identifier, employee name, employee job and employee salary the Portlet accepts and the database should retain.
Any professional application must provide the end users a confirmation messages either the process has finished successfully or something went wrongly.
In between, you will learn the all detailed fine-grained information that may help you achieve the integration between Portlets, JSPs and Servlets. Different integration principles like RequestDispatcher, Portlet Tag Library, handling exceptions and the way in which can leverage all of these principles to get everything done smoothly.
Portlet Tag Library
JavaServer Pages can use Portlet Tag Library to get access of Portlet functionality. Any JSP pages can import the Portlet Tag library that’s already provided by pluto-taglib
dependency.
<defineObjects/>
, <param/>
, <actionURL/>
, <renderURL/>
and <namespace/>
, all of these are provided Tags for being used by the JavaServer Pages.
The <defineObjects/>
Tag, is used to define several objects from the calling Portlet’s request in the JSP page. Using of <defineObjects/>
would define three different variables to be used from within your JSP scriptlets. These variables are portletConfig
, renderRequest
and renderResponse
.
The <param>
Tag, is used to send a parameters for the <actionURL/>
and <renderURL/>
. Every parameter must be a pair of name and value.
The <actionURL/>
and <renderURL/>
are used for generating an action URL for calling action phase and a render URL for calling render phase, respectively. Both of them has provided a var attribute that would be used later on in the form action or link’s target.
The <namespace/>
is used for generating a unique name that would be used with the JavaScript code for making unique JavaScript variables, libraries or resources.
Portlet Request Dispatcher
Similar like Servlet, RequestDispacther
is to dispatch the request into another Web resource. However, PortletRequestDispatcher
is the object that you may got if you’ve called getRequestDispatcher()
or getNamedDispatcher()
against PortletContext
object.
The difference here is that, the getRequestDispatcher()
has used a path for locating a Web resource, while getNamedDispatcher()
has used a defined name for locating a Web resource.
You may invoke include
and forward
upon your PortletRequestDispatcher
. Using of forward
will close the output stream after it has been invoked, whereas, the include
method leaves the output stream open.
Employee Table Design
Before getting started implementing the registration form, let’s see the structure of the Table and its relevant columns as well as the SQL statement that lead you to create similar one into your database.
1 2 3 4 5 6 7 8 9 |
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=4 DEFAULT CHARSET=utf8; |
Employee POJO
As we’ve stated the Employee Table previously, it’s very easy for you to expect the Employee POJO.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
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; } } |
As you’ve seen, Employee POJO is just a normal Java bean that’s contained for four different attributes with their gets and sets methods. id, name, job and salary are attributes that the user must provide for getting employee registered normally.
Design View
Mainly, vast amount of frameworks that were implemented had considered MVC (Model, View & Controller) as a base design for them. MVC is a design pattern, that’s aimed to make concern separation in order to allow develop components in a loosely coupled manner.
Being MVC is a design pattern, it’s applicable for you to design your Portlets to be MVC-compliance. JSPs can be used for viewing purposes, Portlets as a controllers and a simple POJO (Plain Old Java Object) can be your models.
Find below sequence diagram that shows you the way in which the registration process being handled and how the proposed parts are working collectively making this mission possible.
Here’s detailed explanation for the diagram listed above:
- RegisterEmployee JSP page is the view that it would be used for gathering the information for employee being registered.
- RegisterEmployeePortlet is the controller, it would be used for handling the business and dispatching into next coming view. We’ve added a RegisterEmployeeServlet as a complement component that’s aimed to handle the employee registration business.
- EmployeeDAO and ConnectionUtility are just a components that are contained all relevant database code.
Employee Registration Views
We’ve defined different views for the employee registration purpose, as the process of registration may result in a success or failure status, we’ve added two additional views for the main one (registerEmployee.jsp
). The success.jsp
and failure.jsp
should help the user getting a confirmation messages, to know whether the process has been completed successfully or it’s failed and what’s the reason of failure.
registerEmployee.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri='https://java.sun.com/portlet' prefix='portlet'%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Register Employee</title> </head> <body> <portlet:actionURL var="registerLink"/> <form action="<%=registerLink%>" 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:
- The form of employee registration doesn’t contain any strange code except that’s related for
<portlet:actionURL/>
Tag. Mainly, action URL is used for generating a URL would call theprcoessAction()
when it’s clicked. - We’ve used generated action URL to form the action of the whole form. Notice using of Scriptlets for accessing the generated URL.
success.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri='https://java.sun.com/portlet' prefix='portlet'%> <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="https://www.journaldev.com/4957/<%=request.getContextPath()%>/images/success.jpg" name="<portlet:namespace/>Success"/> <body> <span>Congratulations ! you've just add a new employee</span><br/><a href="<%=registerAnother%>">Register Another</a> </body> </html> |
Here’s detailed explanation for the code listed above:
- We’ve used
<renderURL/>
to generate a render URL that’s used for invoking render phase. One parameter has been passed, it’s status which will be used for dispatching purpose. - Implicit objects like
request
,response
that are received by the JSP and Servlet can be used but with a limitation as many of their methods either perform no operation or return null when used inside a Portlet container.
failure.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri='https://java.sun.com/portlet' prefix='portlet'%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Register Employee</title> </head> <portlet:defineObjects/> <portlet:renderURL var="registerAnother"> <portlet:param name="status" value="initiate"/> </portlet:renderURL> <body> <span>Unfortunately ! you may not be able of registering a new employee cause the reason below</span> <br/> <br/> <img src="https://www.journaldev.com/4957/<%=request.getContextPath()%>/images/failed.jpg" name="<portlet:namespace/>Failed"/> <span style="font-size:small ;font-style: italic;color: red;font-weight: bold;"> <%=renderRequest.getAttribute("exception")%> </span> <br/> <br/> <a href="<%=registerAnother%>">Try Again</a> </body> </html> |
Here’s detailed explanation for the code listed above:
- We’ve used two different Portlet Tags,
<renderURL/>
and<defineObjects/>
. - We never be able of accessing the implicit object renderRequest, if we don’t use the
<defineObjects/>
Portlet Tag. - Implicit objects like
request
,response
that are received by the JSP and Servlet can be used but with a limitation as many of their methods either perform no operation or return null when used inside a Portlet container.
Employee Registration Portlet
As we’ve defined the Views that are needed for covering the all scenarios that you may face while employee registration. It’s time to define the controller, following below RegisterEmployeePortlet
that would help you dispatching into required views.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
package com.journaldev.portlet; import java.io.IOException; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.GenericPortlet; import javax.portlet.PortletException; import javax.portlet.PortletRequestDispatcher; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; public class RegisterEmployeePortlet extends GenericPortlet{ public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { if(request.getParameter("status") == null){ // Create a dispatcher PortletRequestDispatcher dispatcher = this.getPortletContext().getRequestDispatcher("/register/registerEmployee.jsp"); dispatcher.include(request, response); } else if(request.getParameter("status") != null && request.getParameter("status").equals("initiate")){ // Create a dispatcher PortletRequestDispatcher dispatcher = this.getPortletContext().getRequestDispatcher("/register/registerEmployee.jsp"); dispatcher.include(request, response); } else if(request.getParameter("status") != null && request.getParameter("status").equals("success")){ // Create a dispatcher PortletRequestDispatcher dispatcher = this.getPortletContext().getRequestDispatcher("/register/success.jsp"); dispatcher.include(request, response); } else if(request.getParameter("status") != null && request.getParameter("status").equals("failed")){ // Create a dispatcher PortletRequestDispatcher dispatcher = this.getPortletContext().getRequestDispatcher("/register/failure.jsp"); request.setAttribute("exception", request.getParameter("exception")); 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 listed above:
RegisterEmployeePortlet
overrode two methods from itsGenericPortlet
parent class.- The
doView()
method will determine which view it should be delegate for based on the status parameter. - The
processAction()
will handle the registration action as it should delegate the action intoRegisterEmployeeServlet
. - In case the
RegisterEmployeeServlet
has completed its work sucessfully, a statussuccess
parameter will be set as a render parameter for getting accessed by the render phase after then. - In case the
RegisterEmployeeServlet
has initiated an exception the catch block will handle it and put a statusfailed
as a render parameter for getting accessed by the render phase after then. - JSPs are located using the
getRequestDispatcher()
while Servlet is located using thegetNamedDispatcher()
. We’ve passed the name of the Servlet that’s registered in the deployment descriptor as a parameter.
Employee Registration Servlet
RegisterEmployeeServlet is used to complete the registration process.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
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); } } } |
Here’s detailed explanation for the code listed above:
- As the form that was initiated the action has used a
POST
method, the Servlet should provide an implementation for it. - The employee object has been created by extracting its properties from the request object.
- It’s Using an
EmployeeDAO
for creating the employee. - It’s Handling the exception in case you’ve got one, and throw a new one for Portlet informing purpose.
EmployeeDAO & ConnectionUtility
We’ve implemented two different singleton classes for handling the employee’s database operations and acquiring the needed connections respectively.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
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; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
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; } } |
It’s important to know that the username and password of the database are read from connection.properties file that’s defined in the resources.
Deployment Descriptor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "https://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> <taglib> <taglib-uri>https://java.sun.com/portlet</taglib-uri> <taglib-location>/WEB-INF/portlet.tld</taglib-location> </taglib> </web-app> |
Maven Build File
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.journaldev</groupId> <artifactId>EmployeeRegistrationApp</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>EmployeeRegistrationApp</name> <url>https://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-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3</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> </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.7</source> <target>1.7</target> </configuration> </plugin> </plugins> </build> </project> |
Employee Registration Demo
It’s now time of executing the application that’s just developed. At the beginning, make sure that you’re deploying the application into your Pluto Portal and you get access to JournalDev page.
Once, you’ve got this page, be sure that the doView() method has been executed and it checks for status variable that’s already null. As a result, the doView() method has dispatched the request into registerEmployee.jsp. Just fill in all the employee’s information.
By clicking on Register, your RegisterEmployeePortlet’s processAction() is executed and the RegisterEmployeeServlet will handle the whole registration process. As a result, the employee must be registered and the user must be confirmed about that.
Now, you have the opportunity to get back into registration form by clicking on the Register Another link. This link is associated with the <renderURL/> as it’s passed a status value. What’s happened if you try to register the same employee with the same identifier. You’re mostly got an exception relevant for the database.
Summary
Using of Portlets with respect to JSP and Servlet is consider so attractive things as it contains a lot of details you must be aware of. We’re already handled that on behalf of you as you can download the source code to know how’s everything going on. Contribute us by commenting below and let us know if you have any concern or questions want to be answered.