Namecard Web Application

This chapter describes the difference between pure Java applications and web applications by converting the JDBC Namecard example into a web application.

Preparations for converting the JDBC Namecard example to a web application

1. Copy the Oracle JDBC driver to CATALINA_HOME/lib.

The JDBC driver must be in CATALINA_HOME/lib instead of WEB-INF/lib for your web application. Copying the JDBC driver files to to CATALINA_HOME/lib for each web application can cause memory leaks. So, there should be no JDBC driver in WEB-INF/lib for your web application.

2. Create directories for the Namecard web application.

If you set C:/www/namecard to be the top-level directory of your namecard web application, you must create the following subdirectories under C:/www/namecard.

  • WEB-INF
  • WEB-INF/classes
  • WEB-INF/lib

3. Create a web.xml file in the WEB-INF directory.

Copy CATALINA_HOME/webapps/ROOT/WEB-INF/web.xml and paste it into C:/www/namecard/WEB-INF/. After copying, open the file C:/www/namecard/WEB-INF/web.xml and delete everything inside the web-app element as below.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0">

</web-app>

4. Create a Tomcat context file named namecard.xml.

Create a namecard.xml file in the CATALINA_HOME/conf/Catalina/localhost directory.

<?xml version="1.0" encoding="UTF-8"?>
<Context
  docBase="C:/www/namecard"
  reloadable="true">
</Context>

Test 1

Copy the namecard and NamecardDao bytecode that you have practiced in Namecard into WEB-INF/classes.

C:/www/namecard/WEB-INF/classes
                           └── net
                               └── java_school
                                       └── namecard
					      ├── Namecard.class
                                              └── NamecardDao.java	

Create all the JSP files in the DocumentBase, C:/www/namecard. This practice is best done with a regular editor, not with Eclipse.

/list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="net.java_school.namecard.*" %>
<%@ page import="java.util.*" %>    
<!DOCTYPE html>
<%
NamecardDao dao = new NamecardDao();
ArrayList<Namecard> list = dao.selectAll();
%>
<html>
<head>
<meta charset="UTF-8" />
<title>List All Namecard</title>
</head>
<body>
<table border="1">
<tr>
  <td>NO</td>
  <td>NAME</td>
  <td>MOBILE</td>
  <td>EMAIL</td>
  <td>COMPANY</td>
</tr>
<%
int size = list.size();
for(int i = 0;i < size;i++) {
  Namecard card = list.get(i);
%>	
<tr>
  <td><%=card.getNo() %></td>
  <td><%=card.getName() %></td>
  <td><%=card.getMobile() %></td>
  <td><%=card.getEmail() %></td>
  <td><%=card.getCompany() %></td>
</tr>
<%
}
%>	
</table>
<p>
<input type="button" value="추가" onclick="location.href='write.jsp'" />
</p>
</body>
</html>

After restarting Tomcat, Visit http://localhost:8080/namecard/list.jsp for testing.

Test 2

You can let users not access java source files directly form their web browser by placing them under /WEB-INF. Let's determine /WEB-INF/src as the java source directory. Copy the src directory of the namecard JDBC example and paste and paste them into /WEB-INF. At the command prompt, go to C:/www/namecad/WEB-INF/src/net/java_school/namecard and compile by doing the following:

javac -d C:/www/namecard/WEB-INF/classes *.java

(If the NamecardDao class uses the connection pool, you have to compile first them)

Visit http://localhost:8080/namecard/list.jsp for testing.

Test 3

Test 3 shows you how to manage your sources in Eclipse. Run Eclipse and select your workspace as C:/www.
select workspace as C:\www
In the Java perspective, select File - New - Java Project.
Create a Java project named namecard.
(Most books and sites illustrate how to create a Dynamic Web Project of the Java EE perspective. But, to focus on Servlets and JSPs rather than Eclipse, this way is better)
Create a Java Project with the Java perspective selected.
We are writing a web application, not a pure Java application, so do not use the directories src and bin that Eclipse sets by default. With the mouse selected for the project, right-click. Select Build Path, Configure Build Path. In the Source tab, specify WEB-INF/src as the Source folder and WEB-INF/classes as the Output folder.
the Source Folder and Output Folder for Namecard Web Application
Visit http://localhost:8080/namecard/list.jsp for testing. If the test succeeds, create a JSP file in C:/www/namecard to register the namecard. First, change the Eclipse JSP template charset to UTF-8. In Eclipse, select Windows - Preferences - Web - JSP Files. And then, select UTF-8 in the Encoding box, and click Apply.
JSP charset to  UTF-8
The highlighted part of the write.jsp source below is what you need to type directly.

/write.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC>
<html>
<head>
<meta charset="UTF-8" />
<title>Add Namecard</title>
</head>
<body>
<h1>Add Namecard</h1>
<form action="write_proc.jsp" method="post">
NAME : <input type="text" name="name" /><br />
MOBILE : <input type="text" name="mobile" /><br />
EMAIL : <input type="text" name="email" /><br />
COMPANY : <input type="text" name="company" /><br />
<input type="submit" value="Confirm" />
<input type="button" value="Cancel" onclick="location.href='list.jsp'" />
</form>
</body>
</html>

Next, create a write_proc.jsp. This page adds the information received from write.jsp to the table. You will have to type in the highlighted part of the source below.

/write_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<%@ page import="net.java_school.namecard.*" %>
<!DOCTYPE html>
<%
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
String mobile = request.getParameter("mobile");
String email = request.getParameter("email");
String company = request.getParameter("company");
Namecard namecard = new Namecard(name,mobile,email,company);
NamecardDao dao = new NamecardDao();
dao.insert(namecard);
%>
<html>
<head>
<meta charset="UTF-8" />
<title>Add Namecard</title>
</head>
<body>
New namecard added.<a href="list.jsp">All Namecards</a>
</body>
</html>

Visit http://localhost:8080/namecard/list.jsp and test the registration.

Let's implement the deletion function. First, edit the list.jsp by referring to the code snippet below.

/list.jsp
.. omit ..

  <td>NO</td>
  <td>NAMe</td>
  <td>MOBILE</td>
  <td>EMAIL</td>
  <td>COMPANY</td>
  <td>Manage</td>

.. omit ..

  <td><%=card.getNo() %></td>
  <td><%=card.getName() %></td>
  <td><%=card.getMobile() %></td>
  <td><%=card.getEmail() %></td>
  <td><%=card.getCompany() %></td>
  <td><a href="delete.jsp?no=<%=card.getNo() %>">Del</a></td>

.. omit ..	

Create delete.jsp. This JSP receives the primary key of the namecard from the list.jsp and performs deletion. You will have to type in the highlighted part of the source below.

/delete.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<%@ page import="net.java_school.namecard.*" %>
<!DOCTYPE html>
<%
int no = Integer.parseInt(request.getParameter("no"));
NamecardDao dao = new NamecardDao();
dao.delete(no);
%>
<html>
<head>
<meta charset="UTF-8" />
<title>Delete Namecard</title>
</head>
<body>
The namecard has been deleted.<a href="list.jsp">All Namecards</a>
</body>
</html>

Visit http://localhost:8080/namecard/list.jsp to test the deletion of namecards.

Next, let's implement namecard modification. Below is the method for modifying a namecard.

NamecardDao.java
public void update(Namecard card) {
  String sql = "UPDATE namecard " +
      "SET name = ? " +
      ",mobile = ? " +
      ",email = ? " +
      ",company = ? " +
      "WHERE no = ?";
			
  Connection con = null;
  PreparedStatement pstmt = null;
	
  try {
    con = getConnection();
    pstmt = con.prepareStatement(sql);
    pstmt.setString(1, card.getName());
    pstmt.setString(2, card.getMobile());
    pstmt.setString(3, card.getEmail());
    pstmt.setString(4, card.getCompany());
    pstmt.setInt(5, card.getNo());
    pstmt.executeUpdate();
		
//.. omit ..

Modify the list.jsp as shown below.

/list.jsp
<td>
  <a href="delete.jsp?no=<%=card.getNo() %>">Del</a>
  <a href="modify.jsp?no=<%=card.getNo() %>">Modify</a>
</td>

Create modify.jsp.

/modify.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<%@ page import="net.java_school.namecard.*" %>
<!DOCTYPE html>
<%
int no = Integer.parseInt(request.getParameter("no"));
NamecardDao dao = new NamecardDao();
Namecard card = dao.selectOne(no);
%>
<html>
<head>
<meta charset="UTF-8" />
<title>Modify a Namecard</title>
</head>
<body>
<h1>Modify a Namecard</h1>
<form action="modify_proc.jsp" method="post">
<input type="hidden" name="no" value="<%=no %>" />
NAME : <input type="text" name="name" value="<%=card.getName() %>" /><br />
MOBILE : <input type="text" name="mobile" value="<%=card.getMobile() %>" /><br />
EMAIL : <input type="text" name="email" value="<%=card.getEmail() %>" /><br />
COMPANY : <input type="text" name="company" value="<%=card.getCompany() %>" /><br />
<input type="submit" value="Confirm" />
<input type="button" value="Cancel" onclick="location.href='list.jsp'" />
</form>
</body>
</html>

<input type="hidden" name="no" value="<%=no %>" />
The above code must be in the form tag.

Create modify_proc.jsp. This JSP modifies a namecard using information sent from modify.jsp.

modify_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<%@ page import="net.java_school.namecard.*" %>
<!DOCTYPE html>
<%
request.setCharacterEncoding("UTF-8");
int no = Integer.parseInt(request.getParameter("no"));
String name = request.getParameter("name");
String mobile = request.getParameter("mobile");
String email = request.getParameter("email");
String company = request.getParameter("company");
Namecard card = new Namecard();
card.setNo(no);
card.setName(name);
card.setMobile(mobile);
card.setEmail(email);
card.setCompany(company);
NamecardDao dao = new NamecardDao();
dao.update(card);
%>
<html>
<head>
<meta charset="UTF-8" />
<title>Modify a Namecard</title>
</head>
<body>
The namecard has been modified. <a href="list.jsp">All Namecards</a>
</body>
</html>

Visit http://localhost:8080/namecard/list.jsp, and modify a namecard.

Let's add a search function to list.jsp. Open list.jsp and add the following before </body>.

/list.jsp
<form action="list.jsp" method="post">
  <input type="text" name="keyword" />
  <input type="submit" value="Search" />
</form>

Add the selectByKeyword (String keyword) method to NamecardDao.java.

NamecardDao.java
public ArrayList<Namecard> selectByKeyword(String keyword) {
  keyword = "%" + keyword + "%";
  ArrayList<Namecard> matched = new ArrayList<Namecard>();
		
  String sql ="SELECT no,name,mobile,email,company " + 
      "FROM namecard " +
      "WHERE name LIKE ? " +
        "OR mobile LIKE ? " +
        "OR email LIKE ? " + 
        "OR company LIKE ? " +
      "ORDER BY no DESC";
			
  Connection con = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
	
  try {
    con = getConnection();
    pstmt = con.prepareStatement(sql);
    pstmt.setString(1, keyword);
    pstmt.setString(2, keyword);
    pstmt.setString(3, keyword);
    pstmt.setString(4, keyword);
    rs = pstmt.executeQuery();
		
    while(rs.next()) {
      int no = rs.getInt("no");
      String sname = rs.getString("name");
      String mobile = rs.getString("mobile");
      String email = rs.getString("email");
      String company = rs.getString("company");
      Namecard namecard = new Namecard(no, name, mobile, email, company);
      matched.add(namecard);
    }
  } catch (SQLException e) {
    e.printStackTrace();
    System.out.println(sql);
  } finally {
    close(rs,pstmt,con);
  }
	
  return matched;

}

There is a bug that searches for null on the list page. The first time you visit list.jsp using the web browser's address bar, the keyword is null. And if you did not put any value in the search field in list.jsp and clicked the search button, the keyword is "" (whitespace).

Open list.jsp and modify it as shown below.

/list.jsp
<%
//Commented out the following code.
//NamecardDao dao = new NamecardDao();
//ArrayList<Namecard> list = dao.selectAll();

request.setCharacterEncoding("UTF-8");
String keyword = request.getParameter("keyword");

NamecardDao dao = new NamecardDao();
ArrayList<Namecard> list = null;

if (keyword == null) {
  keyword = "";
}
if (keyword.equals("")) {
  list = dao.selectAll();
} else {
  list = dao.selectByKeyword(keyword);
}
%>

Visit http://localhost:8080/namecard/list.jsp for testing.

References