Srikanth Technologies

HelpDesk Application Using JSF

HelpDesk is a web based customer support system. It allows customers to do the following:

Technologies and Products Used

In order to develop this application we are going to use the following technologies.

Tables Structure

The following are the tables required for this application.

CUSTOMERS Table

Contains details of all registered customers. Create this table using CREATE TABLE command as follows:
create table customers
(
customerid   number(5) primary key,
loginname varchar(20)  unique,
password varchar(10),
reg_date  date,
email   varchar(50) unique,
serialno  varchar(50) unique
);

ISSUES Table

Stores all issues posted by customers. Create this table with the following CREATE TABLE command.
create table Issues
(
Issueid  number(5) primary key,
customerid number(5) references customers(customerid),
issuetitle  varchar(100),
issuedescription  varchar(2000),
postedon  date,
status  char(1),
resolvedon  date,
supportperson  varchar(20)
);

ISSUERESPONSES Table

Stores all responses given either by support persons or by customers.
create table IssueResponses
( 
IRId number(5) primary key,
Issueid  number(5) references issues(issueid),
IRTitle  varchar(100),
IRDescription varchar(2000),
Postedon date,
Postedby  varchar(20)
);

Sequences

Oracle supports database object called sequence which can be used to get numbers in a sequence. This application uses three sequences - one for customer id , one for issue id and another for issue response id. Create these sequences as follows:
create sequence  customerid start with 1 increment by 1 nocache;
create sequence  issueid start with 1 increment by 1 nocache;
create sequence  irid start with 1 increment by 1 nocache;

Create Web Project using NetBeans IDE

Create a web application using NetBeans by following the steps given below:
  1. Start Netbeans IDE
  2. Select File->New Project
  3. Select web from categories and select Web application
  4. Click on Next
  5. Enter helpdesk as project name, select Bundled Tomcat as server
  6. Click on Next
  7. Check JavaServer Faces from Frameworks window
  8. Click on Finsh

Registration

Registration allows a customer to register the product he purchased. Along with serial number of the product, customer provides loginname, password, email address etc.

It uses the following pages and methods of the project.

all/register.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>

<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!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>Registration</title>
        <link href="../styles.css"  rel="stylesheet"/>
    </head>
    <body>
        <center>
            <f:view>
                <div class="head">OnLine Help Desk</div>
                <h:form>
                    <h3>Registration</h3>
                    <table>
                        <tr  align="left">
                            <td>Login Name : </td>
                            <td> <h:inputText id="loginname" required="true" size="20" value="#{CustomerBean.loginname}"  /> 
                            <h:message id="m1" for="loginname"  />  </td>
                        </tr>
                        <tr  align="left">
                            <td>Password : </td>
                            <td> <h:inputSecret id="password" required="true" size="20"  style="width:150px" value="#{CustomerBean.password}"    /> 
                                <h:message id="m2" for="password"  />  
                            </td>
                        </tr>
                        <tr   align="left">
                            <td>Confirm Password : </td>
                            <td> <h:inputSecret id="confirmpassword" required="true" size="20"  style="width:150px" value="#{CustomerBean.confirmpassword}" /> 
                            <h:message id="m3" for="confirmpassword" /> </td>
                        </tr>
                        <tr  align="left">
                            <td>Email Address :  </td>
                            <td><h:inputText id="email" required="true" size="20" value="#{CustomerBean.email}"  /> 
                            <h:message id="m4" for="email" /> </td>
                        </tr>
                        
                        <tr  align="left">
                            <td>Serail No. :  </td>
                            <td><h:inputText id="serialno" required="true" size="20" value="#{CustomerBean.serialno}"  /> 
                            <h:message id="m5" for="serialno" /> </td>
                        </tr>
                        
                    </table>
                    <p/>
                    <h:commandButton value="Register" actionListener="#{CustomerBean.register}" />
                    <p/>
                    <h4> <h:outputText escape="false"  value="#{CustomerBean.message}"/> </h4>

                </h:form>
            </f:view>
        </center>
    </body>
</html>

/WEB-INF/classes/beans/CustomerBean.java
package beans;

import dao.CustomerDAO;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.jstl.sql.Result;

public class CustomerBean {
    private String loginname,oldpassword,password,confirmpassword,email,serialno, message;
    public String getLoginname() {
        return loginname;
    }
    public void setLoginname(String loginname) {
        this.loginname = loginname;
    }

    public String getPassword() {
        return password;
    }
    
    public void setPassword(String password) {
        this.password = password;
    }
    
    public String getConfirmpassword() {
        return confirmpassword;
    }
    
    public void setConfirmpassword(String confirmpassword) {
        this.confirmpassword = confirmpassword;
    }
    
    public String getEmail() {
        return email;
    }
    
    public void setEmail(String email) {
        this.email = email;
    }
    
    public String getSerialno() {
        return serialno;
    }
    
    public void setSerialno(String serialno) {
        this.serialno = serialno;
    }
    
    public void register(ActionEvent evt){
        if (! password.equals(confirmpassword)) {
            message="Password and confirm password do not match!";
            return;
        }
        boolean done = CustomerDAO.register(loginname,password,email,serialno);
        if ( done)
            message= "Registration Completed. Use <a href=../login.jsp>Login Page</a> to login.";
        else
            message= "Sorry! Could not complete registration.";
    }
    
    public String getMessage() {
        return message;
    }
    
    public void setMessage(String message) {
        this.message = message;
    }
    
    public Result getIssues() {
        try {
            HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
            return CustomerDAO.getIssues( session.getAttribute("customerid").toString());
        } catch(Exception ex) {
            System.out.println(ex.getMessage());
            return(null);
        }
    }
    
    public void recoverPassword(ActionEvent evt) {
         // get password
        String password = CustomerDAO.getPassword(email);
        if ( password == null)
            message = "Sorry! Could not get password for the given email address";
        else {
            try {
            // send mail to user
            Properties props = System.getProperties();
            Session session = Session.getDefaultInstance(props, null);
            // construct the message
            Message msg = new MimeMessage(session);
            msg.setFrom(new InternetAddress("admin@homepc.com"));
            msg.setRecipient(Message.RecipientType.TO,new InternetAddress(email));
            msg.setDataHandler( new DataHandler(new String("<html><body>Dear Customer,<p/>Use the following password to login. <p/>Password:" + password + "<p/>Webmaster,<br>onlinehelpdesk.com<body></html>"),
                    "text/html"));
            msg.setSubject("Password Recovery");
            // send message
            Transport.send(msg);
            message = "Password is sent to your email address. Use that password to login!";
            }
            catch(Exception ex) {
                message = "Sorry! Could not send mail!";
            }
         }
    }
    public void changePassword(ActionEvent evt) {
        if (! password.equals(confirmpassword))  {
            message="Error --> New password and confirm password do not match!";
            return;
        }
        HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
        String status = CustomerDAO.changePassword(
                session.getAttribute("customerid").toString(),getOldpassword(), password);
        if ( status == null)
            message="Password Has Been Changed Successfully";
        else
            message = "Error -->" + status;
    }
    
    
    public String login(){
        String customerid = CustomerDAO.login(loginname,password);
        if ( customerid == null) {  // login failed
            message="Sorry! Invalid Login!";
            return "failed";
        } else {
            // get current session
            HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
            session.setAttribute("customerid", customerid);
            session.setAttribute("loginname",loginname);
            return "success";
        }
    }

    public String getOldpassword() {
        return oldpassword;
    }

    public void setOldpassword(String oldpassword) {
        this.oldpassword = oldpassword;
    }
}

Note : Remember CustomerBean.java is used as Managed bean for other JSF forms also. Method register() is used to call register() method of CustomerDAO.java. Create CustomerDAO class in dao package as follows.
/WEB-INF/classes/dao/CustomerDAO.java
package dao;
import dao.Database;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.servlet.jsp.jstl.sql.Result;
import javax.servlet.jsp.jstl.sql.ResultSupport;

public class CustomerDAO {
   
    public static String getPassword(String email) {
        try {
            Connection con = Database.getConnection();
            PreparedStatement ps = con.prepareStatement("select password from customers where email = ?");
            ps.setString(1,email);
            ResultSet rs = ps.executeQuery();
            String password = null;
            if ( rs.next() )
                password = rs.getString("password");
            rs.close();
            con.close();
            return password;
        } catch(Exception ex) {
            return null;
        }
    }
    
  
    public static Result getIssues(String customerid) throws Exception {
            Connection con =  Database.getConnection();
            Statement statement = con.createStatement();
            ResultSet resultSet = statement.executeQuery("select * from issues where customerid = " + customerid + " order by issueid desc");
            System.out.println("got data");
            return( ResultSupport.toResult(resultSet));
    }
           
    public static String login(String lname, String pwd) {
        try {
            Connection con = Database.getConnection();
            if ( con == null )
                return null;
            PreparedStatement ps = con.prepareStatement("select customerid from customers where loginname = ? and password = ?");
            ps.setString(1,lname);
            ps.setString(2,pwd);
            ResultSet rs = ps.executeQuery();
            String customerid=null;
            if ( rs.next() )  // found - return fullname
                customerid = rs.getString(1);
            rs.close();
            con.close();
            return customerid;
        } 
        catch(Exception ex) {
            return null;
        }
    }
        
    public static String changePassword( String customerid, String oldpwd, String newpwd) {
        try {
            Connection con = Database.getConnection();
            PreparedStatement ps = con.prepareStatement
               ("update customers set password = ? where customerid = ? and password = ?");
            ps.setString(1, newpwd);
            ps.setString(2, customerid);
            ps.setString(3, oldpwd);
            int count  = ps.executeUpdate();
            ps.close();
            con.close();
            if ( count == 1)
                return null;
            else
                return "Invalid Old Password!";
        } catch(Exception ex) {
            return ex.getMessage();
        }
    }
 
    public static String postIssue(String customerid, String title,String description) {
        try {
            Connection con = Database.getConnection();
            PreparedStatement ps = con.prepareStatement("insert into issues values(issueid.nextval,?,?,?,sysdate,'o',null,null)");
            ps.setString(1,customerid);
            ps.setString(2,title);
            ps.setString(3,description);
            ps.executeUpdate();
            return null;
        } catch(Exception ex) {
            return ex.getMessage();
        }
    }
    
    public static String postReply(String issueid,String customer,String title,String description) {
        try {
            Connection con = Database.getConnection();
            PreparedStatement ps = con.prepareStatement("insert into issueresponses values( irid.nextval,?,?,?,sysdate,?)");
            ps.setString(1,issueid);
            ps.setString(2,title);
            ps.setString(3,description);
            ps.setString(4,customer);
            ps.executeUpdate();
            return null;
        } catch(Exception ex) {
            return ex.getMessage();
        }
    }
    
    public static boolean register(String loginname,String password, String email,String serialno) {
        try {
            Connection con = Database.getConnection();
            PreparedStatement ps = con.prepareStatement("insert into customers values( customerid.nextval,?,?,sysdate,?,?)");
            ps.setString(1,loginname);
            ps.setString(2,password);
            ps.setString(3,email);
            ps.setString(4,serialno);
            ps.executeUpdate();
            return true;
        } catch(Exception ex) {
            System.out.println(ex.getMessage());
            return false;
        }
    }
}

/WEB-INF/classes/dao/Database.java
package dao;
import java.sql.Connection;
import oracle.jdbc.pool.OracleDataSource;

public class Database {
   static final String USERNAME="helpdesk";
   static final String PASSWORD="helpdesk";
   
   public static Connection getConnection() 
   {
       try {
            OracleDataSource ods = new OracleDataSource();
            ods.setDriverType("thin");
            ods.setServerName("localhost");
            ods.setNetworkProtocol("tcp");
            ods.setDatabaseName("xe");
            ods.setPortNumber(1521);
            ods.setUser(USERNAME);
            ods.setPassword( PASSWORD);
            Connection con = ods.getConnection();
            return con;
       }
       catch(Exception ex) {
           System.out.println(ex.getMessage());
           return null;
       }
   }
}

Note: Make sure Oracle's JDBC driver is added to project using libraries node in NetBeans project. Oracle JDBC driver is found in ojdbc14.jar file.

Logging

Take customer's loginname and password and check whether the given details are found in CUSTOMERS table. JSP login.jsp (given below) takes customer to home.jsp otherwise displays error message.
/login.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>

<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!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>Login Page</title>
        <link href="styles.css"  rel="stylesheet"/>
    </head>
    <body>
        <center>
        <f:view>
            <div class="head">OnLine Help Desk</div>
        <h:form>
            <h3>Login </h3>
            <table>
            <tr>
                <td align="right">Login Name : </td>
                <td align="left"> <h:inputText id="loginname" required="true" style="width:150px" value="#{CustomerBean.loginname}"  /> 
                <h:message id="m1" for="loginname"  />  
            </td>
            </tr>
            
            <tr>
                <td align="right">Password : </td>
                <td align="left"> <h:inputSecret id="password" required="true" style="width:150px"  value="#{CustomerBean.password}" /> 
                <h:message id="m2" for="password" /> </td>
            </tr>
            </table>
            <p/>
            <h:outputText  value="#{CustomerBean.message}"/>
            <p/>
            <h:commandButton value="Login" action="#{CustomerBean.login}" />
        </h:form>
        
        <a href="./all/forgotpassword.jsp">Forgot Password </a>
        <br/>
        <a href="./all/register.jsp">Register New Product </a>
            
        </f:view>
        </center>
    </body>
</html>

Home Page

This page is represented by home.jsp. It takes content from menu.jsp, myissues.jsp. All these files are given below.
/home.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>

<!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>Home Page</title>
        <link href="styles.css" rel="stylesheet"/>
    </head>
    <body>
    <table border="0" width="100%" height="600px">
        <tr>
            <td class="menu" valign="top" width="20%">
                <%@include file="menu.jsp"%> 
            </td>
            <td valign="top">
                <jsp:include page="myissues.jsp"/>           
            </td>
        </tr>
    </table>
</html>

/menu.jsp

<h4>Welcome ${sessionScope.loginname} </h4>

<a href="postissue.jsp">Post Issue</a>
<p/>
<a href="search.jsp">Search Issues </a>
<p/>
<a href="home.jsp">My Issues </a>
<p/>
<a href="changepassword.jsp">Change Password </a>
<p/>
<a href="logout.jsp">Logout</a>
<p/>

/myissues.jsp
<h2>Pending Issues</h1>
   
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<f:view>
    <h:form>
        <h:dataTable rendered="#{CustomerBean.issues.rowCount > 0}"  value="#{CustomerBean.issues}" var="issue" width="100%" border="1" >
                    <h:column>
                        <f:facet name="header"> <f:verbatim>Title</f:verbatim> </f:facet>
                         <h:outputText value="#{issue.issuetitle}"/>
                    </h:column>
                    <h:column>
                        <f:facet name="header"> <f:verbatim>PostedOn</f:verbatim> </f:facet>
                        <h:outputText value="#{issue.postedon}"/>
                    </h:column>
                    <h:column>
                        <f:facet name="header"><f:verbatim>Status</f:verbatim> </f:facet>
                        <h:outputText  value="#{issue.status == 'o' ? 'Open' : 'Closed'}"/>
                    </h:column>
                    
                    <h:column>
                       <f:facet name="header"><f:verbatim>&nbsp;</f:verbatim></f:facet>
                       <h:outputLink value="showissue.jsp">
                             <h:outputText value="Details"/>
                             <f:param name="issueid" value="#{issue.issueid}"/>
                       </h:outputLink>
                   </h:column>

       </h:dataTable>
    </h:form>
</f:view>

Posting an Issue

JSP postissue.jsp allows customer to post an issue. It uses PostIssueBean.java, which uses CustomerDAO.postIssue() method.
/postissue.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!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>Post Issue</title>
        <link href="styles.css" rel="stylesheet"/>
    </head>
    <body>
    <table border="0" width="100%" height="600px">
        <tr>
            <td class="menu" valign="top" width="20%">
                <%@include file="menu.jsp"%> 
            </td>
            <td valign="top">
                
                <h2>Post Issue </h2>
                <f:view>
                    <h:form>
                        <table>
                            <tr>
                                <td>Isseue Title :  </td>
                                <td> <h:inputText id="title" required="true" size="50" value="#{PostIssueBean.title}"  /> 
                                    <h:message id="m1" for="title" />  
                                </td>
                            </tr>
                            
                            <tr>
                                <td valign="top">Isseue Description :  </td>
                                <td> <h:inputTextarea  id="description" rows="5" cols="50" value="#{PostIssueBean.description}"  /> 
                                <h:message id="m2" for="description" />  
                            </tr>
                        </table>
                        <p/>
                        <h:commandButton value="Post Issue" actionListener="#{PostIssueBean.postIssue}" />
                        <p/>
                        <h:outputText  value="#{PostIssueBean.message}"/>
                    </h:form>
                </f:view>
            </td>
        </tr>
    </table>
</html>

/WEB-INF/classes/beans/PostIssueBean.java
package beans;

import dao.CustomerDAO;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.servlet.http.HttpSession;

public class PostIssueBean {
    private String title;
    private String description;
    private String message = "";
    public PostIssueBean() {
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
    
    public void postIssue(ActionEvent evt) {
       // post issue here        
       HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);   
       String status = CustomerDAO.postIssue( session.getAttribute("customerid").toString(),
                  title, description);
       if ( status == null)
           message="Issue Has Been Posted Successfully";
       else
           message = "Error -->" + status;
    }
}

Displaying Details of an Issue

You can click on Details link for an Issue in home page or in search page to get details of an issue. JSP showissue.jsp is used to display details of an issue. It also contains a link to post reply to an issue.
/showissue.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8" import="dao.*"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Issue Details</title>
        <link href="styles.css" rel="stylesheet"/>
    </head>
    <body>
        <table border="0" width="100%" height="600px">
            <tr>
                <td class="menu" valign="top" width="20%">
                    <%@include file="menu.jsp"%> 
                </td>
                <td valign="top">
                    
                    <h2>Issue Details</h2>
                    
                    <div class="issue">
                        <%
                        String issueid = request.getParameter("issueid");
                        Issue issue = IssueDAO.getDetails(issueid);
                        
                        if (issue == null)
                        return;
                        
                        session.setAttribute("title",issue.getTitle());  // used by postreply.jsp
                        session.setAttribute("issueid",issue.getIssueid());  // used by postreply.jsp
                        
                       
                        %>
                        <h4><%= issue.getTitle() %>  </h4>
                        <pre><%=issue.getDescription()%></pre>
                        Posted By : <%= issue.getCustomer()%> <br/>
                        Posted On : <%= issue.getPostedon()%>
                        <%
                        if ( issue.getStatus().equals("c") )  {
                               out.println("<br/>Closed On : " + issue.getResolvedon() + " By " +  issue.getSupportperson());
                        }
                        else
                            out.println("<p/><a href=postreply.jsp>Post Reply </a> <p/>");
                        
                        %>
                        
                    </div>
                    
                    <%
                     if ( issue.getReplies().size() == 0 )
                          return;
                    %>
                    
                    <h3>Replies </h3>
                    <%
                    for(Reply r : issue.getReplies()) {
                      out.println("<div class=reply>");
                      out.println( "<h4>" + r.getTitle() + "</h4>");
                      out.println("<pre>" + r.getDescription() + "</pre>");
                      out.println( "Posted on " +  r.getPostedon() + " by " + r.getPostedby());
                      out.println("</div>  <p/>");
                      
                    }
                    %>
                </td>
            </tr>
        </table>
        
        
        %>
    
    </body>
</html>

/WEB-INF/classes/dao/IssueDAO.java
package dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import javax.servlet.jsp.jstl.sql.Result;
import javax.servlet.jsp.jstl.sql.ResultSupport;

public class IssueDAO {
     public static Issue getDetails(String issueid) {
        Connection con=null;
        PreparedStatement ps =null;
        try {
            con = Database.getConnection();
            ps = con.prepareStatement("select i.*, loginname from issues i, customers c where issueid = ? and c.customerid = i.customerid");
            ps.setString(1,issueid);
            ResultSet rs = ps.executeQuery();
            if (! rs.next() ) return null;
            Issue issue = new Issue();
            issue.setIssueid(issueid);
            issue.setCustomerid( rs.getString("customerid"));
            issue.setCustomer( rs.getString("loginname"));
            issue.setTitle( rs.getString("issuetitle"));
            issue.setDescription( rs.getString("issuedescription"));
            issue.setPostedon( rs.getString("postedon"));
            issue.setStatus( rs.getString("status"));
            issue.setResolvedon( rs.getString("resolvedon"));
            issue.setSupportperson( rs.getString("supportperson"));
            rs.close();
            // get replies
            ps = con.prepareStatement("select * from issueresponses where issueid = ?");
            ps.setString(1,issueid);
            ArrayList<Reply> replies = new ArrayList<Reply>();
            rs = ps.executeQuery();
            while ( rs.next()){
                Reply r = new Reply();
                r.setTitle( rs.getString("irtitle"));
                r.setDescription( rs.getString("irdescription"));
                r.setPostedon( rs.getString("postedon"));
                r.setPostedby( rs.getString("postedby"));
                replies.add(r);
            }
            rs.close();
            issue.setReplies(replies);
            con.close();
            return issue;
        } catch(Exception ex) {
            System.out.println(ex.getMessage());
            return null;
        }
        finally {
             try {
                ps.close();
                con.close();
             }
             catch(Exception ex) {}
        }
     }
     
     public static Result search(String pattern) {
        Connection con=null;
        PreparedStatement ps =null;
        try {
            con = Database.getConnection();
            ps = con.prepareStatement("select * from issues where upper(issuetitle) like ?  order by issueid desc");
            ps.setString(1,"%" + pattern.toUpperCase() + "%");
            ResultSet rs = ps.executeQuery();
            return ResultSupport.toResult(rs);
        } catch(Exception ex) {
            System.out.println(ex.getMessage());
            return null;
        }
        finally {
             try {
                ps.close();
                con.close();
             }
             catch(Exception ex) {}
        }
     } // search
}

/WEB-INF/classes/dao/Issue.java
package dao;

import java.util.ArrayList;
import java.util.List;


public class Issue {
    private String issueid, customerid, customer, 
            title, description, postedon, status,
            resolvedon, supportperson;
    
    private ArrayList<Reply> replies;
    
    public String getIssueid() {
        return issueid;
    }
    
    public void setIssueid(String issueid) {
        this.issueid = issueid;
    }
    
    public String getCustomerid() {
        return customerid;
    }
    
    public void setCustomerid(String customerid) {
        this.customerid = customerid;
    }
    
    public String getTitle() {
        return title;
    }
    
    public void setTitle(String title) {
        this.title = title;
    }
    
    public String getDescription() {
        return description;
    }
    
    public void setDescription(String description) {
        this.description = description;
    }
    
    public String getPostedon() {
        return postedon;
    }
    
    public void setPostedon(String postedon) {
        this.postedon = postedon;
    }
    
    public String getStatus() {
        return status;
    }
    
    public void setStatus(String status) {
        this.status = status;
    }
    
    public String getResolvedon() {
        return resolvedon;
    }
    
    public void setResolvedon(String resolvedon) {
        this.resolvedon = resolvedon;
    }
    
    public String getSupportperson() {
        return supportperson;
    }
    
    public void setSupportperson(String supportperson) {
        this.supportperson = supportperson;
    }
    
    public ArrayList<Reply> getReplies() {
        return replies;
    }
    
    public void setReplies(ArrayList<Reply> replies) {
        this.replies = replies;
    }

    public String getCustomer() {
        return customer;
    }

    public void setCustomer(String customer) {
        this.customer = customer;
    }
    
    
}

/WEB-INF/classes/dao/Reply.java

package dao;

public class Reply {
    private String issueid, title,description, 
            postedon, postedby;

    public String getIssueid() {
        return issueid;
    }

    public void setIssueid(String issueid) {
        this.issueid = issueid;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getPostedon() {
        return postedon;
    }

    public void setPostedon(String postedon) {
        this.postedon = postedon;
    }

    public String getPostedby() {
        return postedby;
    }

    public void setPostedby(String postedby) {
        this.postedby = postedby;
    }
    
}

Posting a reply

From the details of an issue, customer can post a reply to an issue. JSP postreply.jsp is used to post reply. At the time of posting a reply customer provides title and description.
/postreply.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!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>Post Reply</title>
        <link href="styles.css" rel="stylesheet"/>
    </head>
    <body>
    <table border="0" width="100%" height="600px">
        <tr>
            <td class="menu" valign="top" width="20%">
                <%@include file="menu.jsp"%> 
            </td>
            <td valign="top">
                <h2>Post Reply</h2>
                <f:view>
                    <h:form>
                        <table>
                            <tr>
                                <td>Reply Title :  </td>
                                <td> <h:inputText id="title" required="true"  size="50" value="#{PostReplyBean.title}"  /> 
                                    <h:message id="m1" for="title" />  
                                </td>
                            </tr>
                            
                            <tr>
                                <td valign="top">Reply Description :  </td>
                                <td> <h:inputTextarea  id="description" rows="5" cols="50" value="#{PostReplyBean.description}"  /> 
                                <h:message id="m2" for="description" />  
                            </tr>
                        </table>
                        <p/>
                        <h:commandButton value="Post Reply" actionListener="#{PostReplyBean.postReply}" />
                        <p/>
                        <h:outputText  value="#{PostReplyBean.message}"/>
                    </h:form>
                </f:view>
            </td>
        </tr>
    </table>
</html>

/WEB-INF/classes/beans/PostReplyBean.java
package beans;

import dao.CustomerDAO;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class PostReplyBean {
    private String issueid, title, description, message, customer;
    public PostReplyBean() {
        HttpSession session  = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
        title = "Re: " + (String) session.getAttribute("title");
        customer = (String) session.getAttribute("loginname");
        issueid = (String) session.getAttribute("issueid");
    }
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
    
    public String getMessage() {
        return message;
    }
    
    public void setMessage(String message) {
        this.message = message;
    }
    
    public void postReply(ActionEvent evt) {
       String status = CustomerDAO.postReply(issueid,customer,title, description);
       if ( status == null)
           setMessage("Reply Has Been Posted Successfully");
       else
           setMessage("Error -->" + status);
    }

}

Searching for Issues

JSP search.jsp is used to search for issues based on the string. It looks for issues that contain the given string in the title.
/search.jsp
<!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>Home Page</title>
    <link href="styles.css" rel="stylesheet"/>
</head>
<body>
<table border="0" width="100%" height="600px">
<tr>
<td class="menu" valign="top" width="20%">
    <%@include file="menu.jsp"%> 
</td>
<td valign="top">
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>    
<f:view>
<h:form>
    <h2>Search Issues</h1>
    Search <h:inputText id="pattern" value="#{SearchBean.pattern}"/>
    <h:commandButton  value="Search"/>
    <p/>
    <h:dataTable rendered="#{SearchBean.issues.rowCount > 0}" value="#{SearchBean.issues}" var="issue" width="100%" border="1">
        <h:column>
            <f:facet name="header"> <f:verbatim>Title</f:verbatim> </f:facet>
            <h:outputText value="#{issue.issuetitle}"/>
        </h:column>
        <h:column>
            <f:facet name="header"> <f:verbatim>PostedOn</f:verbatim> </f:facet>
            <h:outputText value="#{issue.postedon}"/>
        </h:column>
        <h:column>
            <f:facet name="header"><f:verbatim>Status</f:verbatim> </f:facet>
            <h:outputText  value="#{issue.status == 'o' ? 'Open' : 'Closed'}"/>
        </h:column>
        
        <h:column>
            <f:facet name="header"><f:verbatim>&nbsp;</f:verbatim></f:facet>
            <h:outputLink value="showissue.jsp">
                <h:outputText value="Details"/>
                <f:param name="issueid" value="#{issue.issueid}"/>
            </h:outputLink>
        </h:column>
        
    </h:dataTable>
</h:form>
</f:view>

</td>
</tr>
</table>

</body>
</html>

Changing password

JSP changepassword.jsp is used to change password. It uses changePassword() method of CustomerDAO.
/changepassword.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!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>Change Password</title>
        <link href="styles.css" rel="stylesheet"/>
    </head>
    <body>
    <table border="0" width="100%" height="600px">
        <tr>
            <td class="menu" valign="top" width="20%">
                <%@include file="menu.jsp"%> 
            </td>
            <td valign="top">
                <h2>Change Password</h2>
                <f:view>
                    <h:form>
                        <table>
                            <tr>
                                <td>Old Password :  </td>
                                <td><h:inputSecret id="oldpassword" required="true" size="20" value="#{CustomerBean.oldpassword}"/> 
                                <h:message id="m1" for="oldpassword" />  
                                </td>
                            </tr>
                            
                            <tr>
                                <td>New Password :  </td>
                                <td> <h:inputSecret id="password" required="true" size="20" value="#{CustomerBean.password}"  /> 
                                <h:message id="m1" for="password" />  
                                </td>
                            </tr>
                            
                            <tr>
                                <td>Confirm Password :  </td>
                                <td> <h:inputSecret id="confirmpassword" required="true" size="20" value="#{CustomerBean.confirmpassword}"  /> 
                                <h:message id="m1" for="confirmpwd" />  
                                </td>
                            </tr>
                        </table>
                        <p/>
                        <h:commandButton value="Change Password" actionListener="#{CustomerBean.changePassword}" />
                        <p/>
                        <h:outputText  value="#{CustomerBean.message}"/>
                    </h:form>
                </f:view>
            </td>
        </tr>
    </table>
</html>

Recovering password

JSP forgotpassword.jsp takes email address and then sends password of the customer with that email address as a mail. 
/all/forgotpassword.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<!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>Forgot Password</title>
        <link href="../styles.css"  rel="stylesheet"/>
    </head>
    <body>
        <center>
            <f:view>
                <div class="head">OnLine Help Desk</div>
                <h:form>
                    <h3>Forgot Password</h3>
                    Email Address : <h:inputText id="email" required="true" size="20" value="#{CustomerBean.email}"  /> 
                     <h:message id="m4" for="email" /> </td>
                    <p/>
                    <h:commandButton value="Submit" actionListener="#{CustomerBean.recoverPassword}" />
                    <p/>
                    <h4> <h:outputText escape="false"  value="#{CustomerBean.message}"/> </h4>
                </h:form>
            </f:view>
        </center>
    </body>
</html>

Logout

JSP logout.jsp is used to terminate session and transfer control to login.jsp.
/logout.jsp
<%

  session.invalidate();
  response.sendRedirect("login.jsp");
%>  

Authentication Filter

A filter is used to ensure only authenticated user can access pages in root folder. But pages in all folder, styles.css, and login.jsp can be accessed even by anonymous users.
/WEB-INF/classes/filter/AuthFilter.java
package filter;
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class AuthFilter implements Filter {
    private FilterConfig filterConfig = null;
    public AuthFilter() {
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {
      try {

            // check whether session variable is set 
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse res = (HttpServletResponse) response;
            HttpSession ses = req.getSession(false);
            System.out.println( req.getRequestURI());
            if ( req.getRequestURI().indexOf("/all/") >= 0  || 
                 req.getRequestURI().indexOf("/styles.css") >= 0  ||
                 req.getRequestURI().indexOf("/login.jsp") >=0 )  {
                 chain.doFilter(request, response);
            }
            else
              if (ses == null || ses.getAttribute("loginname") == null) {
                    res.sendRedirect(req.getContextPath() + "/faces/login.jsp");
              }
              else
                  chain.doFilter(request, response);
      }
     catch(Throwable t) {
         System.out.println( t.getMessage());
     }
    }
    
    public FilterConfig getFilterConfig() {
        return (this.filterConfig);
    }
    public void setFilterConfig(FilterConfig filterConfig) {
        this.filterConfig = filterConfig;
    }
    public void destroy() {
    }
    public void init(FilterConfig filterConfig) {
        this.filterConfig = filterConfig;
    }
}

Other important files

This project also contains other files like faces-config.xml,styles.css and messages.properties files.
/WEB-INF/faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<!-- =========== FULL CONFIGURATION FILE ================================== -->
<faces-config xmlns="http://java.sun.com/JSF/Configuration">
  <managed-bean>
    <managed-bean-name>CustomerBean</managed-bean-name>
    <managed-bean-class>beans.CustomerBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>
  <managed-bean>
    <managed-bean-name>PostIssueBean</managed-bean-name>
    <managed-bean-class>beans.PostIssueBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>
  <managed-bean>
      <managed-bean-name>PostReplyBean</managed-bean-name>
      <managed-bean-class>beans.PostReplyBean</managed-bean-class>
      <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>
  <managed-bean>
      <managed-bean-name>SearchBean</managed-bean-name>
      <managed-bean-class>beans.SearchBean</managed-bean-class>
      <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>
  <application>
      <message-bundle>messages</message-bundle>
  </application>
  <navigation-rule>
    <description>
            
        </description>
    <from-view-id>/login.jsp</from-view-id>
    <navigation-case>
      <from-outcome>success</from-outcome>
      <to-view-id>/home.jsp</to-view-id>
    </navigation-case>
  </navigation-rule>
</faces-config>

/styles.css
div.head {
   background-color: navy;
   color: orange;
   font-family: arial;
   font-size: 30pt;
   font-weight: bold;
   letter-spacing: 5px
}

div.issue {
   background-color: #ffcc00;
   border-bottom-style: solid;
   border-bottom-width: 1px;
   border-left-style: solid;
   border-left-width: 1px;
   border-right-style: solid;
   border-right-width: 1px;
   border-top-style: solid;
   border-top-width: 1px;
   font-family: Verdana,Arial,Helvetica,sans-serif;
   font-size: 10pt
}

div.reply {
   background-color: #ffff99;
   border-bottom-style: solid;
   border-bottom-width: 1px;
   border-left-style: solid;
   border-left-width: 1px;
   border-right-style: solid;
   border-right-width: 1px;
   border-top-style: solid;
   border-top-width: 1px;
   font-family: Verdana,Arial,Helvetica,sans-serif;
   font-size: 10pt
}

body {
   font-family: Verdana,Arial,Helvetica,sans-serif;
   font-size: 10pt;
   margin:0px;
  
}

td.menu {
   background-color: wheat
}

/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <context-param>
        <param-name>com.sun.faces.verifyObjects</param-name>
        <param-value>false</param-value>
    </context-param>
    <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>
    <filter>
        <filter-name>AuthFilter</filter-name>
        <filter-class>filter.AuthFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>AuthFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
	<welcome-file>
            index.jsp
        </welcome-file>
    </welcome-file-list>
</web-app>

/WEB-INF/classes/messages.properties
# Sample ResourceBundle properties file
javax.faces.component.UIInput.REQUIRED=Value Required!

Steps to download and use this application

You can download the entire helpdesk project as NetBeans project. Then follow the steps given below to open the project and add required components.
  1. Unzip helpdesk.zip using WinZip or WinRar. It creates a folder called helpdesk.
  2. Start NetBeans, select File->Open Project and select helpdesk as the folder to open the project.
  3. Add JSF, JSTL libraries using Add Library option of popup menu invoked using right click on the project.
  4. Add ojdbc14.jar , activation.jar and mail.jar to project libraries.
  5. Build project and run login.jsp