Tuesday, May 7, 2013

JSP Pagination

The following example illustrates how to do pagination using JSP. There are two ways in doing the pagination. 
  1. Greedy Approach
  2. Non-Greedy Approach

Greedy Approach:

Greedy Approach means that we will get the list of records from back-end system for e.g., Database all at once and then we will show the records in multiple pages.

Non Greedy Approach:

Non Greedy Approach means that we will get the records from back-end system on demand as we click the page number link.

Please refer to this link jsp pagination from theopentuorials for this approach.

I have made a little modification to this approach in order to present the Greedy Approach.

The following are the source files for the example showing the Greedy Approach.

1. Employee.java:(bean class)


package com.pagination.bean;

import java.io.Serializable;

public class Employee implements Serializable{
private static final long serialVersionUID = 1L;
private int employeeId;
private String employeeName;
private double salary;
private String deptName;
public int getEmployeeId() {
return employeeId;
}
public void setEmployeeId(int employeeId) {
this.employeeId = employeeId;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
}


2.EmployeeDAO.java:

Here I have not followed exact DAO pattern. I have just hard-coded the employee objects instead of getting from database. This is just simulating the results.


package com.pagination.dao;

import java.util.ArrayList;
import java.util.List;
import com.pagination.bean.Employee;

public class EmployeeDAO {
private List<Employee> employeeList = new ArrayList<Employee>();
/**
* We need to write code to contact the database for getting the employee objects.
* For the ease I have hard-coded the things.
*/
public List<Employee> getAllEmployees(){
for(int i=1;i<10;i++){
employeeList.add(getEmployee(i));
}
return employeeList;
}
private Employee getEmployee(int empid){
Employee e = new Employee();
e.setEmployeeId(empid);
e.setDeptName("dept"+empid);
e.setEmployeeName("employee"+empid);
e.setSalary(100*empid);
return e;
}
public int getNoOfRecords(){
return employeeList.size();
}
}

3.EmployeeServlet.java

package com.pagination.servlet;

import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.pagination.bean.Employee;
import com.pagination.dao.EmployeeDAO;

public class EmployeeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
       
  protected void doGet(HttpServletRequest request, HttpServletResponse response) 
  throws ServletException, IOException {
  int page = 1;
        int recordsPerPage = 5;
        if(request.getParameter("page") != null){
        page = Integer.parseInt(request.getParameter("page"));
        }
        EmployeeDAO dao = new EmployeeDAO();
        List<Employee> list = dao.getAllEmployees();
        int noOfRecords = dao.getNoOfRecords();
        int noOfPages = (int) Math.ceil(noOfRecords * 1.0 / recordsPerPage);
        
        List<Employee> currentPageRecords =  getCurrentPageRecords(list,page);
        
        request.setAttribute("noOfPages", noOfPages);
        request.setAttribute("currentPage", page);
        request.setAttribute("currentPageRecords", currentPageRecords);
        RequestDispatcher view = request.getRequestDispatcher("displayEmployee.jsp");
        view.forward(request, response);
}
 
  public List<Employee> getCurrentPageRecords(List<Employee> totalList,int currentPageNo) {
if (totalList==null) {
return null;
}
int startIndex = (currentPageNo-1)*5;
int endIndex = (startIndex+5>totalList.size() ? totalList.size() : startIndex+5);
return totalList.subList(startIndex,endIndex);
}
}

4.web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
id="WebApp_ID" version="3.0">
<display-name>jsp-pagination</display-name>
<servlet>
<servlet-name>EmployeeServlet</servlet-name>
<servlet-class>com.pagination.servlet.EmployeeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EmployeeServlet</servlet-name>
<url-pattern>/employee</url-pattern>
</servlet-mapping>
</web-app>

5.displayEmplyee.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Employee Details</title>
</head>
<body>
<table border="1" cellpadding="5" cellspacing="5">
        <tr>
            <th>Emp ID</th>
            <th>Emp Name</th>
            <th>Salary</th>
            <th>Dept Name</th>
        </tr>
        <c:forEach var="employee" items="${currentPageRecords}">
            <tr>
                <td>${employee.employeeId}</td>
                <td>${employee.employeeName}</td>
                <td>${employee.salary}</td>
                <td>${employee.deptName}</td>
            </tr>
        </c:forEach>
    </table>
    <%--For displaying Previous link except for the 1st page --%>
    <c:if test="${currentPage != 1}">
        <td><a href="employee?page=${currentPage - 1}">Previous</a></td>
    </c:if>
    <%--For displaying Page numbers.
    The when condition does not display a link for the current page--%>
    <table border="1" cellpadding="5" cellspacing="5">
        <tr>
            <c:forEach begin="1" end="${noOfPages}" var="i">
                <c:choose>
                    <c:when test="${currentPage eq i}">
                        <td>${i}</td>
                    </c:when>
                    <c:otherwise>
                        <td><a href="employee?page=${i}">${i}</a></td>
                    </c:otherwise>
                </c:choose>
            </c:forEach>
        </tr>
    </table>
    <%--For displaying Next link --%>
    <c:if test="${currentPage lt noOfPages}">
        <td><a href="employee?page=${currentPage + 1}">Next</a></td>
    </c:if>
</body>
</html>

6.Project Structure























7.Result Screens

URL : 























Screen after clicking the next button






















This information is related to something like this. Let us consider we got more records from Database so that no of pages count also increases, it is not good  to display all the page numbers from 1 to n (look and feel of numbers below table is not so nice). As a solution to this I have modified the code in jsp, now the page looks like this,


















The following modifications are done to the above files to achieve this.

1.In displayEmplyee.jsp paste the below code instead of <c:forEach/> loop inside the <table>/<tr>


<table border="1" cellpadding="5" cellspacing="5">
        <tr>
    <!-- Comment above code and Uncomment the below code for displaying page numbers
     in range like (1 2 .. 10) in case if we have more number of pages -->
        <c:choose>
        <c:when test="${noOfPages < 5}">
           <c:forEach begin="1" end="${noOfPages}" var="i">
               <c:choose>
                   <c:when test="${currentPage eq i}">
                       <td>${i}</td>
                   </c:when>
                   <c:otherwise>
                       <td><a href="employee?page=${i}">${i}</a></td>
                   </c:otherwise>
               </c:choose>
           </c:forEach>
            </c:when>
            <c:otherwise>
            <c:choose>
<c:when test="${(currentPage <= 3)}">
<c:forEach begin="1" end="3" var="i">
               <c:choose>
                   <c:when test="${currentPage eq i}">
                       <td>${i}</td>
                   </c:when>
                   <c:otherwise>
                       <td><a href="employee?page=${i}">${i}</a></td>
                   </c:otherwise>
               </c:choose>
           </c:forEach>
           <td><a>...</a></td>
           <td><a href="employee?page=${noOfPages}">${noOfPages}</a></td>
</c:when>

<c:when test="${(currentPage > 3) and (noOfPages - currentPage >= 3)}">
<td><a href="employee?page=1">1</a></td>
<td><a>...</a></td>
<c:forEach begin="${currentPage-2}" end="${currentPage+2}" var="i">
               <c:choose>
                   <c:when test="${currentPage eq i}">
                       <td>${i}</td>
                   </c:when>
                   <c:otherwise>
                       <td><a href="employee?page=${i}">${i}</a></td>
                   </c:otherwise>
               </c:choose>
           </c:forEach>
<td><a href="employee?page=${noOfPages}">${noOfPages}</a></td>
</c:when>

<c:otherwise>
<td><a href="employee?page=1">1</a></td>
<td><a>...</a></td>
<c:forEach begin="${currentPage}" end="${noOfPages}" var="i">
               <c:choose>
                   <c:when test="${currentPage eq i}">
                       <td>${i}</td>
                   </c:when>
                   <c:otherwise>
                       <td><a href="employee?page=${i}">${i}</a></td>
                   </c:otherwise>
               </c:choose>
           </c:forEach>
</c:otherwise>
</c:choose>
            </c:otherwise>
           </c:choose>
        </tr>
    </table>

2. In EmployeeServlet.java file recordsPerPage decreased to 2 for getting more number of pages.




Ur's
Sivudu