The Perils of Automatic Type Conversion


One of JSP's features is that it will automatically convert text fields from forms into a number of common data types (including float s and int s) during form submission. However, you shouldn't use this feature with Struts.

The reason is that if you use this feature, any nonnumeric value placed in this field will cause it to stick a zero in the field.

You could check to make sure that the values were nonzero in your validator ( assuming that zero isn't a valid value). But, even then, when you returned to the form with the error, the field would have put in zero as the last value submitted, rather than what the user typed.

For example, if you had a field called height that was defined in your ActionForm as an int , and you typed the words too tall in the field, the property would be set to zero. If you returned to the form, the field would now have in it.

So, how should you do it? By making all the properties of the form String s, and doing the conversions using NumberFormat (or DateFormat and so on) after the form is submitted. This might mean that you end up with two sets of get and set methods for the same property. Listing 7.8 shows the ActionForm that handles form submissions from the portfolio page.

Listing 7.8 AddTransactionForm.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.torque.Stock; import java.text.SimpleDateFormat; import stocktrack.struts.form.BaseForm; /**  * stocktrack.struts.form.AddTransactionForm class.  * this class used by Struts Framework to store data from addTransactionForm  *  * struts-config declaration:  * <form-bean name="addTransactionForm"  *         type="stocktrack.struts.form.AddTransactionForm" />  *  * @see org.apache.struts.action.ActionForm org.apache.struts.action.ActionForm  * Generated by StrutsWizard.  */ public class AddTransactionForm extends BaseForm {   public void reset(ActionMapping mapping, HttpServletRequest request) {     symbol = "";     date = "";     shares = "";     price = "";   }   private static SimpleDateFormat df = new SimpleDateFormat("MM-dd-yyyy");   public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {     ActionErrors errors = new ActionErrors();     if (this.isBlankString(symbol)) {       errors.add("symbol", new ActionError("addtransaction.required"));   }     if (this.isBlankString(price)) {       errors.add("price", new ActionError("addtransaction.required"));   } else {     if (!this.isDouble(price)) {       errors.add("price", new ActionError("addtransaction.invalid.price"));     }   }     if (this.isBlankString(shares)) {       errors.add("shares", new ActionError("addtransaction.required"));   } else {     if (!this.isDouble(shares)) {       errors.add("shares", new ActionError("addtransaction.invalid.shares"));     }   }     try {       if (df.parse(date) == null) {         errors.add("symbol", new ActionError("addtransaction.invalid.date"));       } else {         dateAsLong = df.parse(date).getTime();       }     } catch (Exception ex) {         ex.printStackTrace();         errors.add("symbol", new ActionError("addtransaction.invalid.date"));     }      return errors;   }   private String symbol;   private String date;   private String shares;   private long dateAsLong;   private String price;   public long getDateAsLong() {       return dateAsLong;   }   public String getSymbol() {     return symbol;   }   public void setSymbol(String symbol) {     this.symbol = symbol;   }   public String getDate() {     return date;   }   public void setDate(String date) {     this.date = date;   }   public String getShares() {     return shares;   }   public double getSharesAsDouble() {     return Double.parseDouble(this.shares);   }   public void setShares(String shares) {     this.shares = shares;   }   public String getPrice() {     return price;   }   public double getPriceAsDouble() {     return Double.parseDouble(price);   }   public void setPrice(String price) {     this.price = price;   } } 

This ActionForm shows two different ways you can handle this issue. The stock price and number of shares properties have get and set methods for the String version of the value, but also have a get method that returns the String converted into a double .

The transaction date property has a parallel long property that stores the date as a long . But instead of doing the conversion on-the-fly when requested , the date is converted at the same time as it is being validated and is stored for future use.



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