JBoss.orgCommunity Documentation
JavaServer Faces 2 provides built-in support for bean validation as per the Java Specification Request JSR-303 standard. As such, containers must validate model objects. Validation is performed at different application tiers according to annotation-based constraints. Refer to http://jcp.org/en/jsr/detail?id=303 for further details on the JSR-303 specification.
Example 6.1, “JSR-303 validation annotations” shows an example JSF managed bean. The bean includes JSR-303 annotations for validation. Validation annotations defined in this way are registered on components bound to the bean properties, and validation is triggered in the Process Validation phase.
Example 6.1. JSR-303 validation annotations
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
@ManagedBean
@RequestScoped
public class UserBean {
@Size(min=3, max=12)
private String name = null;
@Pattern(regexp = "^[\\w\\-]([\\.\\w])+[\\w]+@([\\w\\-]+\\.)+[a-zA-Z]{2,4}$" , message="Bad email")
private String email = null;
@Min(value = 18)
@Max(value = 99)
private Integer age;
//...
//Getters and Setters
}
Bean validation in both JavaServer Faces and RichFaces requires the JSR-303 implementation. The implementation is bundled with JEE 6 Application Server™.
If using Tomcat™ or another simple servlet container, add the validation-api
Java Archive and a validation provider (such as Hibernate Validator™) to your application libraries.
The validation built in to JavaServer Faces 2 occurs on the server side. The <rich:validator>
behavior adds client-side validation to a control based on registered server-side validators. It provides this validation without the need to reproduce the server-side annotations. The <rich:validator>
behavior triggers all client validator annotations listed in the relevant managed bean.
The <rich:validator>
behavior is added as a child element to any input control. The value of the input control must reference a managed bean. The content of the input control validates on the client-side based on registered server-side validators included in the managed bean.
JSF validation tags, such as <f:validateLength>
and <f:validateDoubleRange>
tags, can be declared alongside <rich:validator>
behaviors. However, because this duplicates the validation processes at both the view and model level, it is not recommended.
Use the <rich:message>
and <rich:messages>
components to display validation messages. The for
attribute of the <rich:message>
component references the id
identifier of the input control being validated.
Example 6.3. Messages
<rich:panel header="User information">
<h:panelGrid columns="3">
<h:outputText value="Name:" />
<h:inputText value="#{validationBean.name}" id="name">
<rich:validator />
</h:inputText>
<rich:message for="name" />
<h:outputText value="Email" />
<h:inputText value="#{validationBean.email}" id="email">
<rich:validator />
</h:inputText>
<rich:message for="email" />
<h:outputText value="Age" />
<h:inputText value="#{validationBean.age}" id="age">
<rich:validator />
</h:inputText>
<rich:message for="age" />
<h:outputText value="I agree the terms" />
<h:selectBooleanCheckbox value="#{validationBean.agree}" id="agree">
<rich:validator/>
</h:selectBooleanCheckbox>
<rich:message for="agree" />
</h:panelGrid>
</rich:panel>
Failed validation checks are reported using <rich:message>
components. The validation annotations in the managed bean are outlined in Example 6.1, “JSR-303 validation annotations”.
Use the event
attribute to specify which event on the input control triggers the validation process. By default, the <rich:validator>
behavior triggers validation when the input control is changed (event="change"
).
Example 6.4. Validation triggers
<h:inputText value="#{userBean.name}">
<rich:validator event="keyup"/>
</h:inputText>
The event
attribute is changed to the keyup
event, such that validation takes place after each key press.
If no client-side validation method exists for a registered server-side validator, Ajax fall-back is used. The <rich:validator>
behavior invokes all available client-side validators. If all the client-side validators return valid, RichFaces performs an Ajax request to invoke the remaining validators on the server side.
client-behavior-renderer-type
: org.richfaces.ClientValidatorRenderer
behavior-id
: org.richfaces.behavior.ClientValidator
handler-class
: org.richfaces.view.facelets.html.ClientValidatorHandler
behavior-class
: org.ajax4jsf.component.behavior.ClientValidatorImpl
client-behavior-renderer-class
: org.richfaces.renderkit.html.ClientValidatorRenderer
The <rich:graphValidator>
component is used to wrap a set of input components related to one object. The object defined by the <rich:graphValidator>
component can then be completely validated. The validation includes all object properties, even those which are not bound to the individual form components. Validation performed in this way allows for cross-field validation in complex forms.
The <rich:graphValidator>
component performs a clone()
method on the referenced bean instance during the validation phase. The cloned object is validated and triggers any required validation messages. As such, the model object remains clean, and the lifecycle is interrupted properly after the Process Validations phase.
Ensure the referenced object implements the Cloneable
interface, and allows a deep clone if required.
The <rich:graphValidator>
element must wrap all the input controls that are required to validate the object. The value
attribute names the bean for the validating object.
Example 6.5. Basic usage
The example demonstrates a simple form for changing a password. The two entered passwords must match, so a <rich:graphValidator>
component is used for cross-field validation.
<h:form>
<rich:graphValidator value="#{userBean}">
<rich:panel header="Change password">
<rich:messages/>
<h:panelGrid columns="3">
<h:outputText value="Enter new password:" />
<h:inputSecret value="#{userBean.password}" id="pass"/>
<rich:message for="pass"/>
<h:outputText value="Confirm the new password:" />
<h:inputSecret value="#{userBean.confirm}" id="conf"/>
<rich:message for="conf"/>
</h:panelGrid>
<a4j:commandButton value="Store changes"
action="#{userBean.storeNewPassword}" />
</rich:panel>
</rich:graphValidator>
</h:form>
The input controls validate against the following bean:
@ManagedBean
@RequestScoped
public class UserBean implements Cloneable {
@Size(min = 5, max = 15, message="Wrong size for password")
private String password;
@Size(min = 5, max = 15, message="Wrong size for confirmation")
private String confirm;
private String status = "";
@AssertTrue(message = "Different passwords entered!")
public boolean isPasswordsEquals() {
return password.equals(confirm);
}
public void storeNewPassword() {
FacesContext.getCurrentInstance().addMessage("", new FacesMessage(FacesMessage.SEVERITY_INFO, "Succesfully changed!", "Succesfully changed!"));
}
...
}
When validation occurs, the whole object is validated against the annotation contstraints. The @AssertTrue
annotation relies on the isPasswordsEqual()
function to check whether the two entered passwords are equal.
If the entered passwords do not match, an error message is displayed: