Apache Jakarta and Beyond: A Java Programmeramp;#039;s Introduction [Electronic resources]

Larne Pekowsky

نسخه متنی -صفحه : 207/ 167
نمايش فراداده

19.4. Simplifying Form Beans with the Validator

There are a number of validation tests that arise very frequently, such as ensuring values are provided and are of the correct form. Both of these were encountered in the calculator example, which required both fields to be provided and be parsable as numbers.

As of version 1.1 struts provides a set of tools that eliminate the need to repeatedly write code for many common validation conditions. The first step to using these tools is to enable the ValidatorPlugIn, which is done by adding the following to struts-config.xml:

<plug-in
className="org.apache.struts.validator.ValidatorPlugIn">
<set-property
property="pathnames"
value="/WEB-INF/classes/config/validator-rules.xml,
/WEB-INF/classes/config/validation.xml"/>
</plug-in>

The pathnames argument is a list of files that contain XML definitions of validation rules and how those rules should be applied to various forms and fields. validator-rules.xml is provided as part of struts and contains definitions for many common validations. It is usually not necessary for users to modify this file. validation.xml specifies which tests are to be performed on which fields and can best be understood through an example.

<form-validation>
<formset>
<form name="calculatorForm2 ">
<field property="number1" depends="required,double ">
<arg0 key="calculatorForm2.number1"/>
</field>
<field property="number2" depends="required,double ">
<arg0 key="calculatorForm2.number2"/>
</field>
</form>
</formset>
</form-validation>

The name in the form tag must match a corresponding form-bean in struts-config.xml. Here, calculatorForm2 is used, which will be defined shortly. Each field node specifies a field for which validation should be done. The depends attribute is a comma-separated list of validations that should be performed. Each entry is defined in validator-rules.xml and behaves as the name implies.requires demands that the field is not empty, and double indicates that the field must be parsable as a number.

The key value names an entry in the application resources that specifies the name of the field. Additionally, the validator uses a number of properties to contain error messages. The full set of properties that must be added to the resources file for this example are

calculatorForm2.number1=The first number
calculatorForm2.number2=The second number
errors.required=<li>{0}   is a required field</li>
errors.double=<li>{0}   is improperly formatted</li>

The errors.required entry is the message that the validator will use when a required field is not provided. Within this message {0} will be replaced by the property named by arg0 from the field. If the first number is not provided, the result will be, as expected,

<li>The first number is a required field</li>

Messages can have any number of such parameters that will be called arg1, arg2, and so on, and will appear in error declarations as {1}, {2}, and so on.

Using the validator the form bean becomes much simpler, and it is shown in Listing 19.8.

Listing 19.8. A simpler calculator form bean
package com.awl.toolbook.chapter19;
import org.apache.struts.validator.ValidatorForm;
public class CalculatorForm2 extends ValidatorForm {
private double number1;
public double getNumber1() {return number1; }
public void setNumber1(double number1) {
this.number1 = number1;
}
private double number2;
public double getNumber2() {return number2; }
public void setNumber2(double number2) {
this.number2 = number2;
}
}

Note that Listing 19.8 extends ValidatorForm instead of actionForm. ValidatorForm provides a validate() method that performs all the validations specified in validations.xml. It is legal to override this method in derived classes as long as super.validate() is called first. This makes it possible to mix built-in and custom validations.

The action form also becomes simpler, as shown in Listing 19.9.

Listing 19.9. A simpler calculator action
package com.awl.toolbook.chapter19;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.text.DecimalFormat;
import java.util.Locale;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import org.apache.struts.util.*;
public final class CalculatorAction2 extends Action {
public ActionForward perform(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
CalculatorForm2 calcForm = (CalculatorForm2) form;
// Build the model
Calculator calc         = new Calculator();
calc.setNumber1(calcForm.getNumber1());
calc.setNumber2(calcForm.getNumber2());
calc.computeSum();
// Store the model in the request so the result
// page can get to it
request.setAttribute("calc",calc);
return (mapping.findForward("success"));
}
}

None of the parsing is necessary this time because by the time this action is called, struts will have ensured that the inputs are of the correct form and populated the double fields in CalculatorForm2.

All that remains is to connect everything together in struts-config.xml:

<form-bean name="calculatorForm2"
type="com.awl.toolbook.chapter19.CalculatorForm2"/>
<action path="/calculator2"
type="com.awl.toolbook.chapter19.CalculatorAction2"
name="calculatorForm2"
scope="request"
validate="true"
input="/chapter19/calculator2.jsp">
<forward name="success"
path="/chapter19/calc_result2.jsp"/>
</action>

These exactly parallel the entries for the first version of the calculator, but different pages and classes are used so the two examples can coexist.

There are many other validations in addition to required and double. One particularly useful one is called mask, which requires that the specified field matches a particular regular expression. For example, a required field that allows only alphabetic characters could be represented as

<field property="someField"   depends="required,mask">
<arg0 key="testForm.someField"/>
<var>
<var-name>mask</var-name>
<var-value>^[A-Za-z]*$</var-value>
</var>
</arg0>
</field>

The use of mask in the depends attribute indicates that the regular expression test should be performed, and the entries in the var node indicate what that regular expression is. The struts validator uses the ORO Perl5 expression library covered in Chapter 13.

There are a number of other validations that require parameters. Such parameters are specified by a var node whose var-name matches the name of the validation and whose var-value holds the parameter.