[Tutorial] reCAPTCHA do Google para JSF2

Graças ao tutorial do Himanshu, http://myjavabuddy.blogspot.com.br/2013/04/implementing-captcha-control-with-jsf-20.html,
consegui implementar o reCAPTCHA do google em meu projeto, com algumas diferenças, ai eu deixo o codigo dele com o que eu fiz para
a comunidade.

RecaptchaComponent.java

@FacesComponent(createTag = true, tagName = "recaptcha", namespace = "http://himanshu/jsf-custom-components/", value = "com.himanshu.jsf.custom.recaptcha")
public class RecaptchaComponent extends UIInput {

    static final String RecaptchaComponent_FAMILY = "RecaptchaComponentFamily";
    private String publicKey;
    private String privateKey;

    @Override
    public final String getFamily() {
        return RecaptchaComponent_FAMILY;
    }

    public String getPublicKey() {
        return publicKey;
    }

    public void setPublicKey(String publicKey) {
        this.publicKey = publicKey;
    }

    public String getPrivateKey() {
        return privateKey;
    }

    public void setPrivateKey(String privateKey) {
        this.privateKey = privateKey;
    }

    @Override
    public void decode(FacesContext arg0) {
        super.decode(arg0);
    }

    @Override
    public void encodeBegin(FacesContext arg0) throws IOException {
        // TODO Auto-generated method stub
        super.encodeBegin(arg0);
    }

    @Override
    public void encodeEnd(FacesContext arg0) throws IOException {

        String publicKey = this.getPublicKey();
        String privateKey = this.getPrivateKey();

        if (publicKey == null || privateKey == null) {
            throw new IllegalArgumentException("reCaptcha keys cannot be null. This is probably a component bug.");
        }

        ReCaptcha c = ReCaptchaFactory.newReCaptcha(publicKey, privateKey, false);
        String createRecaptchaHtml = c.createRecaptchaHtml(null, null);
        ResponseWriter writer = arg0.getResponseWriter();
        writer.write(createRecaptchaHtml);
    }

    /*
     * This is overridden to make sure that the Captcha validator which is included in
     * this custom component gets executed
     * (non-Javadoc)
     * @see javax.faces.component.UIInput#validate(javax.faces.context.FacesContext)
     */
    @Override
    public void validate(FacesContext ctx) {
        Validator[] validators = getValidators();
        for (Validator v : validators) {
            try {
                v.validate(ctx, this, null);
            } catch (ValidatorException ex) {
                setValid(false);
                FacesMessage message = ex.getFacesMessage();
                if (message != null) {
                    message.setSeverity(FacesMessage.SEVERITY_ERROR);
                    ctx.addMessage(getClientId(ctx), message);
                }
            }
        }
        super.validate(ctx);
    }
}

RecaptchaValidator.java

@FacesValidator(value = "com.himanshu.jsf.captcha.validator")
public class RecaptchaValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        HttpServletRequest request = HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        RecaptchaComponent c = (RecaptchaComponent) component;
        String remoteAddr = request.getRemoteAddr();
        ReCaptchaImpl reCaptcha = new ReCaptchaImpl();

        String privateKey = null;
        privateKey = c.getPrivateKey();

        reCaptcha.setPrivateKey(privateKey);

        String challenge = request.getParameter("recaptcha_challenge_field");
        String uresponse = request.getParameter("recaptcha_response_field");
        ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(remoteAddr, challenge, uresponse);

        if (!reCaptchaResponse.isValid()) {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Captcha invalido", "Captcha invalido"));
        }
    }
}

No XHTML

<ui:composition  xmlns="http://www.w3.org/1999/xhtml"
                 xmlns:ui="http://java.sun.com/jsf/facelets"
                 xmlns:h="http://xmlns.jcp.org/jsf/html"
                 xmlns:f="http://xmlns.jcp.org/jsf/core"
                 xmlns:hj="http://himanshu/jsf-custom-components/">
//site
       <h:form>
//restante do site
            <hj:recaptcha id="rc" publicKey="tuachavepublica"
                          privateKey="tuachaveprivada">
                <f:validator validatorId="com.himanshu.jsf.captcha.validator"/>
            </hj:recaptcha>
            <h:commandButton value="Ação" action="#{Bean.acaoDeQualquerCoisa()}"/>
        </h:form>
</ui:composition>

Só tem um pequeno [size=24]PÔREM[/size] nisso, cada vez que subir a aplicação, tem que alterar esta
parte no RecaptchaValidator.java

e vice versa, senão dará exception, no meu caso isso acontece sempre.