Reputation: 9266
In my application, I have the following Validator
to validate a captcha input:
@Named(value = "simpleCaptchaValidator")
@RequestScoped
public class SimpleCaptchaValidator implements Validator {
@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
Captcha secretCaptcha = (Captcha) session.getAttribute(Captcha.NAME);
// Clear the input field
EditableValueHolder input = (EditableValueHolder) component;
input.resetValue();
// Display an error msg if the entered words are wrong
if (!secretCaptcha.isCorrect(value.toString())) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Failed!", "You have entered wrong words.");
throw new ValidatorException(msg);
}
}
}
The above Validator
works great on non-Ajax requests when users do enter wrong captcha words. However, if users enter the right captcha words but there's a validation failed on other components, the input field for the captcha is not cleared.
I'd be very grateful if you could show me how to solve the above problem.
Upvotes: 2
Views: 610
Reputation: 1108632
It doesn't work because the EditableValueHolder#resetValue()
is invoked at the wrong moment. You should be invoking it during invoke application phase (at least, after update model values phase), not in middle of validations phase. Namely, when the validate()
method returns without exception, then JSF will still set the validated value as component's local value. When the validations phase has failed in general, then the update model values phase won't be invoked and the local value still sticks around in the component.
Based on the information provided so far, it isn't possible to propose the right approach. If this is a custom component, then just don't write the value during encode()
. Or, if this is an existing component, then perhaps your best bet is to create a custom converter which stores the submitted value as a custom component attribute and then returns null
in getAsObject()
. In the validator, you then just grab that custom component attribute as value. As last resort, attach a PhaseListener
which resets the component at the right moment.
Upvotes: 2