The JSP pages and ActionForm beans work hand-in-hand in Struts because the JSP submits the user input to the bean, and the bean returns validation errors to the JSP.
To understand how they work together, take a look at one ActionForm and the JSP page it relates to. Listing 7.1 shows the NewUserForm bean, which is the ActionForm for the create account screen of the application.
Note
This file is available on the companion CD with this book.
This ActionForm bean (and most of the other Struts-related files in the application) were generated using the excellent Struts Wizard for JBuilder, which automatically generates ActionForms, Actions, and JSP files for Struts.
The bottom of the file can be ignored for the most part. It contains the get and set methods for the bean properties, just as in any other JavaBean. The two interesting methods of the class are reset() and validate().
The reset() method is called when a form is initialized before being used by Struts. It’s responsible for clearing all the bean properties back to their initial state values. This method can also be used to provide a default value for a property.
The validate() method is the real heart of an ActionForm. It looks at all the user input to the form, and makes sure that it is consistent with the data that the application requires.
You might notice that this bean does not directly extend ActionForm, but instead extends BaseForm. BaseForm is a class that extends ActionForm and provides a number of useful helper functions for validation, such as isValidPostalCode. Listing 7.2 shows the source for BaseForm.
The validate() method is passed two arguments: the ActionMapping for the action (which will be discussed in the next chapter) and the HttpServletRequest. In most cases, the validate() method needs neither of these values, but must take them to match the signature. The method returns an ActionErrors object, which is a collection of all the ActionError objects created during validation.
In this class, the method first instantiates an ActionErrors object, storing it in errors. The method proceeds to validate each property in turn. If the property doesn’t validate (because of an empty required field, for example), the code creates a new ActionError object and uses the add() method on errors to associate the error with a field.
The add() method takes two arguments. The first argument should match the property name of the field as used in the form. For example, if the bean supplies the get method getUsername(), the property name that should be used on the form and as the first argument to ActionError.add should be username. This is the standard JavaBean/JSP convention.
The second argument passed to add() is an ActionError. This class is really just an error message to be passed back to the form, but it is designed so that the error messages come from the application property file instead of a fixed string. This enables nondevelopers to maintain the text of the errors messages, and also automatically makes the error messages “internationalizable” because the application property file can be customized to different locales.
Listing 7.3 shows the portion of ApplicationResources.properties that holds the error messages for this form.
stocktrack.newuser.required=REQUIRED FIELD stocktrack.newuser.invalid.phone=(NNN) NNN-NNNN stocktrack.newuser.invalid.state=No such state stocktrack.newuser.invalid.postalCode=NNNNN or NNNNN-NNNN stocktrack.newuser.duplicate.user=The username you requested is already in use, please try another one |
After all the validations have been run, the validate() method returns the ActionErrors object. If it contains no errors, the controller runs the Action associated with the form. If there were validation errors, control is returned to the JSP, which is responsible for displaying the error messages.
VALIDATING BUSINESS LOGICSometimes there are validations that need to run on a form, but require business logic to determine whether the field or form is valid. For example, in the create account processing, the code must determine whether the username is already in use, because it must be unique. To be consistent with the MVC design pattern, however, you should never place business logic in an ActionForm because the ActionForm is part of the view. Views are not supposed to contain any actual knowledge of the back end. This information lives in the model. In Struts, the Action provides the interface between the View and the Model. As you’ll see in Chapter 8, “The Controller: Directing the Action,” there are ways to do validations inside the Action as well as in the ActionForm. |