JSF 2 – composite-component – Bean validation fails due to component with empty value

bean-validationcomposite-componentformsjsf-2

i have a composite component (a captcha actually) which i use into a h:form.
I have the following error when i click on the submit button of my h:form.

16 janv. 2013 10:02:06 javax.faces.validator.BeanValidator validate
ATTENTION: cannot validate component with empty value: captcha:captchaText

Here is the xhtml code of the captcha's composite-component

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
  xmlns:composite="http://java.sun.com/jsf/composite" xmlns:xcc="http://java.sun.com/jsf/composite/components">
<h:body>

  <composite:interface>
    <composite:attribute name="id" type="java.lang.String" />
    <composite:attribute name="imageWidth" type="java.lang.Integer" />
    <composite:attribute name="imageHeight" type="java.lang.Integer" />
    <composite:attribute name="imageClass" type="java.lang.String" />
    <composite:attribute name="inputClass" type="java.lang.String" default="" />
    <composite:attribute name="placeholder" type="java.lang.String" default="" />
    <composite:attribute name="failureMessage" type="java.lang.String" default="Captcha validation failed" />

    <composite:editableValueHolder name="captchaText" />
  </composite:interface>

  <composite:implementation>
    <h:inputText id="captchaText" required="true" styleClass="#{cc.attrs.inputClass}" placeholder="#{cc.attrs.placeholder}"
      autocomplete="off" maxlength="10">
      <f:param name="failureMessage" value="#{cc.attrs.failureMessage}" />
      <f:validateLength minimum="6" />
      <f:validator validatorId="captchaValidator" />
    </h:inputText>
    <h:graphicImage id="captchaImage" alt="" style="margin-left:3px;" styleClass="#{cc.attrs.imageClass}" width="#{cc.attrs.imageWidth}"
      height="#{cc.attrs.imageHeight}" value="__captcha.jpg" />
  </composite:implementation>

</h:body>
</html>

Here is the Captcha's JSF Validator code.

import javax.faces.application.FacesMessage;


import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

import net.paissad.waqtsalat.servlet.CaptchaServlet;

    @FacesValidator(CaptchaValidator.VALIDATOR_ID)
    public class CaptchaValidator implements Validator {

    public static final String VALIDATOR_ID = "captchaValidator";

    @Override
    public void validate(final FacesContext context, final UIComponent component, final Object value) throws ValidatorException {

        final String enteredValue = (String) value;
        final String expectedValue = (String) context.getExternalContext().getSessionMap()
            .get(CaptchaServlet.CAPTCHA_KEY);

        final boolean ok = (enteredValue != null) && (enteredValue.equals(expectedValue));
        if (!ok) {
            String summary = (String) component.getAttributes().get("failureMessage");
             if (summary == null) summary = "";
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, summary, summary));
        }
    }

}

I don't it is really necessary to show the code of the CaptchaServlet which build the real captcha image. All i can say is that it does work good. I inspired from this code here.

here is basically how i used the composite-component in my form. (This is not my real use case btw)

<h:form>
    <xcc:captcha id="captcha" imageClass="img-rounded" placeholder="#{i18n.Captcha_enter_code_here}" failureMessage="Captcha validation failed" />
    <h:commandButton styleClass="btn btn-success" type="submit" value="#{i18n.Submit}"
            actionListener="#{accountRegistrationController.register}" action="success" />
</h:form>

The form is rendered like this (with French localization) :

enter image description here

I prefer using the composite-component + validator + servlet
I prefer to avoid the use of a controller bean (@Named / @RequestScoped) with a method for verifying the Captcha's entered value.

When i debug the Validator code in Eclipse, the code behaves correctly. The only wrong stuff is the following part of code does never retrieve the "failureMessage" attribute from the Captcha's component, how can i solve this too ? It is always null.

String summary = (String) component.getAttributes().get("failureMessage");

So, how can i solve the Bean validation problem ?
And how can i retrieve correctly the attribute 'failureMessage' in my Validator ?

I've tried lot's of stuffs, and now i rely on you.
Thanks in advance for helping.

PS : i'm currently using TomEE 1.5+ , Java6.

Best Answer

Looks like your inputText tag is missing the value attribute. The value attribute does the binding between the input and the bean.

<h:inputText value="#{yourBean.yourValue" ...
Related Topic