Chapter 14: Developing a Complete Struts Application

 < Day Day Up > 



In this chapter we develop a complete Struts application. We begin by defining each component of the application and then continue with the actual development and implementation of the application. The goal of this chapter is to tie the majority of our previous discussions together through the use of an example that leverages the components most often used in a Struts application. We also use MySQL as our preferred database for the application.

The Employees Application Definition

Our example application, named employees, acts as an employee directory service that will allow a user to list, add, edit, and delete employees stored in the company database. In this section we will define all of the components of our employees application including the Models, the Views, and the Controller.

Preparing the employees Application

Before we can begin developing our example, we must perform the basic steps of preparing the application. These steps are the minimum number of steps that must be completed when defining any Struts application.

  1. Create a new Web application, named employees, using the directory structure described in Chapter 1, "Introducing the Jakarta-Struts Project and its Supporting Components."

  2. Copy the Jar files, extracted from the Jakarta Struts archive, to the <CATALINA_HOME>/webapps/employees/WEB-INF/lib directory.

  3. Copy the MySql JDBC driver file, used in Chapter 11, to the <CATALINA_HOME>/webapps/employees/WEB-INF/lib directory.

  4. Copy the Commons DBCP Jar files, also used in Chapter 11, to the <CATALINA_HOME>/webapps/employees/WEB-INF/lib directory.

  5. Create an empty struts-config.xml file and copy it to the <CATALINA_HOME>/webapps/employees/WEB-INF/ directory. Listing 14.1 contains an example of an empty struts-config.xml file:

    Listing 14.1: An Empty struts-config.xml File.

    start example
     <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config   PUBLIC   "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"   "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config> </struts-config> 
    end example

  6. Create a web.xml file with a Servlet definition for the ActionServlet, and copy this file to the <CATALINA_HOME>/webapps/employees/WEB-INF/ directory. Listing 14.2 contains our initial web.xml file. This file will evolve as we add additional components to our employees application.

    Listing 14.2: Default web.xml File.

    start example
     <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app   PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"   "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app>   <servlet>     <servlet-name>action</servlet-name>     <servlet-class>       org.apache.struts.action.ActionServlet     </servlet-class>     <init-param>       <param-name>debug</param-name>       <param-value>5</param-value>     </init-param>     <init-param>       <param-name>config</param-name>       <param-value>/WEB-INF/struts-config.xml</param-value>     </init-param>     <load-on-startup>1</load-on-startup>   </servlet>   <servlet-mapping>     <servlet-name>action</servlet-name>     <url-pattern>*.do</url-pattern>   </servlet-mapping> </web-app> 
    end example

  7. Create an English application resource bundle and copy it to the <CATALINA_HOME>/webapps/employees/WEB-INF/classes directory. In our examples we will have resource bundles for the English language only. Listing 14.3 contains the resource bundle for our application.

    Listing 14.3: The English Resource Bundle ApplicationResources.properties.

    start example
     app.title=Wrox Employee Database app.username=User Name app.password=Password app.name=Name app.phone=Phone app.email=Email app.role=Role app.department=Department app.administration=Administration app.network=Network app.sales=Sales app.engineering=Engineering app.manager=Manager app.employee=Employee errors.login.unknown=<li>Unknown User : {0}</li> errors.login.required=<li>You must login before proceeding</li> errors.username.required=<li>A Username is Required</li> errors.password.required=<li>A Password is Required</li> errors.name.required=<li>A Name is Required</li> errors.phone.required=<li>A Phone is Required</li> errors.email.required=<li>An Email Address is Required</li> errors.roleid.required=<li>A Role is Required</li> errors.depid.required=<li>A Department is Required</li> errors.database.error=<li>A Database error occurred : {0}</li> errors.header=<h3><font color="red">Error List</font></h3><ul> errors.footer=</ul><hr> 
    end example

  8. Add this resource bundle to the employees application. The modification requires inserting an additional <init-param> to the previously defined <servlet> element. Source 14.4a contains the application's new web.xml, with this modification.

    start sidebar

    We discussed creating new resource bundles in Chapter 9, "Internationalizing Your Struts Applications."

    end sidebar

    Listing 14.4a: The web.xml File after Adding the Application Resource Bundle.

    start example
     <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app   PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"   "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app>   <servlet>     <servlet-name>action</servlet-name>     <servlet-class>       org.apache.struts.action.ActionServlet     </servlet-class>     <init-param>       <param-name>debug</param-name>       <param-value>5</param-value>     </init-param>     <init-param>       <param-name>config</param-name>       <param-value>/WEB-INF/struts-config.xml</param-value>     </init-param>     <init-param>       <param-name>application</param-name>       <param-value>ApplicationResources</param-value>     </init-param>     <load-on-startup>1</load-on-startup>   </servlet>   <servlet-mapping>     <servlet-name>action</servlet-name>     <url-pattern>*.do</url-pattern>   </servlet-mapping> </web-app> 
    end example

  9. We next need to add the tag libraries that we intend to leverage in our application development. This step is an optional step and is only required when your application leverages one or more custom tag libraries. The libraries that we will be using are the HTML, Logic, and Bean libraries. To add these libraries, you must add a <taglib> entry describing each library to the <CATALINA_HOME>/webapps/ employees/WEB-INF/web.xml file. Listing 14.4b contains the application's modified web.xml, with the addition of these libraries.

    Listing 14.4b: The web.xml File after Adding the HTML, Logic, and Bean Tag Libraries.

    start example
     <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app   PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"   "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app>   <servlet>     <servlet-name>action</servlet-name>     <servlet-class>       org.apache.struts.action.ActionServlet     </servlet-class>     <init-param>       <param-name>debug</param-name>       <param-value>5</param-value>     </init-param>     <init-param>       <param-name>config</param-name>       <param-value>/WEB-INF/struts-config.xml</param-value>     </init-param>     <init-param>       <param-name>application</param-name>       <param-value>ApplicationResources</param-value>     </init-param>     <load-on-startup>1</load-on-startup>    </servlet>   <servlet-mapping>     <servlet-name>action</servlet-name>     <url-pattern>*.do</url-pattern>   </servlet-mapping>   <taglib>     <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>     <taglib-location>/WEB-INF/struts-html.tld</taglib-location>   </taglib>   <taglib>     <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>     <taglib-location>       /WEB-INF/struts-logic.tld     </taglib-location>   </taglib>   <taglib>     <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>     <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>   </taglib> </web-app> 
    end example

    start sidebar

    See chapters 16, 18, and 20 for more detailed explanations of the HTML, Logic, and Bean tag libraries.

    end sidebar

  10. Now add the TLDs associated with the previously added tag libraries. You will want to copy the struts-bean.tld, struts-html.tld, and struts-logic.tld to the WEB-INF directory.

That is it. We now have our application defined at the Web level. It is now time to define the remainder of the application, which is completed in the following sections.

Creating the employees Model

In this section we are defining the data layer of the employees application. This layer is defined as the Model and is represented by a relational database, an EmployeeData object, and a business object Employee.

The employees application's persistent data will be stored in three database tables employees, roles, and departments. Each of these tables and their contents are defined in the following sections.

The Employees Table

The employees table holds the actual list of people (the employees) found in the application. It is the main table of our application. The structure of this table is described in Table 14.1. The data that populates this table can be found in Table 14.2.

Table 14.1: The employees Table Structure

Column

Description

username

The username is a unique key identifying the employee. It is a varchar(10).

password

The password acts as the security credentials of the employee. It is a varchar(10).

name

The name is the string represents the employee's name. It is a varchar(30).

roleid

The roleid is used to identify the Role that the employee belongs to. It is an integer.

phone

The phone is the string representation of the employee's phone number. It is a varchar(30).

email

The email is the string representation of the employee's email address. It is a varchar(30).

depid

The depid is used to identify the Department that the employee belongs to. It is an integer.

Table 14.2: The Contents of the employees Table

username

password

name

roleid

phone

email

depid

abrickey

$word

Art Brickey

1

(303) 555–1214

<abrickey@where.com>

2

tharris

ralph

Todd Harris

1

(206) 555–9482

<tharris@where.com>

2

sriley

$mindy$

Sean Riley

2

(206) 555–3412

<sriley@where.com>

4

jgoodwill

$pass$

James Goodwill

1

(303) 555–1214

<jgoodwill@where.com>

3

tgray

password

Tim Gray

2

(303) 555–9876

<tgray@anywhere.com>

1

The Roles Table

The roles table holds the list of roles that a user may be assigned. It is the table that we will be using to determine the rights of the current user. The structure of this table is described in Table 14.3. The data that populates this table can be found in Table 14.4.

Table 14.3: The roles Table Structure

Column

Description

roleid

The roleid is used to uniquely identify the roles of the application. It is an integer.

rolename

The rolename is the string representation of the role. It is a varchar(30).

Table 14.4: The Contents of the roles Table

roleid

rolename

1

manager

2

employee

The Departments Table

The departments table holds the list of departments that an employee may be assigned to. The structure of this table is described in Table 14.5. The data that populates this table can be found in Table 14.6.

Table 14.5: The departments Table Structure

Column

Description

depid

The depid is used to uniquely identify the departments of the application. It is an integer.

depname

The depname is the string representation of the department. It is a varchar(30).

Table 14.6: The Contents of the departments Table

depid

depname

1

Administration

2

Network

3

Sales

4

Engineering

Creating the employees Database

Now that you have seen the employees database structure and its contents, it is time to actually create this database.

Make sure you have MySQL installed and running on your host machine and then complete the following steps:

  1. Start the mysql client found in the <MYSQL_HOME>/bin/ directory by typing the following command:

     mysql 

  2. Create the employees database by executing the following command:

     create database employees; 

  3. Make sure you are modifying the appropriate database by executing the following command:

     use employees; 

  4. Create and populate the employees table by executing the following commands:

     create table employees (   username varchar(15) not null primary key,   password varchar(15) not null,   roleid integer not null,   name varchar(30) not null,   phone varchar(15) not null,   email varchar(30) not null,   depid integer not null ); insert into employees values("abrickey", "$word", 1,   "Art Brickey", "(303) 555–1214",   "abrickey@where.com", 2); insert into employees values("tharris", "ralph", 1,   "Todd Harris", "(303) 555–9482",   "tharris@where.com", 2); insert into employees values("sriley", "$mindy$", 2,   "Sean Riley", "(303) 555–3412",   "sriley@where.com", 4); insert into employees values("jgoodwill", "$pass$", 1,   "James Goodwill", "(303) 555–1214",   "jgoodwill@where.com", 3); insert into employees values("tgray", "password", 2,   "Tim Gray", "(303) 555–9876",   "tgray@where.com", 1); 

  5. Create and populate the roles table by executing the following commands:

     create table roles (   roleid integer not null primary key,   rolename varchar(30) not null ); insert into roles values(1, "manager"); insert into roles values(2, "employee"); 

  6. Create and populate the departments table by executing the following commands:

     create table departments (   depid integer not null primary key,   depname varchar(30) not null ); insert into departments values(1, "Administration"); insert into departments values(2, "Network"); insert into departments values(3, "Sales"); insert into departments values(4, "Engineering"); 

The Employee Object

Now that we have defined the database that will house our employee data, it is time to create the Java object that will model this data. The object that we will use is the com.wrox.Employee object. This object is a very simple JavaBean that is used only to hold the values of an individual employee. The source for the Employee object is shown in Listing 14.5.

Listing 14.5: The Employee Object.

start example
 package com.wrox; public class Employee {   protected String username;   protected String password;   protected String name;   protected String department;   protected String rolename;   protected String phone;   protected String email;   protected Integer depid;   protected Integer roleid;   public void setUsername(String username) {     this.username = username;   }   public String getUsername() {     return username;   }   public String getPassword() {     return password;   }   public void setPassword(String password) {     this.password = password;   }   public void setName(String name) {     this.name = name;   }   public String getName() {     return name;   }   public void setDepartment(String department) {     this.department = department;   }   public String getDepartment() {     return this.department;   }   public void setRolename(String rolename) {     this.rolename = rolename;   }   public String getRolename() {     return rolename;   }   public void setPhone(String phone) {     this.phone = phone;   }   public String getPhone() {     return phone;   }   public void setEmail(String email) {     this.email = email;   }   public String getEmail() {     return email;   }   public void setDepid(Integer depid) {     this.depid = depid;   }   public Integer getDepid() {     return depid;   }   public void setRoleid(Integer roleid) {     this.roleid = roleid;   }   public Integer getRoleid() {     return roleid;   } } 
end example

We could have modeled each table in the employees database, but to keep things simple, we have chosen only to model the Employee object, which has both a role and a department.

After you have had a chance to look over the Employee object, go ahead and compile it and move the resulting class file to the <CATALINA_HOME>/webapps/employees/WEB-INF/classes/com/wrox directory.

The EmployeeData Object

Now we have business object to represent our data, let's create an object that will handle the transferring of data to this object. The object that we will use is the com.wrox.EmployeeData object, which is a static object that encapsulates the JDBC layer of the application. Table 14.7 describes each of the methods in the EmployeeData object. The source for the EmployeeData object is shown in Listing 14.6.

Listing 14.6: The EmployeeData Object.

start example
 package com.wrox; import javax.sql.DataSource; import java.util.ArrayList; import java.sql.Connection; import java.sql.Statement; import java.sql.ResultSet; import java.sql.SQLException; public class EmployeeData {   public static Employee getEmployee(String username,     DataSource dataSource)     throws Exception {     Connection conn = null;     Statement stmt = null;     ResultSet rs = null;     Employee employee = null;     try {       conn = dataSource.getConnection();       stmt = conn.createStatement();       rs =         stmt.executeQuery("select * from employees where"         + "username=\'" +username + "'");       if ( rs.next() ) {         employee = new Employee();         employee.setUsername(rs.getString("username"));         employee.setPassword(rs.getString("password"));         employee.setDepid(new Integer(rs.getInt("depid")));         employee.setRoleid(           new Integer(rs.getString("roleid")));         String name = rs.getString("name");         employee.setName(name);         employee.setPhone(rs.getString("phone"));         employee.setEmail(rs.getString("email"));       }       else {         throw new Exception(username + " not found!");       }     }     finally {       if ( rs != null ) {         rs.close();       }       if ( stmt != null ) {         stmt.close();       }       if ( conn != null ) {         conn.close();       }     }     return employee;   }   public static ArrayList getEmployees(DataSource dataSource) {     Employee employee = null;     ArrayList employees = new ArrayList();     Connection conn = null;     Statement stmt = null;     ResultSet rs = null;     try {       conn = dataSource.getConnection();       stmt = conn.createStatement();       rs =         stmt.executeQuery("select * from employees, roles, "         + "departments where employees.roleid=roles.roleid "         + "and employees.depid=departments.depid");       while (rs.next()) {         employee = new Employee();         employee.setUsername(rs.getString("username"));         employee.setName(rs.getString("name"));         employee.setRolename(rs.getString("rolename"));         employee.setPhone(rs.getString("phone"));         employee.setEmail(rs.getString("email"));         employee.setRoleid(new Integer(rs.getInt("roleid")));         employee.setDepid(new Integer(rs.getInt("depid")));         employee.setDepartment(rs.getString("depname"));         employees.add(employee);         System.err.println("Username : "           + employee.getUsername()           + " Department : " + rs.getString("depname"));       }     }     catch ( SQLException e ) {       System.err.println(e.getMessage());     }     finally {       if ( rs != null ) {         try {           rs.close();         }         catch ( SQLException sqle {           System.err.println(sqle.getMessage());         }         rs = null;       }       if ( stmt != null ) {         try {           stmt.close();         }         catch ( SQLException sqle ) {           System.err.println(sqle.getMessage());         }         stmt = null;       }       if ( conn != null ) {         try {           conn.close();         }         catch ( SQLException sqle ) {           System.err.println(sqle.getMessage());         }         conn = null;       }     }     return employees;   }   public static void removeEmployee(String username,     DataSource dataSource)     throws Exception {     Connection conn = null;     Statement stmt = null;     ResultSet rs = null;     try {       conn = dataSource.getConnection();       stmt = conn.createStatement();       StringBuffer sqlString =         new StringBuffer("delete from employees ");       sqlString.append("where username='" + username + "'");       stmt.execute(sqlString.toString());     }     finally {       if ( rs != null ) {         rs.close();       }       if ( stmt != null ) {         stmt.close();       }       if ( conn != null ) {         conn.close();       }     }   }   public static void addEmployee(Employee employee,     DataSource dataSource)     throws Exception {     Connection conn = null;     Statement stmt = null;     ResultSet rs = null;     try {       conn = dataSource.getConnection();       stmt = conn.createStatement();       StringBuffer sqlString =         new StringBuffer("insert into employees ");       sqlString.append("values (\""         + employee.getUsername() + "\", ");       sqlString.append("\"" +         employee.getPassword() + "\", ");       sqlString.append("\""         + employee.getRoleid() + "\", ");       sqlString.append("\""         + employee.getName() + "\", ");       sqlString.append{"\""         + emp1oyee.getPhone() + "\", ");       sqlString.append("\""         + employee.getEmail() + "\", ");       sqlString.append("\""         + employee.getDepid() + "\")");       stmt.execute(sqlString.toString());     }     finally {       if ( rs != null ) {         rs.close();       }       if ( stmt != null ) {         stmt.close();       }       if ( conn != null ) {         conn.close();       }     }   }   public static void updateEmployee(Employee employee,     DataSource dataSource)     throws Exception {     Connection conn = null;     Statement stmt = null;     ResultSet rs = null;     try {       conn = dataSource.getConnection();       stmt = conn.createStatement();       StringBuffer sqlString =         new StringBuffer("update employees ");       sqlString.append("set password='"         + employee.getPassword() + "', ");       sqlString.append("rolebackground-color:d9d9d9">+ employee.getRoleid() + ",");       sqlString.append("name='"         + employee.getName() + "', ");       sqlString.append("phone='"         + employee.getPhone() + "', ");       sqlString.append("email='"         + employee.getEmail() + "', ");       sqlString.append("depbackground-color:d9d9d9">+ employee.getDepid());       sqlString.append(" where username='"         + employee.getUsername() + "'");       stmt.execute(sqlString.toString());     }     finally {       if ( rs != null ) {         rs.close();       }       if ( stmt != null ) {         stmt.close();       }       if ( conn != null ) {         conn.close();       }     }   } } 
end example

Table 14.7: The Methods of the EmployeeData Object

Method

Description

getEmployee()

Takes a username and a DataSource reference, and returns an Employee object matching the passed in username.

getEmployees()

Takes a DataSource and returns an ArrayList containing all of the current Employees.

removeEmpoyee()

Takes a username and a DataSource reference, and removes the Employee object matching the passed in username.

addEmployee()

Takes an Employee and a DataSource reference and inserts the Employee into the Database.

updateEmployee()

Takes an Employee and a DataSource reference and updates the matching Employee row in the Database.

After you have had a chance to look over the EmployeeData object, go ahead and compile it and move the resulting class file to the <CATALINA_HOME>/webapps/employees/WEB-INF/classes/ com/wrox directory.

Data Source Configuration

The final step that we must complete to make our data layer available to the remainder of the employees application is to add a DataSource definition to the employees Struts configuration file. To do this we are going to add a <data-source> entry into the <CATALINA_HOME>/webapps/employees/WEB-INF/ struts-config.xml file. The following snippet contains our new DataSource.

 <data-sources>   <data-source type="org.apache.commons.dbcp.BasicDataSource">     <set-property property="driverClassName"       value="com.mysql.jdbc.Driver" />     <set-property property="url"       value="jdbc:mysql://localhost/employees" />     <set-property property="username"       value="YOUR USERNAME"/>     <set-property property="password"       value="YOUR PASSWORD"/>   </data-source> </data-sources> 

start sidebar

Before continuing with this example, make sure that you have copied the MySQL JDBC driver to the <CATALINA_HOME>/webapps/employees/ WEB-INF/lib directory. We discussed how to set up data sources in Chapter 11, "Integrating the Jakarta Commons Database Connection Pool (DBCP)."

end sidebar

Building the Employees Application

As we discussed earlier, the employees application is intended to be used as an employee directory service that allows a user to list, add, edit, and delete employees stored in the company database. To accomplish these tasks we need to define the Views and Actions that will allow the user to perform each of these functions. The following sections describe each of these functions from the input View through the Action ending with the target View.

start sidebar

In this section we will be using the word transaction to describe an entire application function, which consists of the Views and Actions associated with one application requirement, such as the add transaction or the edit transaction.

end sidebar

The Welcome Page

The Welcome page is the first page that a user will see. It is a simple JSP, index.jsp, that will have only one function and that is to forward the current request to the EmployeeListAction. The source for the login.jsp is shown in Listing 14.7.

Listing 14.7: index.jsp.

start example
 <%@ page language="java" %> <jsp:forward page="/EmployeeList.do" /> 
end example

As stated earlier, the index.jsp acts as the entry point to our application; therefore, we need to add it to the application's web.xml file as one of the welcome files. Listing 14.8 contains the application's current web.xml, including this addition.

Listing 14.8: The web.xml file after adding the index.jsp welcome file.

start example
 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC   "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"   "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app>   <servlet>     <servlet-name>action</servlet-name>     <servlet-class>       org.apache.struts.action.ActionServlet     </servlet-class>     <init-param>       <param-name>debug</param-name>       <param-value>5</param-value>     </init-param>     <init-param>       <param-name>config</param-name>       <param-value>/WEB-INF/struts-config.xml</param-value>     </init-param>     <init-param>       <param-name>application</param-name>       <param-value>ApplicationResources</param-value>     </init-param>     <load-on-startup>1</load-on-startup>   </servlet>   <servlet-mapping>     <servlet-name>action</servlet-name>     <url-pattern>*.do</url-pattern>   </servlet-mapping>   <welcome-file-list>     <welcome-file>/index.jsp</welcome-file>   </welcome-file-list>   <taglib>     <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>     <taglib-location>/WEB-INF/struts-html.tld</taglib-location>   </taglib>   <taglib>     <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>     <taglib-location>       /WEB-INF/struts-logic.tld     </taglib-location>   </taglib>   <taglib>     <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>     <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>   </taglib> </web-app> 
end example

The EmployeeListAction

Once the EmployeeListAction receives control, then the EmployeeListAction.perform() method is invoked. The EmployeeListAction is used to retrieve all of the employees currently contained in the employees database.

If the employees are successfully retrieved from the employees database, then an Employee object, which was described in the data layer of this chapter, is created and populated with the contents of each returned row, and each one of these Employee objects is added to an ArrayList. The ArrayList is then added to the request and the request is forwarded to the success target, which in this case is the employeelist.jsp. The source for the EmployeeListAction can be found in Listing 14.9.

Listing 14.9: EmployeeListAction.java.

start example
 package com.wrox; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import java.util.ArrayList; public class EmployeeListAction extends Action {   public ActionForward execute(ActionMapping mapping,     ActionForm form,     HttpServletRequest request,     HttpServletResponse response)     throws IOException, ServletException {     // Default target to success     String target = new String("success");     ArrayList employees = null;     employees =       EmployeeData.getEmployees(getDataSource(request));     request.setAttribute("employees", employees);     // Forward to the appropriate View     return (mapping.findForward(target));   } } 
end example

The Employee List JSP

The Employee List JSP is used to display all of the employees stored in the employees database. The Employees List View is a simple JSP that takes an ArrayList of Employee objects, forwarded by the EmployeeListAction which we described previously, and iterates over them printing the contents of each Employee object to the output stream. This View also presents the user with the ability to initiate an edit or delete of an employee. The source for the employeelist.jsp is listed in Listing 14.10.

Listing 14.10: The employeelist.jsp.

start example
 <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <html>   <head>     <title><bean:message key="app.title" /></title>   </head>   <body>     <table width="650"       border="0" cellspacing="0" cellpadding="0">       <tr>         <td colspan="7">&nbsp;</td>       </tr>       <tr>     <td height="68" width="48%">           <div align="left">             <img src="/books/2/574/1/html/2/images/wxmainlogowhitespace.gif">           </div>         </td>        </tr>        <tr>          <td colspan="7">&nbsp;</td>        </tr>     </table>     <html:errors />     <table width="700"       border="0" cellspacing="0" cellpadding="0">       <tr align="left">         <th><bean:message key="app.username" /></th>         <th><bean:message key="app.name" /></th>         <th><bean:message key="app.phone" /></th>         <th><bean:message key="app.email" /></th>         <th><bean:message key="app.department" /></th>         <th><bean:message key="app.role" /></th>       </tr>       <!-- iterate over the results of the query -->       <logic:iterate  name="employees">    <tr align="left">      <td>            <bean:write name="employee" property="username" />      </td>      <td>            <bean:write name="employee" property="name" />      </td>      <td>            <bean:write name="employee" property="phone" />      </td>      <td>            <bean:write name="employee" property="email" />      </td>      <td>            <bean:write name="employee" property="department" />      </td>      <td>            <bean:write name="employee" property="rolename" />      </td>      <td>           <a href="Edit.do?username=<bean:write name="employee"        property="username" />">Edit</a>       <a href="Delete.do?username=<bean:write             name="employee" property="username" />">Delete</a>      </td>    </tr>       </logic:iterate>       <tr>         <td colspan="7">     <hr>   </td>       </tr>     </table>     <font size="-1" face="arial">       <a href="addemployee.jsp">Add New Employee</a>     </font>   </body> </html> 
end example

As you look over the source for the Employee List View, pay particular attention to the bolded text. This section includes the occurrences of the <logic:iterate /> tag, which is used to iterate over the ArrayList that is passed to the employeelist.jsp by the EmployeeListAction.jsp.

Deploying the Components of the Employee List Transaction

Now that we have all of the components of the Employee List transaction defined, we need to deploy them to our employees application. The code shown in Listing 14.11, contains the struts-config.xml file, including the changes necessary to deploy the previously described Employee List components.

Listing 14.11: The web.xml file after adding the Employee List components.

start example
 <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC   "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"   "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config>   <data-sources>     <data-source       type="org.apache.commons.dbcp.BasicDataSource">       <set-property property="driverClassName"         value="com.mysql.jdbc.Driver" />       <set-property property="url"         value="jdbc:mysql://localhost/employees" />       <set-property property="username"         value="jim"/>       <set-property property="password"         value="password"/>     </data-source>   </data-sources>   <global-forwards>     <forward name="employeelist" path="/EmployeeList"/>   </global-forwards>   <action-mappings>     <action path="/EmployeeList"       type="com.wrox.EmployeeListAction"       scope="request" >       <forward name="success" path="/employeelist.jsp"/>     </action>   </action-mappings> </struts-config> 
end example

Once you have looked over the new struts-config.xml file, you should have noticed that it looks very similar to any other struts-config.xml file, except for the two lines of code.

The Add Employee Transaction

The Add Employee transaction is used to add employees to the employees database. It is initiated when a user selects the Add New Employee link from the employeelist.jsp. When this link is selected, the Add Employee transaction presents its components in the following order:

  1. Add Employee JSP

  2. EmployeeForm

  3. AddEmployeeAction

  4. EmployeeListAction

  5. Employee List JSP

The Add Employee JSP

The Add Employee View, represented by the JSP addemployee.jsp, is used to retrieve the values of the new employee being added to the employees database. The source for the addemployee.jsp is shown in Listing 14.12.

Listing 14.12: The Add Employee View.

start example
 <%@ page language="java" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <html>   <head>     <title><bean:message key="app.title" /></title>   </head>   <body>     <table width="500"       border="0" cellspacing="0" cellpadding="0">       <tr>         <td>&nbsp;</td>       </tr>       <tr>         <td height="68" width="48%">           <div align="left">             <img src="/books/2/574/1/html/2/images/wxmainlogowhitespace.gif">           </div>         </td>       </tr>       <tr>         <td>&nbsp;</td>       </tr>     </table>     <html:errors />     <html:form action="/Add"       name="employeeForm"       type="com.wrox.EmployeeForm" >       <table width="500" border="0">         <tr>           <td><bean:message key="app.username" />:</td>           <td><html:text property="username" /></td>           <td><bean:message key="app.password" />:</td>           <td><html:text property="password" /></td>         </tr>         <tr>           <td><bean:message key="app.name" />:</td>           <td><html:text property="name" /></td>           <td><bean:message key="app.phone" />:</td>           <td><html:text property="phone" /></td>         </tr>         <tr>           <td><bean:message key="app.email" />:</td>           <td><html:text property="email" /></td>           <td><bean:message key="app.department" />:</td>           <td>             <html:select property="depid" size="1">               <html:option value="1">                 <bean:message key="app.administration" />               </html:option>               <html:option value="2">                 <bean:message key="app.network" />        </html:option>               <html:option value="3">          <bean:message key="app.sales" />        </html:option>               <html:option value="4">          <bean:message key="app.engineering" />        </html:option>             </html:select>           </td>         </tr>         <tr>           <td><bean:message key="app.role" />:</td>           <td>              <html:select property="roleid" size="1">                <html:option value="1">                  <bean:message key="app.manager" />                </html:option>                <html:option value="2">                  <bean:message key="app.employee" />                </html:option>              </html:select>           </td>           <td colspan="2" align="center">             <html:submit /><html:cancel /><html:reset />           </td>         </tr>       </table>     </html:form>   </body> </html> 
end example

The EmployeeForm

Now that you have seen the JSP that will be submitting the new employee values, we need to create an ActionForm that will validate and encapsulate these new employee values. The source for EmployeeForm is shown in Listing 14.13.

Listing 14.13: The EmployeeForm.java.

start example
 package com.wrox; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionError; public class EmployeeForm extends ActionForm {   protected String username;   protected String password;   protected String name;   protected String phone;   protected String email;   protected String depid;   protected String roleid;   public void setUsername(String username) {     this.username = username;   }   public String getUsername() {     return username;   }   public void setPassword(String password) {     this.password = password;   }   public String getPassword() {     return password;   }   public void setName(String name) {     this.name = name;   }   public String getName() {     return name;   }   public void setPhone(String phone) {     this.phone = phone;   }   public String getPhone() {     return phone;   }   public void setEmail(String email) {     this.email = email;   }   public String getEmail() {     return email;   }   public void setDepid(String depid) {     this.depid = depid;   }   public String getDepid() {     return depid;   }   public void setRoleid(String roleid) {     this.roleid = roleid;   }   public String getRoleid() {     return roleid;   }   // This method is called with every request. It resets the   // Form attribute prior to setting the values in the new   // request.   public void reset(ActionMapping mapping,     HttpServletRequest request) {     this.username = "";     this.password = "";     this.name = "";     this.phone = "";     this.email = "";     this.depid = "1";     this.roleid = "1";   }   public ActionErrors validate(ActionMapping mapping,     HttpServletRequest request) {     ActionErrors errors = new ActionErrors();     if ( (roleid == null) || (roleid.length() == 0) ) {       errors.add("roleid",         new ActionError("errors.roleid.required"));     }     if ( (depid == null) || (depid.length() == 0) ) {       errors.add("depid",         new ActionError("errors.depid.required"));     }     if ( (email == null) || (email.length() == 0) ) {       errors.add("email",         new ActionError("errors.email.required"));     }     if ( (phone == null) || (phone.length() == 0) ) {       errors.add("phone",         new ActionError("errors.phone.required"));     }     if ( (name == null) || (name.length() == 0) } {       errors.add("name",         new ActionError("errors.name.required"));     }     if ( (password == null) || (password.length() == 0) ) {       errors.add("password",         new ActionError("errors.password.required"));     }     if ( (username == null) || (username.length() ==0) ) {       errors.add("username",         new ActionError("errors.username.required"));     }     return errors;   } } 
end example

start sidebar

The EmployeeForm is used by both the Add and Edit employee transactions.

end sidebar

As you look over the EmployeeForm.java, you will notice that there is nothing out of the ordinary about it. It provides accessors to data members that map to the values submitted by the Add Employee View, and it performs some simple validation of those values. If the values pass the validation, then the transaction continues; otherwise ActionErrors are created and the request is forwarded back to the addemployee.jsp, which is named by the input attribute of the AddEmployeeAction definition.

The Add Employee Action

The AddEmployeeAction is a simple Struts Action that takes the values submitted in the EmployeeForm object and inserts them into the employees database as a new employee record.

If the insert is successful, then the request is forwarded to the EmployeeListAction, which will retrieve all of the employees from the database (including the newly inserted record) and forward the results to the employeelist.jsp for display. The source for the AddEmployeeAction can be found in Listing 14.14.

Listing 14.14: The Add EmployeeAction.java.

start example
 package com.wrox; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionError; public class AddEmployeeAction extends Action {   public ActionForward execute(ActionMapping mapping,     ActionForm form,     HttpServletRequest request,     HttpServletResponse response)     throws IOException, ServletException {     // Default target to success     String target = new String("success"};     if ( isCancelled(request) ) {       // Cancel pressed back to employee list       return (mapping.findForward("success"));     }     try {       Employee employee = new Employee();       EmployeeForm employeeForm = (EmployeeForm) form;       employee.setUsername(employeeForm.getUsername());       employee.setPassword(employeeForm.getPassword());       employee.setRoleid(         new Integer(employeeForm.getRoleid()));       employee.setName(employeeForm.getName());       employee.setPhone(employeeForm.getPhone());       employee.setEmail(employeeForm.getEmail());       employee.setDepid(new Integer(employeeForm.getDepid()));       EmployeeData.addEmployee(employee,         getDataSource(request));     }     catch ( Exception e ) {       System.err.println("Setting target to error");       target = new String("error");       ActionErrors errors = new ActionErrors();       errors.add(ActionErrors.GLOBAL_ERROR,         new ActionError("errors.database.error",         e.getMessage()));       // Report any errors       if ( !errors.isEmpty() ) {         saveErrors(request, errors);       }     }     // Forward to the appropriate View     return (mapping.findForward(target));   } } 
end example

Deploying the Components of the Add Employee Transaction

Now that we have the components of the Add Employee transaction defined, we can deploy them to our employees application. The code shown in Listing 14.15 contains the struts-config.xml file, including the changes necessary to deploy the Add Employee components.

Listing 14.15: The web.xml file after adding the Add Employee components.

start example
 <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC   "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"   "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config>   <data-sources>     <data-source       type="org.apache.commons.dbcp.BasicDataSource">       <set-property property="driverClassName"         value="com.mysql.jdbc.Driver" />       <set-property property="url"         value="jdbc:mysql://localhost/employees" />       <set-property property="username"         value="jim"/>       <set-property property="password"         value="password"/>     </data-source>   </data-sources>   <form-beans>     <form-bean name="employeeForm"       type="com.wrox.EmployeeForm" />   </form-beans>   <global-forwards>     <forward name="employeelist" path="/EmployeeList"/>   </global-forwards>   <action-mappings>     <action path="/EmployeeList"       type="com.wrox.EmployeeListAction"       scope="request" >       <forward name="success" path="/employeelist.jsp"/>     </action>     <action path="/Add"       type="com.wrox.AddEmployeeAction"       name="employeeForm"       scope="request"       input="/addemployee.jsp"       validate="true" >       <forward name="success" path="/EmployeeList.do"/>       <forward name="error" path="/addemployee.jsp"/>     </action>   </action-mappings> </struts-config> 
end example

Once you have looked over the new struts-config.xml file, you should have noticed that we added two new elements. The first element is a new <form-bean> sub-element named employeeForm, which references the com.wrox.EmployeeForm object. This just tells the application that we want to use the EmployeeForm when performing an AddEmployeeAction.

The second sub-element added to the struts-config.xml file actually defines the AddEmployeeAction. The only thing to note about this entry is that the success target, like the LoginAction, is the EmployeeList.do, which will cause the updated list of employees to be displayed.

The Edit Employee Transaction

The Edit Employee transaction is used to modify employees that currently exist in the employees database. It is initiated when a user selects the Edit link, next to the employee to be edited, from the employeelist.jsp. When this link is selected the Edit Employee transaction presents its components in the following order:

  1. GetEmployeeAction

  2. Edit Employee JSP

  3. EmployeeForm

  4. EditEmployeeAction

  5. EmployeeListAction

  6. Employee List JSP

The Get Employee Action

The GetEmployeeAction is the first Action that is invoked in the Edit Employee transaction. It is invoked from the employeelist.jsp using the following code snippet:

 <a href="Edit.do?username=<bean:write name="employee"   property="username" />">Edit</a> 

As you will notice, this link executes a get request to the Edit.do path with the request parameter username set to the username to be edited. The purpose of the GetEmployeeAction is to retrieve the selected employee from the database and then populate an EmployeeForm with the retrieved values. This allows the editemployee.jsp, which is the successful target of the GetEmployeeAction, to pre-populate the input elements of the <html:form /> with the values of the created EmployeeForm object. The source for the GetEmployeeAction object is shown in Listing 14.16.

Listing 14.16: The GetEmployeeAction.java.

start example
 package com.wrox; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionError; public class GetEmployeeAction extends Action {   protected ActionForm buildEmployeeForm(String username,     HttpServletRequest request)     throws Exception {     EmployeeForm form = null;     Employee employee =       EmployeeData.getEmployee(username,       getDataSource(request));     if ( employee != null ) {       form = new EmployeeForm();       form.setUsername(employee.getUsername());       form.setPassword(employee.getPassword());       form.setDepid((employee.getDepid()).toString());       form.setRoleid(employee.getRoleid().toString());       form.setName(employee.getName());       form.setPhone(employee.getPhone());       form.setEmail(employee.getEmail());     }     else {       throw new Exception(username + " not found!");     }     return form;   }   public ActionForward execute(ActionMapping mapping,     ActionForm form,     HttpServletRequest request,     HttpServletResponse response)     throws IOException, ServletException {     // Default target to success     String target = new String("success");     if ( isCancelled(request) ) {       // Cancel pressed back to employee list       return (mapping.findForward(target));     }     try {       form =         buildEmployeeForm(request.getParameter("username"),           request);       if ( "request".equals(mapping.getScope()) ) {         request.setAttribute(mapping.getAttribute(), form);       }       else {         HttpSession session = request.getSession();         session.setAttribute(mapping.getAttribute(), form);       }     }     catch ( Exception e ) {       System.err.println("Setting target to error");       System.err.println("---->" + e.getMessage() + "<----");       target = new String("error");       ActionErrors errors = new ActionErrors();       errors.add(ActionErrors.GLOBAL_ERROR,         new ActionError("errors.database.error",           e.getMessage ())));       // Report any errors       if ( !errors.isEmpty() ) {         saveErrors(request, errors);       }     }     // Forward to the appropriate View     return (mapping.findForward(target));   } } 
end example

The GetEmployeeAction begins its processing, just like any other Action class, with the perform() method. It first makes sure that the user is logged in; it then makes sure that the Action was not cancelled.

At this point the GetEmployeeAction is ready to perform its specific logic. It begins by invoking the buildEmployeeForm() method, which retrieves the employee with the passed in username, creates and populates an EmployeeForm object, and returns the newly created form to the perform() method.

The perform() then determines where the EmployeeForm object should be stored, using the ActionMapping.getScope() method. Once the Action knows where the EmployeeForm should be stored, it then retrieves the name attribute of the <action> element and adds the EmployeeForm—bound to the retrieved name—to the appropriate scope. This logic is performed using the following code snippet:

 form =   buildEmployeeForm(request.getParameter("username"),     request); if ( "request".equals(mapping.getScope()) ) {   request.setAttribute(mapping.getAttribute(), form); } else {   HttpSession session = request.getSession();   session.setAttribute(mapping.getAttribute(), form); } 

Once the EmployeeForm is added to the appropriate object (either the request or session), then the perform() method forwards the request to the success target, which in this case will be the editemployee.jsp. At this point there should be an EmployeeForm instance stored in either the request or session, with the values retrieved from the employees database.

The Edit Employee JSP

The Edit Employee View, represented by the JSP editemployee.jsp, is used to modify the values of the selected employee. The editemployee.jsp presents the user with an HTML form that should be pre-populated by the GetEmployeeAction described previously. When the user has completed their modifications, they select the Submit button and the modified values, stored in an EmployeeForm instance, are submitted to the EditEmployeeAction. The source for the editemployee.jsp is shown in Listing 14.17.

Listing 14.17: The Edit Employee view.

start example
 <%@ page language="java" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <html>   <head>     <title><bean:message key="app.title" /></title>   </head>   <body>     <table width="500"       border="0"   cellspacing="0" cellpadding="0">       <tr>         <td>&nbsp;</td>       </tr>       <tr>         <td height="68" width="48%">           <div align="left">             <img src="/books/2/574/1/html/2/images/wxmainlogowhitespace.gif">           </div>         </td>       </tr>       <tr>         <td>&nbsp;</td>       </tr>     </table>     <html:errors />     <html:form action="/EditEmployee"       name="employeeForm"       type="com.wrox.EmployeeForm"       scope="request" >       <table width="500" border="0">         <tr>           <td><bean:message key="app.username" />:</td>           <td><html:text property="username" /></td>           <td><bean:message key="app.password" />:</td>           <td><html:password property="password" /></td>         </tr>         <tr>           <td><bean:message key="app.name" />:</td>           <td><html:text property="name" /></td>           <td><bean:message key="app.phone" />:</td>           <td><html:text property="phone" /></td>         </tr>         <tr>           <td><bean:message key="app.email" />:</td>           <td><html:text property="email" /></td>           <td><bean:message key="app.department" />:</td>           <td>             <html:select property="depid" size="1">               <html:option value="1">                 <bean:message key="app.administration" />               </html:option>               <html:option value="2">                 <bean:message key="app.network" />               </html:option>               <html:option value="3">                 <bean:message key="app.sales" />               </html:option>               <html:option value="4">                 <bean:message key="app.engineering" />               </html:option>             </html:select>           </td>         </tr>         <tr>           <td><bean:message key="app.role" />:</td>    <td>      <html:select property="roleid" size="1">               <html:option value="1">          <bean:message key="app.manager" />        </html:option>               <html:option value="2">          <bean:message key="app.employee" />        </html:option>             </html:select>           </td>           <td colspan="2" align="center">      <html:submit />      <html:cancel />      <html:reset />    </td>         </tr>       </table>     </html:form>   </body> </html> 
end example

The EmployeeForm

The EmployeeForm object used in the Edit Employee Transaction is the same EmployeeForm used by the Add Employee Transaction.

The Edit Employee Action

The EditEmployeeAction is a very basic Struts Action that takes the submitted employee values, from the editemployee.jsp View, and performs a SQL update on the record with the matching username. The source for the EditEmployeeAction object is shown in Listing 14.18.

Listing 14.18: The EditEmployeeAction.

start example
 package com.wrox; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionError; public class EditEmployeeAction extends Action {   protected void editEmployee(EmployeeForm form,     HttpServletRequest request)     throws Exception {     Employee employee = new Employee();     employee.setPassword(form.getPassword());     employee.setRoleid(new Integer(form.getRoleid()));     employee.setName(form.getName());     employee.setPhone(form.getPhone());     employee.setEmail(form.getEmail());     employee.setDepid(new Integer(form.getDepid()));     employee.setUsername(form.getUsername());     EmployeeData.updateEmployee(employee,       getDataSource(request));   }   public ActionForward execute(ActionMapping mapping,     ActionForm form,     HttpServletRequest request,     HttpServletResponse response)     throws IOException, ServletException {     // Default target to success     String target = new String("success");     if (isCancelled(request) ) {       // Cancel pressed back to employee list       return (mapping.findForward("success"));   }   try {     editEmployee((EmployeeForm) form, request);   }   catch ( Exception e ) {     System.err.println("Setting target to error");     target = new String("error");     ActionErrors errors = new ActionErrors();     errors.add(ActionErrors.GLOBAL_ERROR,       new ActionError("errors.database.error",         e.getMessage()));     // Report any errors     if ( !errors.isEmpty() ) {       saveErrors(request, errors);     }   }     // Forward to the appropriate View     return (mapping.findForward(target));   } } 
end example

The EditEmployeeAction begins by first making sure the user is logged in and the Action was not cancelled. Once these conditions are satisfied, then the EditEmployeeAction.perform() method is ready to perform it specific logic, which is simply to invoke the editEmployee() method with the submitted EmployeeForm.

The editEmployee() method then calls the EmployeeData.updateEmployee() method, which in turn performs a SQL update using the employee record referenced by the username contained in the EmployeeForm instance. Assuming that no Exceptions were thrown, then the request is forwarded to the success target, which is the previously described employeelist.jsp.

If the editEmployee() method does throw an Exception, then an ActionError is created and the request is forwarded to the failure target, which in this case is back to the editemployee.jsp.

Deploying the Components of the Edit Employee Transaction

At this point we have the components of the Edit Employee transaction are defined and we can now deploy them to our employees application. Listing 14.19 contains the struts-config.xml file, including the changes necessary to deploy the Edit Employee components.

Listing 14.19: The struts-config.xml file after adding the Edit Employee components.

start example
 <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC   "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"   "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config>   <data-sources>     <data-source       type="org.apache.commons.dbcp.BasicDataSource">       <set-property property="driverClassName"         value="com.mysql.jdbc.Driver" />       <set-property property="url"         value="jdbc:mysql://localhost/employees" />       <set-property property="username"         value="jim"/>       <set-property property="password"         value="password"/>     </data-source>   </data-sources>   <form-beans>     <form-bean name="employeeForm"       type="com.wrox.EmployeeForm" />   </form-beans>   <global-forwards>     <forward name="employeelist" path="/EmployeeList"/>   </global-forwards>   <action-mappings>     <action path="/EmployeeList"       type="com.wrox.EmployeeListAction"       scope="request" >       <forward name="success" path="/employeelist.jsp"/>     </action>     <action path="/Add"       type="com.wrox.AddEmployeeAction"       name="employeeForm"       scope="request"       input="/addemployee.jsp"       validate="true" >       <forward name="success" path="/EmployeeList.do"/>       <forward name="error" path="/addemployee.jsp"/>     </action>     <action path="/Edit"       type="com.wrox.GetEmployeeAction"       name="employeeForm"       scope="request"       validate="false" >       <forward name="success" path="/editemployee.jsp"/>       <forward name="error" path="/EmployeeList.do"/>     </action>     <action path="/EditEmployee"       type="com.wrox.EditEmployeeAction"       name="employeeForm"       scope="request"       input="/editemployee.jsp"       validate="true" >       <forward name="success" path="/EmployeeList.do"/>       <forward name="error" path="/editemployee.jsp"/>     </action>   </action-mappings> </struts-config> 
end example

As you examine the new struts-config.xml file, you will notice that we added two new <action> elements. These two elements are used to describe the GetEmployeeAction and EditEmployeeAction, respectively.

The only thing that should be noted about these <action> elements is that we have set the validate attribute of the GetEmployeeAction to false. This is because the instance of the EmployeeForm will be empty when first submitted to the GetEmployeeAction.

start sidebar

In the <action> element defining the GetEmployeeAction, we are setting the name attribute to point to employeeForm. This would not be necessary if we were not retrieving the name attribute in the GetEmployeeAction.perform() method, but because we are using the name as the key to bind our EmployeeForm instance, we must specify the name attribute.

end sidebar

The Delete Employee Transaction

The Delete Employee transaction is used to remove a selected employee from the employees database. It is initiated when a user selects the Delete link, next to the employee to be removed, from the employeelist.jsp. When this link is selected, the Delete Employee transaction presents its components in the following order:

  1. DeleteEmployeeAction

  2. EmployeeListAction

  3. Employee List JSP

The Delete Employee Action

The final transaction that we will be adding to our employees application is also the simplest. It is invoked from the employeelist.jsp using the following code snippet:

 <a href="Delete.do?username=<bean:write name="employee"   property="username" />">Delete</a> 

As you will notice, this link executes a get request to the Delete.do path with the request parameter username, which will contain the username of the employee to be deleted. The source for the DeleteEmployeeAction object is shown in Listing 14.20.

Listing 14.20: The DeleteEmployeeAction.

start example
 package com.wrox; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionError; public class DeleteEmployeeAction extends Action {   public ActionForward execute(ActionMapping mapping,     ActionForm form,     HttpServletReguest request,     HttpServletResponse response)     throws IOException, ServletException {     // Default target to success     String target = new String("success"};     try {       EmployeeData.removeEmployee(         request.getParameter("username"),         getDataSource(request));     }     catch ( Exception e ) {       System.err.println("Setting target to error");       target = new String("error");       ActionErrors errors = new ActionErrors();       errors.add(ActionErrors.GLOBAL_ERROR,         new ActionError("errors.database.error",           e.getMessage()));       // Report any errors       if ( !errors.isEmpty() ) {         saveErrors(request, errors);       }     }     // Forward to the appropriate View     return (mapping.findForward(target));   } } 
end example

The DeleteEmployeeAction begins by first making sure the user is logged in and the Action was not cancelled. Once these conditions are satisfied, then the DeleteEmployeeAction.perform() method is ready to perform it specific business logic, which is simply to invoke the EmployeeData.removeEmployee() method with the submitted username.

The EmployeeData.removeEmployee() method then performs a SQL delete, removing the employee record referenced by the username and returns control back to the perform() method. Assuming that no Exceptions were thrown by the EmployeeData.removeEmployee() method, then the request is forwarded to the success target, which was previously described EmployeeListAction.

If the EmployeeData.removeEmployee() method does throw Exceptions, then an ActionError is created and the request is forwarded to the failure target (which in this case is the same as the success target).

Deploying the Delete Employee Transaction

The Delete Employee Transaction has only a single component, the DeleteEmployeeAction. To deploy this action, we simply need a single <action> element describing it. The code shown in Listing 14.21, contains the struts-config.xml file, including the changes necessary to deploy the DeleteEmployeeAction.

Listing 14.21: The struts-config.xml file after adding the DeleteEmployee components.

start example
 <?xml version="1.0" encoding="ISO-8859-1"   ?> <!DOCTYPE struts-config PUBLIC   "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"   "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config>   <data-sources>     <data-source       type="org.apache.commons.dbcp.BasicDataSource">       <set-property property="driverClassName"         value="com.mysql.jdbc.Driver" />       <set-property property="url"         value="jdbc:mysql://localhost/employees" />       <set-property property="username"         value="jim"/>       <set-property property="password"         value="password"/>     </data-source>   </data-sources>   <form-beans>     <form-bean name="employeeForm"       type="com.wrox.EmployeeForm" />   </form-beans>   <global-forwards>     <forward name="employeelist" path="/EmployeeList"/>   </global-forwards>   <action-mappings>     <action path="/EmployeeList"       type="com.wrox.EmployeeListAction"       scope="request" >       <forward name="success" path="/employeelist.jsp"/>     </action>     <action path="/Add"       type="com.wrox.AddEmployeeAction"       name="employeeForm"       scope="request"       input="/addemployee.jsp"       validate="true" >       <forward name="success" path="/EmployeeList.do"/>       <forward name="error" path="/addemployee.jsp"/>     </action>     <action path="/Edit"       type="com.wrox.GetEmployeeAction"       name="employeeForm"       scope="request"       validate="false" >       <forward name="success" path="/editemployee.jsp''/>       <forward name="error" path="/EmployeeList.do"/>     </action>     <action path="/EditEmployee"       type="com.wrox.EditEmployeeAction"       name="employeeForm"       scope="request"       input="/editemployee.jsp"       validate="true" >       <forward name="success" path="/EmployeeList.do"/>       <forward name="error" path="/editemployee.jsp"/>     </action>     <action path="/Delete"       type="com.wrox.DeleteEmployeeAction"       scope="request"       validate="false" >       <forward name="success" path="/EmployeeList.do"/>     </action>   </action-mappings> </struts-config> 
end example

As you examine the new struts-config.xml file, you will notice that we added a single <action> element that describes the DeleteEmployeeAction with a very basic definition.

Walkthrough

We have now described and deployed all of the components of our employees application. To see this application in action, you need make sure that you have completed the following:

  1. Move all of your JSPs to the <CATALINA_HOME>/webapps/employees directory.

  2. Compile all of the Java classes and move them to the <CATALINA_HOME>/webapps/employees/classes/com/wrox directory.

  3. Start MySQL, if it is not already running.

  4. Start Tomcat, if it is not already running.

  5. Open your browser to the following URL:

    • http://localhost:8080/employees/

If you logged in correctly, you should see a page similar to Figure 14.1, the Employee List view.

click to expand
Figure 14.1: The Employee List view.

Now select the Edit link next to a user that you want to edit. In this example we selected the user tharris. You should now see the Edit Employee view, which should look similar to Figure 14.2.

click to expand
Figure 14.2: The Edit Employee View.

Go ahead and change one of the attributes of the employee and press the Submit button. You should now see the Employee List View with the changes you made being displayed.

Now select the Add New Employee Link. You should see an empty HTML form similar to Figure 14.3, which represents the possible attributes of an Employee.

click to expand
Figure 14.3: The Add Employee View.

Go ahead and enter a new employee and press the submit button. If everything went according to plan, you should see the Employee List View with the new Employee displayed.



 < Day Day Up > 



Professional Jakarta Struts
Professional Jakarta Struts (Programmer to Programmer)
ISBN: 0764544373
EAN: 2147483647
Year: 2003
Pages: 183

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net