Two-Step Forms

I l @ ve RuBoard

The credit card code shows how you can implement a form that is filled out in two steps. The first page (see Listing 16.8) looks much like the Address.jsp code, letting the user fill out or edit the credit card information.

Listing 16.8 CreditCard .jsp
 <%@ page language="java" %> <%@ taglib uri="/WEB-INF/struts-html.tld"         prefix="html" %> <%@ taglib uri="/WEB-INF/struts-bean.tld"         prefix="bean" %> <%@ include file="/jsp/cust/AutoLogin.jsp" %> <% {     Customer customer =     (Customer) pageContext.getAttribute("customer", PageContext.SESSION_SCOPE);     if (( customer == null)  (customer.getEmail() == null)) {      response.sendRedirect("Login.jsp");      return;     } } %> <html:html> <head> <title>   <bean:message key="mycard.title"/> </title> <%@ include file="/jsp/includes/bfgheader.jsp" %> <h2 align="center"><bean:message key="mycard.title"/></h2> <html:errors/> <html:form action="/CreditCard"> <html:hidden property="cardID"/> <bean:message key="mycard.field.cardOwner"/> <html:text property="cardOwner"/><BR> <bean:message key="mycard.field.cardType"/> <html:select property="cardType"> <html:option value="">SELECT</html:option> <html:option value="VISA">Visa</html:option> <html:option value="MC">MasterCard</html:option> <html:option value="AMEX">American Express</html:option> <html:option value="DISC">Discover</html:option> </html:select><BR> <bean:message key="mycard.field.cardNumber"/> <html:text property="cardNumber"/><BR> <bean:message key="mycard.field.expires"/> <html:select property="expMonth">   <html:option value="0">SELECT</html:option>   <html:option value="1">Jan</html:option>   <html:option value="2">Feb</html:option>   <html:option value="3">Mar</html:option>   <html:option value="4">Apr</html:option>   <html:option value="5">May</html:option>   <html:option value="6">Jun</html:option>   <html:option value="7">Jul</html:option>   <html:option value="8">Aug</html:option>   <html:option value="9">Sep</html:option>   <html:option value="10">Oct</html:option>   <html:option value="11">Nov</html:option>   <html:option value="12">Dec</html:option> </html:select> / <html:select property="expYear">   <html:option value="0">SELECT</html:option>   <html:option value="2002">02</html:option>   <html:option value="2003">03</html:option>   <html:option value="2004">04</html:option>   <html:option value="2005">05</html:option>   <html:option value="2006">06</html:option>   <html:option value="2007">07</html:option>   <html:option value="2008">08</html:option>   <html:option value="2009">09</html:option>   <html:option value="2010">10</html:option>   <html:option value="2011">11</html:option>   <html:option value="2012">12<P></html:option> </html:select><BR> <html:submit/> </html:form> </html:html> 

When you do a select using the Struts taglib, you use the html:option tag for the values. Again, the taglib automatically causes the right one to be preselected if the page already has values.

There are no surprises with the credit card validation code in the bean form for this page (see Listing 16.9). I've left out the card number checksum validations to keep things compact, but in the real site, you would put them in along with date checks.

Listing 16.9 creditcardForm.java
 package com.bfg.struts; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionMapping; public class creditcardForm extends ActionForm {     protected int cardID = -1;     protected String cardOwner;     protected String cardType = "";     protected String cardNumber;     protected int expMonth = 0;     protected int expYear = 0;     public int getCardID() {      return cardID;     }     public void setCardID(int id) {      cardID = id;     }     public String getCardOwner() {      return cardOwner;     }     public void setCardOwner(String name) {      cardOwner = name;     }     public String getCardType() {      return cardType;     }     public void setCardType(String name) {      cardType = name;     }     public String getCardNumber () {      return cardNumber;     }     public void setCardNumber(String name) {      cardNumber = name;     }     public int getExpMonth () {      return expMonth;     }     public void setExpMonth(int month) {      expMonth = month;     }     public int getExpYear () {      return expYear;     }     public void setExpYear(int year) {      expYear = year;     }     public ActionErrors validate(ActionMapping mapping,                                  HttpServletRequest request) {         ActionErrors errors = new ActionErrors();      if ((cardNumber == null)           (cardNumber.length() == 0)) {             errors.add("cardNumber",                        new ActionError("error.cardnumber.required"));      }      if ((cardOwner == null)           (cardOwner.length() == 0)) {             errors.add("cardOwner",                        new ActionError("error.cardowner.required"));      }      if ((cardType == null)           (cardType.length() == 0)) {             errors.add("cardType",                        new ActionError("error.cardtype.required"));      }      if (expMonth == 0) {             errors.add("expMonth",                        new ActionError("error.expmonth.required"));      }      if (expYear == 0) {             errors.add("expYear",                        new ActionError("error.expyear.required"));      }      return errors;     } } 

If the card passes , the next step is to gather the address. So, the action (see Listing 16.10) stores the credit card information in a session property for the moment. You could also have done this by specifying that the creditcardForm object should be session scoped in the XML configuration file ”it's pretty much a matter of style.

Then the method either gets a new Address object or gets the old one from the credit card that's being edited so that the address form can be filled in with it.

Listing 16.10 cardAction.java
 package com.bfg.struts; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletException; import org.apache.struts.action.ActionForm; import org.apache.struts.action.Action; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionForward; import org.apache.struts.util.PropertyUtils; import com.bfg.customer.Address; import com.bfg.customer.CreditCard; import com.bfg.customer.Customer; import java.text.NumberFormat; import java.io.*; public class cardAction extends Action {     public ActionForward perform(ActionMapping mapping,                      ActionForm form,                      HttpServletRequest request,                      HttpServletResponse response)      throws IOException, ServletException {      creditcardForm ccf = (creditcardForm) form;      Customer cust = ((Customer)request.getSession().getAttribute("customer"));      request.getSession().setAttribute("cardData", ccf);      if (ccf.getCardID() == -1) {          request.setAttribute("addressForm", new addressForm());          return mapping.findForward("CCaddress");      }  else {          try {           CreditCard card =               (CreditCard) cust.getWallet().get(new Integer(ccf.getCardID()));           if (card == null) {               return mapping.findForward("myaccount");           }           addressForm ad_form = new addressForm();           PropertyUtils.copyProperties(ad_form, card.getAddress());           request.setAttribute("addressForm", ad_form);           return mapping.findForward("CCaddress");          }  catch (Exception ex) {           ex.printStackTrace();          }      }      return mapping.findForward("myaccount");     } } 

With a little cleverness , you could have made the address JSP code serve two purposes: to handle both the normal address case and the credit card case. For the moment, you can use a separate JSP (see Listing 16.11) for the credit card address, which is a copy of Address.jsp with the following differences show in bold.

Listing 16.11 CCAddress.jsp
 <%@ page language="java" %> <%@ taglib uri="/WEB-INF/struts-html.tld"         prefix="html" %> <%@ taglib uri="/WEB-INF/struts-bean.tld"         prefix="bean" %> <%@ include file="/jsp/cust/AutoLogin.jsp" %> <% {     Customer customer =     (Customer) pageContext.getAttribute("customer", PageContext.SESSION_SCOPE);     if (( customer == null)  (customer.getEmail() == null)) {      response.sendRedirect("Login.jsp");      return;     } } %> <html:html> <head> <title>  <bean:message key="myccaddr.title"/>  </title> <%@ include file="/jsp/includes/bfgheader.jsp" %>  <h2 align="center"><bean:message key="myccaddr.title"/></h2>  <html:errors/>  <html:form action="/CreditCardAddr">  <bean:message key="myaddr.field.firstname"/> <html:text property="firstName"/><BR> <bean:message key="myaddr.field.lastname"/>  <html:text property="lastName"/><BR> <bean:message key="myaddr.field.street1"/> <html:text property="street1"/><BR> <bean:message key="myaddr.field.street2"/> <html:text property="street2"/><BR> <bean:message key="myaddr.field.city"/> <html:text property="city"/> <bean:message key="myaddr.field.state"/> <html:text property="state"/> <bean:message key="myaddr.field.postal"/> <html:text property="postalCode"/><BR> <html:submit/> </html:form> </html:html> 

Because the code uses the same addressForm object, the validations come for free. If they succeed, the controller hands off to cardAddrAction (see Listing 16.12), which gathers together the saved credit card information and the newly gathered address. It then either creates or updates the credit card record.

Listing 16.12 cardAddrAction.java
 package com.bfg.struts; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletException; import org.apache.struts.action.ActionForm; import org.apache.struts.action.Action; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionForward; import org.apache.struts.util.PropertyUtils; import com.bfg.customer.Address; import com.bfg.customer.Customer; import com.bfg.customer.CreditCard; import java.text.NumberFormat; import java.io.*; public class cardAddrAction extends Action {     public ActionForward perform(ActionMapping mapping,                      ActionForm form,                      HttpServletRequest request,                      HttpServletResponse response)      throws IOException, ServletException {      addressForm af = (addressForm) form;      creditcardForm ccf =          (creditcardForm) request.getSession().getAttribute("cardData");      if (ccf == null) {          return mapping.findForward("myaccount");      }      request.getSession().setAttribute("cardData", null);      Customer cust = ((Customer)request.getSession().getAttribute("customer"));      try {          if (ccf.getCardID() == -1) {           Address addr = new Address();           PropertyUtils.copyProperties(addr, af);           addr.createAddress();           CreditCard card = new CreditCard();           PropertyUtils.copyProperties(card, ccf);           card.setAddress(addr);           card.setCustomer(cust);           card.createCreditCard();           cust.getWallet().put(new Integer(card.getCardID()),                                 card);           return mapping.findForward("myaccount");          }  else {           CreditCard card =               (CreditCard) cust.getWallet().get(new Integer(ccf.getCardID()));           if (card == null) {               return mapping.findForward("myaccount");           }           PropertyUtils.copyProperties(card, ccf);           card.updateCreditCard();           PropertyUtils.copyProperties(card.getAddress(), af);           card.getAddress().updateAddress();           return mapping.findForward("myaccount");          }      }  catch (Exception ex) {          ex.printStackTrace();      }      return mapping.findForward("CCaddress");     } } 

You need to make sure that the code nulls out the saved credit card data so that the application doesn't leave it around for someone else due to some weird session leak.

Listing 16.13 shows the ApplicationResources file that you've been using to get your strings.

Listing 16.13 ApplicationResources.properties
 myaccount.title=BFG Account Maintainance Page myaccount.addrbook=Address Book myaccount.createaddr=Create New Address myaccount.wallet=Credit Cards myaccount.createcard=Create New Credit Card myaccount.edit=EDIT myaccount.delete=DELETE myaddr.title=BFG Address Book Maintainance Page myaddr.field.firstname=First Name: myaddr.field.lastname=Last Name: myaddr.field.street1=Street Addr 1: myaddr.field.street2=Street Addr 2: myaddr.field.city=City: myaddr.field.state=State: myaddr.field.postal=Postal Code: mycard.title=BFG Credit Card Maintainance Page: myccaddr.title=BFG Credit Card Address Page mycard.field.cardOwner=Card Owner Name: mycard.field.cardType=Card Type: mycard.field.cardNumber=Card Number: mycard.field.expires=Card Expires: error.lastname.required=Last Name Required<BR> error.firstname.required=First Name Required<BR> error.street1.required=Street Address Required<BR> error.city.required=City Required<BR> error.state.required=State Required<BR> error.postal.required=Postal Code Required<BR> error.cardnumber.requied=Card Number Required<BR> error.cardowner.required=Card Owner Required<BR> error.cardtype.required=Card Type Required<BR> error.expmonth.required=Card Expiration Month Required<BR> error.expyear.required=Card Expiration Year Required<BR> 
I l @ ve RuBoard


MySQL and JSP Web Applications. Data-Driven Programming Using Tomcat and MySQL
MySQL and JSP Web Applications: Data-Driven Programming Using Tomcat and MySQL
ISBN: 0672323095
EAN: 2147483647
Year: 2002
Pages: 203
Authors: James Turner

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