Chapter 6: Building the Presentation Layer

 < Day Day Up > 



In this chapter, we examine the View components of the Struts Framework. We show you how to apply tags from Struts tag libraries, use ActionForm and DynaActionForm beans, and wire Views into a Struts application.

The goal of this chapter is to give you an understanding of the Struts View and the components that you can use to construct the View.

Building a Struts View

As we discussed in Chapter 1, "Introducing the Jakarta Struts Project and Its Supporting Components," the Struts View is represented by a combination of JSPs, custom tag libraries, and optional Form bean objects. In the sections that follow, we examine each of these components.

At this point, you should have a pretty good understanding of what JSPs are and how they can be used, which will allow us to now focus on how JSPs are leveraged in a Struts application.

JSPs in the Struts Framework serve two main functions. The first is to act as the presentation layer of a previously executed Controller Action. This is most often accomplished using a set of custom tags that are focused on iterating and retrieving data forwarded to the target JSP by the Controller Action.

The second of these Views is used to gather the data required to perform a particular Controller Action. This is done most often with a combination of tag libraries and Form objects. This is the type of View that we will focus on for the remainder of this chapter.

JSPs That Gather Data

Now that you know how JSPs are deployed in a Struts application, let's take a look at one of the two most common uses of a JSP in a Struts application: using JSPs to gather data.

start sidebar

Here, we're using the application from Chapter 4, "Actions and the ActionServlet," to demonstrate Struts forms.

end sidebar

You can choose among several methods when gathering data using a JSP. The most common method entails using the HTML <form> element and any combination of <input> sub-elements. When gathering form data, Struts uses a set of Struts-specific JSP custom tags that emulate the HTML <form> and <input> elements. The following code snippet contains a JSP that uses the Struts tags to gather data:

 <html:form action="Lookup">   <table width="45%" border="0">     <tr>       <td>Symbol:</td>       <td><html:text property="symbol" /></td>     </tr>     <tr>       <td colspan="2" align="center"><html:submit /></td>     </tr>   </table> </html:form> 

If we break this JSP into logical sections, you see three Struts HTML tags: <html:form />, <html:text />, and <html:submit />. These tags include special Struts functionality that is used to gather HTML form data. We look at each of these tags in the sections that follow.

start sidebar

The Struts library that includes the HTML tags is named, appropriately enough, the HTML Tag Library. It includes tags that closely mimic the same functionality common to HTML form elements. In our example, we saw only a small fraction of the entire HTML tag library. The remaining tags are discussed in Chapter 16 "The HTML Tag Library."

end sidebar

The <html:form /> Tag

The first of these tags is the <html:form /> tag. This tag serves as the container for all other Struts HTML input tags. It renders an HTML <form> element containing all of the child elements associated with this HTML form. This tag, with its children, encapsulates the presentation layer of Struts form processing.

The form tag, in our example, uses only one attribute action. The action attribute represents the URL to which this form will be submitted. This attribute is also used to find the appropriate ActionMapping in the Struts configuration file, which we describe later in this section. The value used in our example is /Lookup, which maps to an ActionMapping with a path attribute equal to /Lookup:

 <html:form action="Lookup"> 

The Input Tags

Once you get past the <html:form /> tag, you will see that it also acts as a parent to two other HTML tags. These tags are synonymous with the HTML input elements.

The <html:text /> Tag

The first of the HTML input tags is the <html:text /> tag. This tag is equivalent to the HTML text input tag, with the only difference being the property attribute, which names a unique data member found in the ActionForm bean class named by the form's type attribute. The following code snippet contains our <html:text /> tag:

 <html:text property="symbol" /> 

As you can see, the property attribute of this instance is set to the value symbol; therefore, when the form is submitted the value of this input tag is stored in the LookupForm's symbol data member.

The <html:submit />Tag

The second HTML tag that we use is the <html:submit /> tag. This tag simply emulates an HTML Submit button by submitting the request to the targeted action:

 <html:submit /> 

When a View containing the <html:submit /> tag is requested, it is evaluated and the resulting HTML looks similar to this:

 <form name="lookupForm"   method="post"   action="/wroxapp/Lookup.do">   <table width="45%" border="0">     <tr>       <td>Symbol:</td>       <td><input type="text" name="symbol" value=" "></td>     </tr>     <tr>       <td colspan="2" align="center">         <input type="submit" value="Submit">       </td>     </tr>   </table> </form> 

start sidebar

As you examine the evaluated form, notice that the value of the <input> elements is an empty string. This will not always be the case. If the form has already been submitted, the values stored in its data members will be used to pre-populate the input values.

end sidebar

Deploying JSPs to a Struts Application

Before we can continue looking at the role of a JSP in the Struts Framework, we must take a look at how JSPs are deployed to the Framework. JSPs are most often the target of a previous request; whether they are gathering or presenting data usually makes no difference as to how they are deployed. All JSPs should be deployed to a Struts application by using a <forward> element. This element is used to define the targets of Struts Actions, as shown in the following code snippet:

 <forward name="error" path="/errorpage.jsp"/> 

In this example, the <forward> element defines a View named error with a path of /errorpage.jsp.

To make this <forward> element available to a Struts application, nest it within one of two possible Struts configuration elements. The first element, <global-forward>, makes a JSP available globally to the entire application. This type of JSP deployment is useful for error and login pages. You perform this type of deployment by adding a JSP <forward> to the <global-forwards> section of the struts-config.xml file. Here's an example:

 <global-forwards>   <forward name="error" path="/errorpage.jsp"/> </global-forwards> 

This <forward> element states that /errorpage.jsp will be the target of all Struts Actions that return an ActionForward instance with the name login, as shown here:

 return (mapping.findForward("error")); 

start sidebar

The only time that a global forward is not used is when an <action> element has a <forward> declaration with the same name. In this instance, the <action> element's <forward> takes precedence.

end sidebar

The second type of <forward> declaration is defined as an Action <forward>. These types of <forward> elements are defined as sub-elements of an <action> definition and are accessible only from within that <action>. The following code snippet shows an example that deploys our index.jsp and quote.jsp to the Lookup action:

 <action path="/Lookup"   type="ch03.LookupAction"   name="lookupForm" >   <forward name="success" path="/quote.jsp"/>   <forward name="failure" path="/index.jsp"/> </action> 

The first <forward> definition states that /quote.jsp will be the target of ch03.LookupAction when this Action returns an ActionForward instance with the name success, as shown here:

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

The second <forward> definition tells the Controller to forward the results of a failed Action to /index.jsp when this Action returns an ActionForward instance with the name failure, as shown here:

 return (mapping.findForward("failure")); 

ActionForm Beans

The next thing that we must discuss is the org.apache.struts.action.ActionForm object. ActionForms are JavaBeans that are used to encapsulate and validate the request data submitted by an HTTP request. Our sample ActionForm, named LookupForm, is shown in Listing 6.1.

Listing 6.1: LookupForm.java.

start example
 package ch03; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; public class LookupForm extends ActionForm {   private String symbol = null;   public String getSymbol() {     return (symbol);   }   public void setSymbol(String symbol) {     this.symbol = symbol;   }   public void reset(ActionMapping mapping,     HttpServletRequest request) {     this.symbol = null;   } } 
end example

As you look over this ActionForm, notice that it extends the org.apache.struts.action.ActionForm class; all ActionForm beans must extend this class. Also notice that the LookupForm definition itself contains one data member, username, as well as three methods.

The first two of these methods are simple setters and getters used to access and modify the symbol data member. Setter methods are called by the Struts Framework when a request is submitted with a parameter matching a data member's name. This is accomplished using JavaBean reflection; therefore, the accessors of an ActionForm must follow the JavaBean standard naming convention.

The last method of this ActionForm, probably the most important method of this implementation, is the reset() method. This method is called by the Struts Framework with each request that uses the defined ActionForm. The purpose of this method is to reset all of the ActionForm's data members prior to the new request values being set. You should implement this method to reset your form's data members to their original values; otherwise, the default implementation will do nothing and your ActionForm's data members could be left holding stale data.

start sidebar

The ActionForm contains another important method that we did not cover in this chapter--the validate() method, which is used to validate form data. We discuss this method and the Struts error-management process in much more detail in Chapter 10, "Managing Errors."

end sidebar

Deploying ActionForms to a Struts Application

Now that you have actually seen what an ActionForm does, let's take a look at how they are deployed. An ActionForm is deployed much like any other Struts object, using a named element in the struts-config.xml file. The element used to describe an ActionForm is the <form-bean> element, and all <form-bean> elements must be nested within the <form-beans> element. Here's an example showing the definition of the ch03.LookupForm:

 <form-beans>   <form-bean name="lookupForm"     type="ch03.LookupForm"/> </form-beans> 

As you can see, this definition has a single <form-bean> element surrounded by a <form-beans> element, which as we explained acts as the parent to all <form-bean> elements. The <form-bean> shown here contains two attributes: name and type. These two elements act as a key/pair with the name attribute representing the key used to index the ch03.LookupForm and the type attribute indicating the fully qualified path to our ActionForm object.

The Steps of a Struts Form Submission

Now that you have seen the HTML form and its matching ActionForm, let's see how they interact. The best way to do this is to examine the form-submission process. When a user enters the appropriate HTML form values and clicks the Submit button, the following actions take place:

  1. The Controller creates or retrieves (if it already exists) an instance of the ch03.LookupForm object. It then stores the instance in the session, if necessary.

  2. The Controller then calls the ch03.LookupForm.reset() method to set the form's data members back to their default values.

  3. The Controller next populates the ch03.LookupForm's symbol data member with the value entered in the <html:text /> input box.

  4. Once the data members of the Form have been set, the Controller invokes the ch03.LookupAction.execute() method.

  5. When the LookupAction.execute() method finishes its processing, it returns an ActionForward and the request is forwarded to the next View, at which point the process begins all over again.

That's it!. There is almost no limit to the type of Views that can exist in a Struts application, but this type of View is most tightly bound to the Struts Framework. This is also the type of View that you will see evolve throughout the remainder of this text.

An Alternative ActionForm:DynaActionForm Bean

One thing that you will notice as you develop more and more Struts applications is its dependence on the ActionForm object. You will find yourself developing a new ActionForm object for just about every piece of business logic that you would like to perform. What you eventually end up with is an ActionForm for every Action object. This process can get extremely time-consuming as well as irritating—especially when you are capturing trivial (one or two elements) form data.

Creating a DynaActionForm

Struts solves this problem with the introduction of a dynamic ActionForm, called the DynaActionForm. This version of the ActionForm object (a direct extension of the ActionForm) gives the developer the ability to define a Form object using an XML entry in the struts-config.xml file. An example entry that would replace the ch03.LookupForm is shown in the following snippet:

 <form-beans>   <form-bean name="lookupForm"     type="ch03.LookupForm"/>   <form-bean name="dynamicLookupForm"     type="org.apache.struts.action.DynaActionForm">     <form-property name="symbol"       type="java.lang.String"       initial="MSFT"/>   </form-bean> </form-beans> 

This looks much like any other <form-bean>, with two exceptions. First, the type attribute points to the org.apache.struts.action.DynaActionForm object. This object is the Struts component that encapsulates the logic required to process a dynamic form.

The second difference is the addition of the <form-property> sub-element. This sub-element defines the properties and respective data members of the dynamic form that is being created. The <form-property> that we use in this example defines three attributes, as described in Table 6.1.

Table 6.1: Attributes of an <action> Element

Attribute

Description

name

Defines the unique identifier of this form. This value will be used by the <action> element as an index into the collection defined in the <form-beans> element.

initial

The default value of the property.

type

Defines the Java type that this property will be mapped to. For our example, we are using a java.lang.String. The available types are:

java.lang.BigDecimal

java.lang.BigInteger

boolean and java.lang.Boolean

byte and java.lang.Byte

char and java.lang.Character

java.lang.Class

double and java.lang.Double

float and java.lang.Float

int and java.lang.Integer

long and java.lang.Long

short and java.lang.Short

java.lang.String

java.sql.Date

java.sql.Time

java.sql.Timestamp

Using a DynaActionForm

Once you have defined your DynaActionForm, you need to modify your application to use it. To make things a bit easier to understand, we are going to mimic the functionality of our ch03.LookupForm and ch03.LookupAction examples.

Creating a New Action

The first thing that you need to do is create a new Action object that provides the same functionality as the previously defined ch03.LookupAction, with the only difference being the method in which it retrieves data from a form. Our new Action retrieves the data from a DynaActionForm as opposed to a user-defined ActionForm. Listing 6.2 contains the source for our new Action.

Listing 6.2: DynamicLookupAction.java.

start example
 package ch06; 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.DynaActionForm; public class DynamicLookupAction extends Action {   protected Double getQuote(String symbol) {     if ( symbol.equalsIgnoreCase("SUNW") ) {       return new Double(25.00);     }     return null;   }   public ActionForward execute(ActionMapping mapping,     ActionForm form,     HttpServletRequest request,     HttpServletResponse response)     throws IOException, ServletException {     Double price = null;     // Default target to success     String target = new String("success");     if ( form != null ) {       // Use the LookupForm to get the request parameters       DynaActionForm lookupForm = (DynaActionForm)form;       String symbol = (String)lookupForm.get("symbol");       price = getQuote(symbol);     }     // Set the target to failure     if ( price == null ) {       target = new String("failure");     }     else {       request.setAttribute("PRICE", price);     }     // Forward to the appropriate View     return (mapping.findForward(target));   } } 
end example

Let's take a close look at two sections of DynamicLookupAction. First let's examine the additional import statement (this is the package that contains the class definition for the DynaActionForm):

 import org.apache.struts.action.DynaActionForm; 

The next section we should consider is the actual code that retrieves data from the form:

 // Use the LookupForm to get the request parameters DynaActionForm lookupForm = (DynaActionForm)form; String symbol = (String)lookupForm.get("symbol"); 

This code first retrieves the ActionForm object passed to the execute() method and then casts this object to its real type, a DynaActionForm. Once it has a reference to the DynaActionForm, it calls the DynaActionForm.get() method, passing it the name of the property to look up. This code works just like a HashMap.

After the proper data has been retrieved, the execute() method performs exactly as it did in the ch03.LookupAction implementation.

Deploying the New Action

Now that you have an Action object that leverages the DynaActionForm, compile the new Action, move the class file into the WEB-INF/classes/ch06/ directory, and make the following changes (shown in bold) to the struts-config.xml file:

 <action-mappings>   <action path="/Lookup"     type="ch03.LookupAction"     name="lookupForm" >     <forward name="success" path="/quote.jsp"/>     <forward name="failure" path="/index.jsp"/>   </action>   <action path="/DynamicLookup"     type="ch06.DynamicLookupAction"     name="dynamicLookupForm" >     <forward name="success" path="/quote.jsp"/>     <forward name="failure" path="/dynamicindex.jsp"/>   </action> </action-mappings> 

When you examine the <action> element, you see that the only thing worth noting is the type and name attributes—everything else is the same, and the values of the type and name attributes simply point to our new ch06.DynamicLookupAction and DynamicLookupForm, respectively.

Creating a New JSP

The final step is creating a JSP that references your new DynaActionForm. To do this, create a new JSP that references the previously defined <action-mapping>. There is really nothing to this—you just change the action attribute of the <html:form> tag to point to the DynamicLookup action. Listing 6.3 shows our new JSP.

Listing 6.3: Dynamicindex.jsp.

start example
 <%@ page language="java" %> <%@ taglib   uri=" /WEB-INF/struts-html.tld"   prefix="html" %> <html>   <head>     <title>Wrox Struts Application - Dynamic Index</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>       <tr>         <td>&nbsp;</td>       </tr>     </table>     <html:form action="DynamicLookup">       <table width="45%" border="0">         <tr>           <td>Symbol:</td>           <td><html:text property="symbol" /></td>         </tr>         <tr>           <td colspan="2" align="center"><html:submit /></td>         </tr>       </table>     </html:form>   </body> </html> 
end example

Now you can restart the server and your new Action and JSP will be deployed and running. To see your changes in action, open your browser to the following URL and enter the symbol SUNW just as you did before:

  • http://localhost:8080/wroxapp/dynamicindex.jsp

Everything should run as it did when you used a static ActionForm without having actually created an object to hold your data. As you can see, using DynaActionForms saves you a tremendous amount of time and effort.



 < 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