Using Standard Validators It is difficult to imagine a web application that should not perform a healthy dose of data validation. Since validation is so pervasive, you want it to be easy to use and extend. JSF fits the bill in both respects by providing a handful of standard validators and affording you a simple mechanism for implementing your own validators. A key role of validation is to protect the model. Because JSF uses separate phases for processing validations and updating model values, you can be assured that the model is not put into an inconsistent state if some of the inputs cannot be validated. Validating String Lengths and Numeric Ranges It is easy to use JSF validators within JSF pages add validator tags to the body of a component tag, like this: <h:inputText value="#{payment.card}"> <f:validateLength minimum="13"/> </h:inputText> The preceding code fragment adds a validator to a text field; when the text field's form is submitted, the validator makes sure that the string contains at least 13 characters. When validation fails (in this case, when the string has 12 or fewer characters), validators generate error messages associated with the guilty component. These messages can later be displayed in a JSF page by the h:message or h:messages tag. Note | JavaServer Faces 1.x does not explicitly support client-side validation. All validation occurs on the server after the user has submitted the form data. If you want validation to occur inside the browser, you need to supply custom tags that contain the appropriate JavaScript commands. See Chapter 13 for details. | JavaServer Faces has built-in mechanisms that let you carry out the following validations: -
Checking the length of a string -
Checking limits for a numerical value (for example, > 0 or 100) -
Checking that a value has been supplied Table 6-4 lists the standard validators that are provided with JSF. You saw the string length validator in the preceding section. To validate numerical input, you use a range validator. For example, <h:inputText value="#{payment.amount}"> <f:validateLongRange minimum="10" maximum="10000"/> </h:inputText> Table 6-4. Standard Validators JSP Tag | Validator Class | Attributes | Validates | f:validateDoubleRange | DoubleRangeValidator | minimum, maximum | A double value within an optional range | f:validateLongRange | LongRangeValidator | minimum, maximum | A long value within an optional range | f:validateLength | LengthValidator | minimum, maximum | A String with a minimum and maximum number of characters | The validator checks that the supplied value is 10 and 10000. All the standard validator tags have minimum and maximum attributes. You need to supply one or both of these attributes. Checking for Required Values To check that a value is supplied, you do not nest a validator inside the input component tag. Instead, you supply the attribute required="true": <h:inputText value="#{payment.date}" required="true"/> All JSF input tags support the required attribute. You can combine the required attribute with a nested validator: <h:inputText value="#{payment.card}" required="true"> <f:validateLength minimum="13"/> </h:inputText> Caution | If the required attribute is not set and a user supplies a blank input, then no validation occurs at all! Instead, the blank input is interpreted as a request to leave the existing value unchanged. | An alternate syntax for attaching a validator to a component is to use the f:validator tag. You specify the ID of the validator and the validator parameters like this: <h:inputText value="#{payment.card}"> <f:validator validator> <f:attribute name="minimum" value="13"/> </f:validator> </h:inputText> Yet another way of specifying the validator is with a validator attribute to the component tag (see "Validating with Bean Methods" on page 259). Note | As of JSF 1.2, the f:validateLength, f:validateLongRange, f:validateDoubleRange, and f:validator tags have an optional binding attribute. This allows you to tie a validator instance to a backing bean property of type javax.faces.validator.Validator. | Displaying Validation Errors Validation errors are handled in the same way as conversion errors. A message is added to the component that failed validation, the component is invalidated, and the current page is redisplayed immediately after the Process Validations phase has completed. You use the h:message or h:messages tag to display the validation errors. For details, see "Displaying Error Messages" on page 226. As of JSF 1.2, you can supply a custom message for a component by setting the requiredMessage or validatorMessage attribute, like this: <h:inputText value="#{payment.card}" required="true"> requiredMessage="#{msgs.cardRequired}" validatorMessage="#{msgs.cardInvalid}"> <f:validateLength minimum="13"/> </h:inputText> You can also globally override the default validator messages shown in Table 6-5. Define a message bundle for your application and supply messages with the appropriate keys, as shown under "Changing the Text of Standard Error Messages" on page 228. Table 6-5. Standard Validation Error Messages Resource ID | Default Text | Reported By | javax.faces.component. UIInput.REQUIRED
| {0}: Validation Error: Value is required. | UIInput with required attribute when value is missing | javax.faces.validator. DoubleRangeValidator.NOT_IN_RANGE javax.faces.validator. LongRangeValidator.NOT_IN_RANGE
| {2}: Validation Error: Specified attribute is not between the expected values of {0} and {1} | DoubleRangeValidator and LongRangeValidator when value is out of range and both minimum and maximum are specified | javax.faces.validator. DoubleRangeValidator.MAXIMUM javax.faces.validator. LongRangeValidator.MAXIMUM
| {1}: Validation Error: Value is greater than allowable maximum of "{0}". | DoubleRangeValidator or LongRangeValidator when value is out of range and only maximum is specified | javax.faces.validator. DoubleRangeValidator.MINIMUM javax.faces.validator. LongRangeValidator.MINIMUM
| {1}: Validation Error: Value is less than allowable minimum of "{0}". | DoubleRangeValidator or LongRangeValidator when value is out of range and only minimum is specified | javax.faces.validator. DoubleRangeValidator.TYPE javax.faces.validator. LongRangeValidator.TYPE
| {0}: Validation Error: Value is not of the correct type. | DoubleRangeValidator or LongRangeValidator when value cannot be converted to double or long | javax.faces.validator. LengthValidator.MAXIMUM
| {1}: Validation Error: Value is greater than allowable maximum of "{0}". | LengthValidator when string length is greater than maximum | javax.faces.validator. LengthValidator.MINIMUM
| {1}: Validation Error: Value is less than allowable minimum of "{0}". | LengthValidator when string length is less than minimum | Note | In JSF 1.1, the input label was not included in the validation messages. The key for the "not in range" messages was javax.faces.validator.NOT_IN_RANGE. | Bypassing Validation As you saw in the preceding examples, validation errors (as well as conversion errors) force a redisplay of the current page. This behavior can be problematic with certain navigation actions. Suppose, for example, you add a "Cancel" button to a page that contains required fields. If the user clicks "Cancel", leaving a required field blank, then the validation mechanism kicks in and forces the current page to be redisplayed. It would be unreasonable to expect your users to fill in required fields before they are allowed to cancel their input. Fortunately, a bypass mechanism is available. If a command has the immediate attribute set, then the command is executed during the Apply Request Values phase. Thus, you would implement a "Cancel" button like this: <h:commandButton value="Cancel" action="cancel" immediate="true"/> A Complete Validation Example The following sample application shows a form that employs all the standard JSF validation checks: required fields, string length, and numeric limits. The application makes sure that values are entered in all fields, the amount is between $10 and $10,000, the credit card number has at least 13 characters, and the PIN is a number between 1000 and 9999. Figure 6-6 shows typical validation error messages. A "Cancel" button is also provided to demonstrate the validation bypass. Figure 6-7 shows the directory structure of the application. Listing 6-5 contains the JSF page with the validators. Listing 6-5. validator/web/index.jsp 1. <html> 2. <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> 3. <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> 4. <f:view> 5. <head> 6. <link href="styles.css" rel="stylesheet" type="text/css"/> 7. <title><h:outputText value="#{msgs.title}"/></title> 8. </head> 9. <body> 10. <h:form> 11. <h1><h:outputText value="#{msgs.enterPayment}"/></h1> 12. <h:panelGrid columns="3"> 13. <h:outputText value="#{msgs.amount}"/> 14. <h:inputText label="#{msgs.amount}" 15. value="#{payment.amount}" required="true"> 16. <f:convertNumber minFractionDigits="2"/> 17. <f:validateDoubleRange minimum="10" maximum="10000"/> 18. </h:inputText> 19. <h:message for="amount" style/> 20. 21. <h:outputText value="#{msgs.creditCard}"/> 22. <h:inputText label="#{msgs.creditCard}" 23. value="#{payment.card}" required="true"> 24. <f:validateLength minimum="13"/> 25. <f:attribute name="requiredMessage" value="#{msgs.cardRequired}"/> 26. </h:inputText> 27. <h:message for="card" style/> 28. 29. <h:outputText value="#{msgs.expirationDate}"/> 30. <h:inputText label="#{msgs.expirationDate}" 31. value="#{payment.date}" required="true"> 32. <f:convertDateTime pattern="MM/yyyy"/> 33. </h:inputText> 34. <h:message for="date" style/> 35. </h:panelGrid> 36. <h:commandButton value="Process" action="process"/> 37. <h:commandButton value="Cancel" action="cancel" immediate="true"/> 38. </h:form> 39. </body> 40. </f:view> 41.</html>
| |