JSP Files: The Alpha and the Omega


I call the JSP files the alpha and omega because every Struts transaction begins and ends on a JSP page. They represent the outermost layer of the view, controlling the formatting of information as it is presented to the user and (through JavaScript and other client-side scripting) providing the first level of validation to input from the user .

JSP files under Struts look much the same as normal JSP files, except that the Struts taglibs are used to provide quick access to common Struts functionality and to reduce the number of raw Java scriptlets used on the page.

JAVA SCRIPTLETS VERSUS TAGS

There's a certain amount of programmatic dogma floating around the software industry right now. The basic premise is that raw Java should never appear on a JSP page.

The primary argument is that Java confuses nonprogrammers who have to maintain the pages, and that by using tags, you avoid the risk of having stray keystrokes contaminate the logic.

In theory, I agree that whenever you can conveniently use a tag instead of a Java scriptlet, you should. However, the keyword here is conveniently . I've seen two or three lines of compact Java replaced with dozens of lines of tags because of someone's zeal to keep a JSP file Javaclean.

As a rule of thumb, if using tags will make a JSP file significantly longer and if the functionality needed will not be repeated enough to consider writing a custom tag, don't reject using some Java.

The JSP page fits hand and glove with the ActionForm ; any properties that must be populated in the form bean must have corresponding form fields on the JSP, and the JSP page must be able to display any errors that occur during processing.

Again, the best perspective on how this works can be achieved by looking at a JSP file. In this case, we'll examine newUser.jsp (see Listing 7.4).

Listing 7.4 newUser.jsp
 <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%> <%@ taglib uri="/WEB-INF/struts-template.tld" prefix="tmp"%> <%@ taglib uri="/WEB-INF/stock.tld" prefix="stock"%> <tmp:insert template="header.jsp"> <tmp:put name="title">Create a New Account</tmp:put> </tmp:insert> <table width="100%" BORDER="1" CELLPADDING="5"><TR> <TD WIDTH="250" VALIGN="TOP" HALIGN="LEFT"> <tmp:insert template="minibar.jsp"/> </TD><TD VALIGN="TOP"> <html:errors property="org.apache.struts.action.GLOBAL_ERROR"/> <table>   <html:form action="/newUser.do">   <tr>     <td colspan="2">       <h2>New User Registration</h2>     </td>   </tr>   <tr>     <td>username</td><td>     <html:text property="username" maxlength="15" size="15"/>     </td><td><html:errors property="username"/></td>   </tr>   <tr>     <td>password</td><td>      <html:text property="password" maxlength="15" size="15"/></td>     <td><html:errors property="password"/></td>   </tr>   <tr>     <td>email</td><td>      <html:text property="email" maxlength="30" size="30"/></td>     <td><html:errors property="email"/></td>   </tr>   <tr>     <td>firstName</td><td>      <html:text property="firstName" maxlength="30" size="30"/></td>     <td><html:errors property="firstName"/></td>   </tr>   <tr>     <td>lastName</td><td>      <html:text property="lastName" maxlength="30" size="30"/></td>     <td><html:errors property="lastName"/></td>   </tr>   <tr>     <td>streetAddress1</td><td>      <html:text property="streetAddress1" maxlength="60" size="60"/></td>     <td><html:errors property="streetAddress1"/></td>   </tr>   <tr>     <td>streetAddress2</td><td>       <html:text property="streetAddress2" maxlength="60" size="60"/></td>     <td><html:errors property="streetAddress2"/></td>   </tr>   <tr>     <td>city</td><td><html:text property="city" maxlength="30" size="30"/></td>     <td><html:errors property="city"/></td>   </tr>   <tr>     <td>state</td><td><html:text property="state" maxlength="2" size="2"/></td>     <td><html:errors property="state"/></td>   </tr>   <tr>     <td>postalCode</td><td>       <html:text property="postalCode" maxlength="10" size="10"/></td>     <td><html:errors property="postalCode"/></td>   </tr>   <tr>     <td>homePhone</td><td>       <html:text property="homePhone" maxlength="13" size="13"/></td>     <td><html:errors property="homePhone"/></td>   </tr>   <tr>     <td>workPhone</td><td>       <html:text property="workPhone" maxlength="13"size="13"/></td>     <td><html:errors property="workPhone"/></td>   </tr>   <tr>     <td>workExt</td><td>       <html:text property="workExt" maxlength="10" size="10"/></td>     <td><html:errors property="workExt"/></td>   </tr>   <tr>     <td colspan="2"><html:submit property="ok"/></td>   </tr>   </html:form> </table> </TD></TR></TABLE> </body> </html> 

In many ways, this page is very similar to a normal HTML form that would be submitted to a CGI or servlet. As with most things, however, the devil is in the details.

To begin with, the JSP page immediately loads the taglibs for Struts, as well as a custom taglib called stock , which is used to generate stock quotes for the Web app.

After the tablibs are loaded, the page uses the template tags insert and put to request a copy of the standard page header (shown in Listing 7.5).

Listing 7.5 header.jsp
 <%@ taglib uri="/WEB-INF/struts-template.tld" prefix="tmp"%> <html> <head> <title> <tmp:get name="title"/> </title> </head> <body> <table width="100%"> <tr><td align="CENTER"><H1>STOCK TRACKER</H1></td></tr> <tr><td align="CENTER">Your Insider's View to Wall Street</td></tr> </table><P> 

All the header does is write out a TITLE tag with a title string handed in to the template using the put tag and read using the get tag. It also puts a banner across the top of the Web page.

Next, newUser.jsp sets up a two-column table and again uses insert to place the contents of minibar.jsp (Listing 7.6) in the left-side column.

Listing 7.6 minibar.jsp
 <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%> <%@ taglib uri="/WEB-INF/struts-template.tld" prefix="tmp"%> <%@ taglib uri="/WEB-INF/stock.tld" prefix="stock"%> <logic:present name="validatedUser" scope="session"> <font size="-2">Welcome back,      <bean:write name="validatedUser" property="userFirstName"/> <bean:write name="validatedUser" property="userLastName"/></FONT><P/> <logic:notEmpty name="validatedUser" property="holdings" scope="session"> <font size="-2"><B>Your Portfolio</B></font> <TABLE WIDTH="100%"><TR><TH><font size="-2">Symbol</font></TH> <TH align="right"><font size="-2">Holdings</font></TH> <TH align="right"><font size="-2">Latest Quote</font></TH> <TH align="right"><font size="-2">Current Value</font></TH></TR> <logic:iterate id="holding" name="validatedUser" property="holdings"> <TR><TD><font size="-2">      <bean:write name="holding" property="stock.stockSymbol"/></font></TD> <TD align="right"><font size="-2">      <bean:write name="holding" property="numShares"/></font></TD> <TD align="right"><font size="-2"><stock:lastquote holding="holding"/></font></TD> <TD align="right"><font size="-2">      <stock:lastquote holding="holding" multiply="yes"/></font></TD></TR> </logic:iterate> </TABLE> <font size="-2">You can update your portfolio by clicking <html:link href="addTransaction.do">here</html:link></font> </logic:notEmpty> <logic:empty name="validatedUser" property="holdings" scope="session"> <font size="-2">You can track your portfolio by clicking <html:link href="portfolio.do">here</html:link></font> </logic:empty> </logic:present> <logic:notPresent name="validatedUser" scope="session"> <table>   <html:form action="/login.do">   <tr>     <td colspan="2">       <h2>Login Please</h2>     </td>   </tr>   <logic:equal name="RESULT" scope="request" value="INVALID">   <tr><td colspan="2">Invalid User Name or Password</td></tr>   </logic:equal>   <tr><TD COLSPAN="2"><html:errors property="username"/></TR>     <TR><td><FONT SIZE="-2">Username</FONT></td>         <td><html:text property="username"/></td></tr>   <tr><td><html:errors property="password"/></td></tr>     <tr><td><FONT SIZE="-2">Password</FONT></td>         <td><html:password property="password"/></td></td>   </tr>   <tr>     <td colspan="2"><html:submit property="ok"/></td>   </tr>   </html:form>   <tr><td colspan="2">     <FONT SIZE="-2">No account? Click        <html:link page="/newaccount.do">here</html:link>         to create one.</FONT></td></tr> </table> </logic:notPresent> <CENTER> <HR> <tmp:insert template="marketupdate.jsp"/> </CENTER> <HR> Selected Technology Stocks:<BR> <FONT SIZE="-2">IBM: <stock:lastquote symbol="IBM"/>                (<stock:dfc symbol="IBM"/>)<BR> MSFT: <stock:lastquote symbol="MSFT"/> (<stock:dfc symbol="MSFT"/>)<BR> </FONT> 

The minibar is a much more complex piece of JSP/Struts. First, it checks to see whether the validatedUser property has been placed on the session (this is done after a successful login). If the property is there (checked using the logic:present tag), the JSP generates a greeting with the first and last names of the user using the bean:write tag to look inside the validatedUser bean. Next, it checks whether the user has any stocks in the portfolio using the logic:notEmpty tag, which displays its body only if the argument is not null or an empty collection.

The logic:iterate tag loops over the stocks in the holdings, and then uses some custom tags from the stock taglib to display various attributes and quotes for each stock.

If there is no current portfolio, the user is given a link to start entering one. If no one is logged in, a login form is presented instead. This form submits values to the LoginForm , shown in Listing 7.7.

Listing 7.7 LoginForm.java
 package stocktrack.struts.form; import javax.servlet.http.*; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionForm; import stocktrack.struts.form.BaseForm; /**  * stocktrack.struts.form.LoginForm class.  * this class used by Struts Framework to store data from loginForm  *  * struts-config declaration:  * <form-bean name="loginForm"  *         type="stocktrack.struts.form.LoginForm" />  *  * @see org.apache.struts.action.ActionForm org.apache.struts.action.ActionForm  * Generated by StrutsWizard.  */ public class LoginForm extends BaseForm {   public void reset(ActionMapping mapping, HttpServletRequest request) {     username = "";     password = "";   }   public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {     ActionErrors errors = new ActionErrors();     if (this.isBlankString(username)) {      errors.add("username", new ActionError("stocktrack.login.username.required"));     }     if (this.isBlankString(password)) {      errors.add("password", new ActionError("stocktrack.login.password.required"));     }   return errors;   }   private String username;   private String password;   public String getUsername() {     return username;   }   public void setUsername(String username) {     this.username = username;   }   public String getPassword() {     return password;   }   public void setPassword(String password) {     this.password = password;   } } 

This form provides two validations for missing username or password. If the login fails, that is handled in the Action.

Returning to the main newUser page (Listing 7.4), you can see how the form fields, properties, and errors all tie together. At the top of the page, an html:errors tag looks for what are called global errors. Global errors are errors not associated with validations of a specific field, and are typically created in the Action . In this case, the Action will check to make sure that there is no user already with the requested username, and return a global error if there is.

Each field consists of an html:text tag for the property, followed by an html:errors tag asking for errors for that property. Using the html:text tag rather than a plain INPUT tag is important because the html:text tag automatically places the last value from a submit into the field if the form fails validation. Essentially, it does the opposite of a jsp:setProperty : It takes bean values and plops them into the form fields.



Struts Kick Start
Struts Kick Start
ISBN: 0672324725
EAN: 2147483647
Year: 2002
Pages: 177

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