Rabu, 29 Januari 2014

Validator for multiple fields



Notice


The JSF utility library OmniFaces has several useful multi-field validators such as , which may end up to be easier than homegrowing one. See also the javadoc of the base class ValidateMultipleFields.







Introduction


Validators in JSF are nice. They, however, have its shortcomings. They will by default validate only one field at once. There is no standard way to attach one validator to multiple fields. Although there are some situations where you want this kind of functionality. For example validating the password confirmation field, validating the range of two numeric or date values (e.g. the one have to be lesser than the other), validating correctness of the three separate day, month and year fields, etcetera.



The cleanest solution would be to create a custom component which renders two or more components and use a specific validator for that, but that would involve more work. The easiest solution in this particular case is to attach the validator to the first component of the group (components are rendered, validated, converted and updated in the same order as you define them in the JSF view) and pass the other component(s) as unique f:attribute facet(s) along the first component. Then in the validator you can get the desired component(s) using UIComponent#getAttributes().


Back to top


Basic example


This example demonstrates a basic registration form with one username field and two password fields. The value of the second password field should equal to the value of the first password field before the action method may be invoked. The stuff is tested in a Java EE 5.0 environment with Tomcat 6.0 with Servlet 2.5, JSP 2.1 and JSF 1.2_07 (currently called Mojarra by the way!).



Here is the relevant JSF code. Note the binding="#{confirm}" of the second password field. It binds the component to the view and makes it available elsewhere by #{confirm}. This is an instance of the UIInput class which has a getSubmittedValue() method to get the submitted value. Note the f:attribute of the first password field, its value should point to the component of the second password field #{confirm}. Also note that the second password field doesn't have any value bound to the backing bean as this is unnecessary in this specific case.



 id="register">
columns="3">
for="username" value="Username" />
id="username" value="#{myBean.username}" required="true" />
for="username" style="color: red;" />

for="password" value="Password" />
id="password" value="#{myBean.password}" required="true">
validatorId="passwordValidator" />
name="confirm" value="#{confirm}" />

for="password" style="color: red;" />

for="confirm" value="Confirm password" />
id="confirm" binding="#{confirm}" required="true" />
for="confirm" style="color: red;" />

/>
value="Register" action="#{myBean.register}" />
for="register" style="color: green;" />



And now the validator code:



package mypackage;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

public class PasswordValidator implements Validator {

// Actions ------------------------------------------------------------------------------------

public void validate(FacesContext context, UIComponent component, Object value)
throws ValidatorException
{
// Cast the value of the entered password to String.
String password = (String) value;

// Obtain the component and submitted value of the confirm password component.
UIInput confirmComponent = (UIInput) component.getAttributes().get("confirm");
String confirm = confirmComponent.getSubmittedValue();

// Check if they both are filled in.
if (password == null || password.isEmpty() || confirm == null || confirm.isEmpty()) {
return; // Let required="true" do its job.
}

// Compare the password with the confirm password.
if (!password.equals(confirm)) {
confirmComponent.setValid(false); // So that it's marked invalid.
throw new ValidatorException(new FacesMessage("Passwords are not equal."));
}

// You can even validate the minimum password length here and throw accordingly.
// Or, if you're smart, calculate the password strength and throw accordingly ;)
}

}


The appropriate test backing bean look like:



package mypackage;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

public class MyBean {

// Init ---------------------------------------------------------------------------------------

private String username;
private String password;

// Actions ------------------------------------------------------------------------------------

public void register() {

// Just for debug. Don't do this in real! Hash the password, save to DB and forget it ;)
System.out.println("Username: " + username);
System.out.println("Password: " + password);

// Show succes message.
FacesContext.getCurrentInstance().addMessage("register", new FacesMessage("Succes!"));
}

// Getters ------------------------------------------------------------------------------------

public String getUsername() {
return username;
}

public String getPassword() {
return password;
}

// Setters ------------------------------------------------------------------------------------

public void setUsername(String username) {
this.username = username;
}

public void setPassword(String password) {
this.password = password;
}

}


Finally the relevant part of the faces-config.xml:






passwordValidator
mypackage.PasswordValidator



myBean
mypackage.MyBean
request




That's all, folks!



Back to top



Copyright - There is no copyright on the code. You can copy, change and distribute it freely. Just mentioning this site should be fair.


(C) December 2007, BalusC



Source:http://balusc.blogspot.com/2007/12/validator-for-multiple-fields.html

Tidak ada komentar:

Posting Komentar