Namecard Web Application

Before studying a Web application, let's make the JDBC Namecard example as a Web application. In this Chapter, You will be able to understand the difference between pure Java applications and web applications.

Preparations for changing 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 for special reasons.1 There should be no JDBC driver in WEB-INF/lib for your web application. Copy the ojdbc6.jar file to CATALINA_HOME/lib.

2. Create a directory structure for Namecard web applications.

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

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

3. Create the 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.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
 Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0"
  metadata-complete="true">

</web-app>

4. Create a context file named namecard.xml.

Create a namecard.xml file as shown below and move it to CATALINA_HOME/conf/Catalina/localhost.

<?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.class
						

Create all the JSP files in the DocumentBase C: / www / namecard. Make list.jsp as follows. (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 http-equiv="Content-Type" content="text/html; 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.

Test 2

In Test 1, you can place the Java source in a location that is completely independent of where the web application is located. However, if you manage the source in this way, you can forget the location of the source, or you can erase the source by mistake. Test 2 is a test that moves the source into the area of the web application and compiles the source. First, you need to decide where to put the Java source, If you place the source under WEB-INF, you will not be able to access the source directly from your web browser, so we will set the source directory to WEB-INF/src. Copy the business card management src directory from JDBC and paste it 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:2

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

Go to http://localhost:8080/namecard/list.jsp and test.

Test 3

Test 3 shows you how to manage your sources in Eclipse. Run Eclipse. Select your workspace as C:/www.
Select workspace as C:/www.
In the Java perspective, select File - New - Java Project. Create a Java project with the name namecard.3 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, select WEB-INF/src as the Source folder. Select WEB-INF/classes as the Output folder.
the Source Folder and Output Folder for Namecard Web Application
Now if you modify the source in Eclipse, you will have bytecode in WEB-INF/classes without having to compile it separately. Go to http://localhost:8080/namecard/list.jsp and test. 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, 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 "-//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>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 file. This page adds a business card using information received from write.jsp. 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 PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
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 http-equiv="Content-Type" content="text/html; 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 business card registration. Let's implement the business card deletion function. First, edit the list.jsp as follows.

/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 ..	

Next, create delete.jsp. delete.jsp receives the value corresponding to the primary key of the namecard in 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 PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
int no = Integer.parseInt(request.getParameter("no"));
NamecardDao dao = new NamecardDao();
dao.delete(no);
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; 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 a method to modify a namecard in NamecardDao.java.

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 file 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>

Next, create a modify.jsp file.

/modify.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="net.java_school.namecard.*" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
int no = Integer.parseInt(request.getParameter("no"));
NamecardDao dao = new NamecardDao();
Namecard card = dao.selectOne(no);
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; 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 the modify_proc.jsp file. This JSP modifies the 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 PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
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 http-equiv="Content-Type" content="text/html; 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 edit the 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;
}

If you visit list.jsp to test your search, there is a bug that searches for null. The first time you visit list.jsp from 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);
}
%>

If you have done so, go to http://localhost:8080/namecard/list.jsp and test.

Comments
  1. Copying the JDBC driver files to WEB-INF/lib for each web application can cause memory leaks.
  2. If the NamecardDao class uses a connection pool, you must first compile the connection pool-related classes.
  3. In contrast, most books and sites illustrate how to create a Dynamic Web Project in the Java EE perspective. To focus on servlets/JSPs rather than Eclipse, the settings presented here are better.
References