Adding Error Handling to the wroxapp Application

 < Day Day Up > 



Now that you have seen the classes involved in Struts error management, let's see how they are actually used. We do this by adding the Struts error-management components to our wroxapp Web application in two areas: the ActionForm and the Action itself.

Before you can leverage the Struts error-management classes, make sure that the following two attributes have been added to the <action> element that describes the ch03.LookupAction. The following code snippet shows the changes to the struts-config.xml file:

 <action className="ch08.WROXActionMapping"   path="/Lookup"   type="ch03.LookupAction"   name="lookupForm"   validate="true"   input="/index.jsp">   <set-property property="logResults" value="true"/>   <forward name="success" path="/quote.jsp"/>   <forward name="failure" path="/index.jsp"/> </action> 

The new attributes are the validate and input attributes. The first attribute, validate, when set to true tells the Struts Framework that validation should be performed. The second attribute tells the Struts Framework where the error originated and where the action should be redirected, if any errors have occurred. You must add these attributes to all <action> elements that will use the ActionForm.validate() mechanism described in the following section.

The ActionForm.validate() Method

The first area where we apply error-management techniques is in the ActionForm object. This is probably the best place to begin, because it is the first chance you will have to test the incoming request for errors. We are checking for validation errors that occur when the user submitting an HTML form enters incorrect data. The Struts Framework allows you to do this by simply overriding the ActionForm.validate() method. The signature of this method is as follows:

 public ActionErrors validate(ActionMapping mapping,   HttpServletRequest request) 

The ActionForm.validate() method is called by the ActionServlet after the matching HTML input properties have been set. It provides you with the opportunity to test the values of the input properties before the targeted Action.execute() method is invoked. If the validate() method finds no errors in the submitted data, then it returns either an empty ActionErrors object or null and processing continues normally.

If the validate() method does encounter errors, then it should add an ActionError instance describing each encountered error to an ActionErrors collection and return the ActionErrors instance. When the ActionServlet receives the returned ActionErrors, it forwards the collection to the JSP that is referenced by the input attribute described earlier, which in our case is index.jsp. Later in this section you see what the index.jsp View will do with the ActionErrors collection. Listing 10.1 contains the changes we have made to our LookupForm to perform input validation.

Listing 10.1: The modified LookupForm.java.

start example
 package ch03; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; 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;   }   public ActionErrors validate(ActionMapping mapping,     HttpServletRequest request) {     ActionErrors errors = new ActionErrors();     if ( (symbol == null ) || (symbol.length() == 0) ) {       errors.add("symbol",         new ActionError("errors.lookup.symbol.required"));     }     return errors;   } } 
end example

As you look over Listing 10.1, you will notice two areas of change. The first is the addition of two import statements. These statements include the ActionError and ActionErrors classes that we use to handle errors.

The second change is the addition of the validate() method. In this method, we test the symbol data member that was set by the HTML form tag. We test it for both a null and an empty String. If it returns true for either of these tests, then the input data is not valid, and it creates an ActionErrors instance and adds an ActionError object describing the error. It then returns the ActionErrors instance, which is forwarded to index.jsp for display.

You should take note of the values passed to the errors.add() method. The first value, symbol, binds this error to the symbol input property submitted by the HTML form. This tells the Struts Framework that the input value referenced by the symbol property failed validation.

The second parameter, errors.lookup.symbol.required, is a key to the resource bundle of this application. To make this a valid key, you need to add the following entries to both the ApplicationResources_en_US.properties and ApplicationResources_it_IT.properties files, respectively.

The following errors are surrounded by the HTML list item elements <li>. We do this to make the messages more readable when displayed in an HTML client. You learn the purpose of this in the following section.

 errors.lookup.symbol.required=<li>A Symbol is Required</li> errors.lookup.symbol.required=<li>Un simbolo richiesto</li> 

<html:errors />

To see our new validate() method in action, let's modify the index.jsp to display any errors resulting from our validation. The easiest way to do this is with <html:errors />. The <html:errors /> tag is used to display the ActionError objects stored in an ActionErrors collection. It is extremely easy to use, and in most circumstances, you do not need to use any of its available attributes; however, you should define its header and footer.

The header and footer consist of HTML text that is placed before and after the list of ActionErrors. The text that describes the header and footer is stored in the application's resource bundles, allowing the text to be language independent. Like all other objects in a resource bundle, the header and footer values are identified using text keys. The two keys that describe the header and footer are errors.header and errors.footer, respectively. To use the header and footer values, add the following code snippet to the ApplicationResources-en_US.properties file:

 errors.header=<h3>   <font color="red">Error List</font></h3>   <ul> errors.footer=</ul><hr> 

and this code snippet to the ApplicationResources_it_IT.properties file:

 errors.header=<h3>   <font color="red">Elenco degli errori</font></h3>   <ul> errors.footer=</ul><hr> 

start sidebar

Both the header and the footer values are surrounded by HTML unnumbered list elements. This is for formatting purposes, as we mentioned earlier, and is not a required format. You can format your header and footer in just about any style that suits your needs.

end sidebar

Now that we have the header and footer of our error messages defined and in place, we simply need to add the <html:errors /> tag to our JSP. Listing 10.2 shows the index.jsp with the addition of the <html:errors /> tag.

Listing 10.2: The modified index.jsp.

start example
 %@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> %@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <html>   <head>     <title>WROX Struts Application</title>   </head>   <body>     <table width="500" border="0"       cellspacing="0" cellpadding="0">       <tr>         <td>&nbsp;</td>       </tr>       <tr bgcolor="#36566E">         <td height="68" width="48%">           <div align="left">             <img src="/books/2/574/1/html/2/images/hp_logo_wrox.gif"           width="220"          height="74">           </div>         </td>       </tr>       <tr>         <td>&nbsp;</td>       </tr>     </table>     <html:errors />     <html:form action="Lookup">       <table width="45%" border="0">         <tr>           <td><bean:message key="app.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

As you can see, there is really nothing special about this change—you simply need to pick a location in your JSP that will not be missed by the user.

To see these changes take effect, recompile the ch03.LookupForm, copy the resulting class file to the <CATALINA_HOME>/webapps/wroxapp/WEB_INF/classes directory, restart Tomcat, and open your browser to the wroxapp application.

The first time the index.jsp is loaded, you will not see any differences. Recall that we have added code that ensures that the user enters a stock symbol, so to test this change, do not enter any value in the symbol input and click the Submit button. If everything went according to plan, you should see an error message similar to Figure 10.1. If you do not see the error message, check both the LookupForm.validate() method and the resource bundles for this application.

click to expand
Figure 10.1: An error returned from the LookupForm.validate() method.

Error Management in the Action.execute() Method

The final area of Struts error management that we will look at addresses how you report errors that occur in the Action.execute() methods of your application. There is no defined place that errors can occur in an execute() method (as there is in a validate() method), but the important thing to consider is how an error is reported back to the user.

When reporting errors in the execute() method, the same two classes, ActionError and ActionErrors, are used. The only difference is how the collection of errors is sent back to the client. If you examine the code in Listing 10.3, you will see the changes that have been added to the ch03.LookupAction to report errors.

Listing 10.3: The modified LookupAction.java.

start example
 package ch03; 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.ActionError; import org.apache.struts.action.ActionErrors; import ch08.WROXActionMapping; public class LookupAction 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 Exception{     String theMapping = mapping.getClass().toString();     WroxActionMapping wroxMapping =       (WROXActionMapping)mapping;     Double price = null;     String symbol = null;     // Default target to success     String target = new String("success");     if ( form != null ) {       LookupForm lookupForm = (LookupForm)form;       symbol = lookupForm.getSymbol();       price = getQuote(symbol);     }   // if price is null, set the target to failure      if ( price == null ) {        target = new String("failure");        ActionErrors errors = new ActionErrors();        errors.add("symbol",          new ActionError("errors.lookup.unknown",symbol));        // Report any errors we have discovered        if ( !errors.isEmpty() ) {          saveErrors(request, errors);        }      }      else {       boolean logging = wroxMapping.getLogResults();       if ( logging ) {         System.err.println("SYMBOL:"           + symbol + " PRICE:" + price);       }       request.setAttribute("PRICE", price);     }     // Forward to the appropriate View     return (mapping.findForward(target));   } } 
end example

You will see two changes in this file. The first change is just a couple of import statements that include the ActionError and ActionErrors classes.

The second change is the actual error-reporting section. In this section, we test the value of the price variable. If it is null—which it will be if any value other than SUNW was entered—then we need to report an error. This is accomplished by first setting the target to failure, then by creating an ActionErrors collection and adding an ActionError object to the collection.

The last thing to note about these changes is how the errors are reported back to the client. This is done using the Action.saveErrors() method, as shown here:

 if (!errors.isEmpty()) {   saveErrors(request, errors); } 

The saveErrors() method adds the ActionErrors collection to the HttpServletRequest object. The result of this action is a request containing the errors collection being forwarded to the index.jsp, which is the failure target that will display the errors using the <html:errors /> tag.

Notice the parameters passed to the errors.add() method. The first value that is passed to the add() method is the input property, symbol; this value indicates that this error is bound to the <html:text> tag with the property named symbol.

The second parameter acts no different than it did in the validate() method. It simply looks up a different key representing a different error. To add this error message to the wroxapp application, you need to modify both the ApplicationResources.properties and the ApplicationResources_it.properties files, as shown in Listings 10.4 and 10.5.

Listing 10.4: The modified ApplicationResources_en_US.properties file.

start example
 app.symbol=Symbol app.price=Current Price errors.lookup.symbol.required=<li>A Symbol is Required</li> errors.lookup.unknown=<li>Unknown Symbol {0}</li> errors.header=<h3><font color="red">Error List</font></h3><ul> errors.footer=</ul><hr> 
end example

Listing 10.5: The modified ApplicationResources_it_IT.properties file.

start example
 app.symbol=Simbolo app.price=Prezzo Corrente errors.lookup.symbol.required=<li>Un simbolo richiesto</li> errors.lookup.unknown=<li>Simbolo Sconosciuto {0}</li> errors.header=<h3><font color="red">Elenco degli errori</font></h3><ul> errors.footer=</ul><hr> 
end example

To see these changes take effect, compile the wrox.LookupAction, copy the resulting class file to the <CATALINA_HOME>/webapps/wroxapp/WEB_INF/classes directory, restart Tomcat, and open your browser to the wroxapp application. Now this time, instead of entering an empty stock symbol, enter any value other than SUNW and click the Submit button. You should see an error message similar to Figure 10.2. If you do not see this message, check both the LookupAction.execute() method and the application resource bundles.

click to expand
Figure 10.2: An error returned from the LookupAction.execute() method.



 < 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