Home

This Chapter
-Chapter 2: Input Validation with Action Forms
-An Overview of Action Forms
-The ActionForm Class
-Using Action Forms
-Using HTML Tag Libraries
-Another Example
-Multipage Forms
-Dynamic Action Forms
-Summary

Table of Contents
-Introduction
-Chapter 1: Model 2 and Struts
-Chapter 2: Input Validation with Action Forms
-Chapter 3: The HTML Tag Library
-Chapter 4: Input Validation and Data Conversion
-Chapter 5: The Validator Plugin
-Chapter 6: The Expression Language
-Chapter 7: JSTL
-Chapter 8: The Bean Tag Library
-Chapter 9: The Logic Tag Library
-Chapter 10: Struts-EL, Nested, selectLabel
-Chapter 11: Message Handling and Internationalization
-Chapter 12: The Tiles Framework
-Chapter 13: Securing Struts Applications
-Chapter 14: The Config Object
-Chapter 15: The Persistence Layer
-Chapter 16: Object Caching
-Chapter 17: File Upload and File Download
-Chapter 18: Paging and Sorting
-Chapter 19: Preventing Double Submits
-Chapter 20: Early HttpSession Invalidation
-Chapter 21: Decorating Request Objects
-Chapter 22: How Struts Works

Previous
Next

 

Using Action Forms

As an example of how to use action forms, consider the app02a application that can be used to add a product. The directory structure of this application is shown in Figure 2.2.

There are two actions in this application, displayAddProductForm and saveProduct. The displayAddProductForm action displays a form for adding product information. The saveProduct action saves the product. The struts-config.xml file is given in Listing 2.1.

Figure 2.2: The directory structure of app02a

Listing 2.1: The Struts configuration file for this application

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE struts-config SYSTEM
  "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
  <form-beans>
    <form-bean name="productForm" type="app02a.form.ProductForm"/>
  </form-beans>

  <action-mappings>
    <action path="/displayAddProductForm" forward="/jsp/displayAddProductForm.jsp"/>
    <action path="/saveProduct"
      name="productForm"
      input="/jsp/displayAddProductForm.jsp"
      scope="request"
      type="app02a.action.SaveProductAction">
      <forward name="success" path="/jsp/displaySavedProduct.jsp"/>
    </action>
  </action-mappings>
</struts-config>

There is no action class associated with the displayAddProductForm action. The forward attribute tells us that the user will be forwarded to the displayAddProductForm.jsp page upon the invocation of this action.

The saveProduct action, on the other hand, has an action class of type app02a.action.SaveProductAction. More importantly, the action defines the name, input, and scope attributes. The name attribute indicates that an action form must be created upon the invocation of this action. The type of the action form is app02a.form.ProductForm, as specified in the form-bean element. The ProductForm class is given in Listing 2.2.

Listing 2.2: The ProductForm class

package app02a.form;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;

public class ProductForm extends ActionForm {
  private String productName;
  private String description;
  private String price;

  public String getProductName() {
    return productName;
  }
  public void setProductName(String productName) {
    this.productName = productName;
  }
  public String getDescription() {
    return description;
  }
  public void setDescription(String description) {
    this.description = description;
  }
  public String getPrice() {
    return price;
  }
  public void setPrice(String price) {
    this.price = price;
  }
  public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
    ActionErrors actionErrors = new ActionErrors();
    if (productName.equals("")) {
      actionErrors.add("no.productName", new ActionMessage("no.productName"));
     }
    if (description.equals("")) {
      actionErrors.add("no.description", new ActionMessage("no.description"));
    }
    return actionErrors;
  }
}

Pay special attention to the validate method in the ProductForm class. This method contains the rules that say that the productName and the description properties must not be empty. This means, the productName and the description fields in the HTML form associated with this action form must have a value.

The displayAddProductForm.jsp contains the associated HTML form and is given in Listing 2.3.

Listing 2.3: The displayAddProdutForm.jsp page

<html>
<head>
<title>Add Product Form</title>
</head>
<body>
<h3>Add a product</h3>
<form method="post" action="saveProduct.do">
<table>
<tr>
  <td>Product Name</td>
  <td><input type="text" name="productName"/></td>
</tr>
<tr>
  <td>Description</td>
  <td><input type="text" name="description"/></td>
</tr>
<tr>
  <td>Price</td>
  <td><input type="text" name="price"/></td>
</tr>
<tr>
  <td><input type="reset"/></td>
  <td><input type="submit" value="Add Product"/></td>
</tr>
</table>
</form>
</body>
</html>

Note that the HTML forms have fields that match the properties in the ProductForm action form. You will learn a better way of writing an HTML form in the next sample application.

When the user submits the form, the saveProduct action will be invoked and Struts will create an instance of ProductForm and call its validate method. If either the productName or description field is empty, validation will fail and Struts will forward control to the displayAddProductForm.jsp page, as specified by the input attribute in the saveProduct action element. If validation is successful, Struts calls the execute method on the associated action object, an instance of SaveProductAction. The SaveProductAction class is given in Listing 2.4.

Listing 2.4: The SaveProductAction class

package app02a.action;
import app02a.form.ProductForm;
import app02a.to.ProductTO;
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;

public class SaveProductAction extends Action {
  public ActionForward execute(ActionMapping mapping,
    ActionForm form, HttpServletRequest request,
    HttpServletResponse response) throws Exception {

    ProductForm productForm = (ProductForm) form;
    ProductTO product = new ProductTO();
    product.setProductName(productForm.getProductName());
    product.setDescription(productForm.getDescription());
    product.setPrice(productForm.getPrice());

    // code for persisting the ProductTO object goes here
    request.setAttribute("product", product);

    return (mapping.findForward("success"));
  }
}

The execute method of SaveProductAction creates a ProductTO object (whose class is similar to the one in Chapter 1), inserts it to the database, and stores it in the HttpServletRequest object. Note that the ProductTO instance gets the values for its properties from the action form. The code for inserting the transfer object into a database is not shown here. Object persistence is discussed in Chapter 15.

The SaveProductAction class forwards control to the displaySavedProduct.jsp page (Listing 2.5). It uses JSTL to display the values of the ProductTO object.

Listing 2.5: The displaySavedProduct.jsp page

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<html>
<head>
<title>Save Product</title>
</head>

<body>
<b>The product has been saved.</b>
<br/><br/>
<b>Details:</b>
<br/>
<br/>Product Name: <c:out value="${product.productName}"/>
<br/>Description: <c:out value="${product.description}"/>
<br/>Price: $<c:out value="${product.price}"/>
</body>
</html>

Running the Application

You start the app02a application by invoking the displayAddProductForm action using the following URL:

http://localhost:8080/app02a/displayAddProductForm.do

This action is defined by the action element in the struts-config.xml file:

<action path="displayAddProductForm"
   forward="/jsp/displayAddProductForm.jsp"/>

Because no type attribute is defined in the action element, the action simply forwards control to the displayAddProductForm.jsp page. As a result, you will see an HTML form in your browser, like the one shown in Figure 2.2.

Figure 2.2: The “Add Product” form

Now, type in values to the first two fields, but leave the last field blank. Submit the form and you will be forwarded back to the same page.

If you enter a value to all the fields and submit the form, you will see something like Figure 2.3 in your browser.

Figure 2.3: The displaySavedProduct.jsp page

The flow of the app02a application is depicted in Figure 2.4.

Figure 2.4: The app02a application’s control flow

When you invoke the displayAddProductForm action (Request 1), Struts forwards control to the displayAddProductForm.jsp (Response 1). As a result, you see the form in Figure 2.2.

When you submit the form without entering a value in all the fields (Request 2A), the saveProduct action is invoked. Recall that this action is defined by the following action element in the struts-config.xml file:

<action path="/saveProduct"
  name="productForm"
  input="/jsp/displayAddProductForm.jsp"
  scope="request"
  type="app02a.action.SaveProductAction">
  <forward name="success" path="/jsp/displaySavedProduct.jsp"/>
</action>

Upon the form submit, the action servlet creates an instance of app02a.form.ProductForm and calls its validate method. The validate method will return a non-empty ActionErrors object because validation fails. As a result, the action servlet will try to obtain the value of the input attribute in the corresponding action element. In this case, you will be forwarded to the displayAddProductForm.jsp page (Response 2A).

Now, complete all the fields and submit the form (Request 2B). The saveProduct action is invoked again, and a ProductForm instance will be created and its validate method called. This time validation is successful and the action form will be sent to a SaveProductAction instance. The execute method of SaveProductAction returns an ActionMapping object that forwards control to the displaySavedProduct.jsp and you see will the confirmation message in your browser (Response 2B) (See Figure 2.3.)

Note

The value of an input element can also be the path of another action.

Previous
Next