JSF 2 - Validar múltiplos valores

Fala Galera.

Estou estudando JSF 2.0 e me deparei com o seguinte problema.

Tenho uma lista com dois inputText’s, preço Mínimo e preço Máximo. Quando o usuário realizar a pesquisa preciso validar se o preço mínimo é menor que o preço máximo.

Tenho uma classe chamada ValidatePreco que implemeta “javax.faces.validator.Validator”, porém preciso sobrescrever o método validate e esse método so aceita um valor.

Existe um jeito de eu recuperar os dois valores ao mesmo tempo para fazer a validação?

Segue a classe e a tela abaixo:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <f:view>
            <h:form>
                <h:inputText id="txtMinPreco"/>
                <h:inputText id="txtMaxPreco"/>
            </h:form>
            <h:form>
                <h:dataTable value="#{ListaCdBean.all}" var="cd">
                    <h:column>
                        <h:commandLink action="cd" value="Editar">
                            <f:setPropertyActionListener value="#{cd}" target="#{CdBean.cd}"/>
                        </h:commandLink>
                    </h:column>
                    <h:column>
                        <h:commandLink action="#{ListaCdBean.excluir(cd)}" value="Excluir">
                        </h:commandLink>
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            id
                        </f:facet>
                        #{cd.id}
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            Cantor
                        </f:facet>
                        #{cd.cantor}
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            Título
                        </f:facet>
                        #{cd.titulo}
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            Preço
                        </f:facet>
                        #{cd.preco}
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            Ano
                        </f:facet>
                        #{cd.anoLancamento.anoLancamento}
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            Gênero
                        </f:facet>
                        #{cd.genero.genero}
                    </h:column>
                </h:dataTable>
            </h:form>
        </f:view>
    </h:body>
</html>
package s2.validator;

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;

@FacesValidator("ValidatePreco")
public class ValidatePreco implements Validator {

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

Obrigado.

como voce está fazendo a pesquisa?? É um commandButton que tem a action?

sim.

entao tenta assim…
na action que faz a pesquisa voce valida esses valores se verdadeiro, faz a pesquisa, se falso voce manda uma mensagem para o usuario dizendo que os valores estao incorretos…

Então Caio, isso eu já até fiz, mas eu gostaria de saber se tem como eu validar isso antes dele jogar os valores no modelo, na camada de validação mesmo, e dessa forma eu já estou com os valores no objeto.

Estou tentando fazer isso porque sei que no struts eu consigo, mas em JSF está meio complicado.

Bom dia.
Pelo que entendi você quer fazer uma validação do lado client, sendo assim terá que validar com javaScript.
Flw

Eu já trabalho à algum tempo com JSF e ai vai a minha respósta: LARGA ESSA DROGA!!!

Bom eu imagino que você não deve ter gostado muito dessa respósta mesmo porque você deve pensar, assim como eu já pensei, que JSF é um bom framework.
Se esse for o seu caso você tem duas opções:

1 - Esperar pela versão 2.2 do JSF e pela boa vontade de adicionar esse recurso básico que qualquer framework (menos JSF) suporta.
2 - Implementar um custom componente que contenha as dois inputTexts que você quer é usar um POJO como modelo desse componente. Dessa forma o seu validator vai receber esse POJO e você vai poder validar.

Como eu duvido muito que a primeira solução seja viável para você… Prepare-se, para implementar a sua solução você vai precisar de umas 3 classes quando tudo que você queria é algo do tipo
if (precoMinimo >= precoMaximo).

Na verdade, pelo que entendi o JSF tem um ciclo de vida, ele é divido em várias partes.

1 - Restaurar Visão.
2 - Aplicar valores de requisição.
3 - Processar validações.
4 - Atualizar os valores do modelo.
5 - Invocar a aplicação.
6 - Renderizar resposta.

O que eu queria era que, quando ele chegasse em “Processar validações” eu conseguisse aplicar minha validação com os parâmetros necessários, porém não sei como passar dois parâmetros para essa fase, pois sei que se minha validação falhar o própio JSF vai abortar e retornar a mensagem que eu colocar para essa validação.

Um parâmetro eu consigo passar mas dois eu não sei como fazer.

Com javascript, pelo que entendi, eu saio fora desse ciclo de vida, posso estar errado.

Obrigado, dev.rafael.

Mas infelizamente não posso “LARGAR ESSA DROGA”, rs, estou fazendo um treinamento pela empresa.

Mas muito obrigado pelas opções, vou tentar fazer alguma coisa assim.

Se conseguir posto o resultado.

Está!! Javascript não tem nada haver com o rolo todo.

O seu problema é que na fase de validação o JSF executa Validators e esses Validators, na especificação atual do framework, só suportam validação o valor de um único UIInput. O que você precisa é de um UIInput que tenha os valores dos dois campos simultaneamente, pois só assim na fase de validação o seu Validador os receberia ambos.

Esse problema é velho no JSF e o JCP nunca o resolveu, então se você não quer aceitar a sugestão de colocar a validação dessa form durante a fase Invoke Application(ou seja dentro do action) o jeito complicado é o único.

Acho que agora a resposta sobre o javascript ficou mais clara, rs.

Bom dia a todos!

Uma alternativa para este tipo de validação com mais de um valor é no método do seu ManagedBean, que é chamado pela view, você fazer a comparação que for necessária e caso não atenda às condições esperadas acontece o seguinte:

FacesContext.getCurrentInstance().addMessage("seuForm:seuCampo", new FacesMessage("O valor mínimo deve ser menor que o máximo!"));
return null;

Dessa forma a mensagem de erro aparecerá no seu elemento h:message ou h:messages.

Fica com Deus!

Uma outra forma é implementar mais ou menos o seguinte:

View:

<h:outputText value="*Em@il:" />
<h:inputText id="email" binding="#{emailComponent}" value="#{securityController.email}" required="true"/>                   
<br/>
<h:outputText value="*Password: " />
<h:inputSecret id="password" value="#{securityController.password}" validator="#{securityController.validateEmailAndPassword}" required="true">
    <f:attribute name="emailComponent" value="#{emailComponent}" />
</h:inputSecret> 

ManagedBean:

public void validateEmailAndPassword(FacesContext context, UIComponent component, Object value) throws ValidatorException {
    UIInput emailComponent = (UIInput) component.getAttributes().get("emailComponent");
    String email = (String) emailComponent.getValue();
    String password = (String) value;

    // ...
}

Fonte