[RESOLVIDO] VRaptor - Forma de validação

67 respostas
V

Bom tarde pessoal !

Bom eu estou desenvolvendo um projeto pequeno aonde eu faço faculdade e comecei a utilizar o VRaptor + Hibernate.
Eu gostaria de saber qual a melhor forma de validação utilizando esses dois frameworks.

Por exemplo

Quero adicionar um produto no banco.
Tenho as validações na página normalmente mas preciso validar tbm no camada de negócio, se por exemplo, existe algum produto com o mesmo nome.

Qual a melhor forma de realizar isso? Caso o usuário tenha digitado um nome que já existe deve aparecer um alert na página informando isso.
Agradeço a paciẽncia !

Abraços
Vitor Morales

67 Respostas

K

Leia a documentação man! rs

O link abaixo tem tudo o q vc precisa

http://vraptor.caelum.com.br/pt/docs/validacao/

K

nesse caso… vc faz um ajax e verifica apenas se o nome está igual…
da pra fazer logo quando ele sai do input, instantâneo.

se vc tiver dificuldade grita que eu te dou as coordenadas

V

Opa!
Eu li a documentação sim… até acompanho ela.
Mas queria saber se existe modo melhor do que aquelas regras no controle.
Essa validação Ajax como é? Tem como da um exemplo ou indicar um link?
Abraços
Vitor Morales

K

vc pode fazer a sua!
de qualquer forma vc terá que fazer no controller… ou delegar pra uma outra camada que vai ter que retornar pro controller!
mas qual o problema de fazer no controller?

por ajax vc faria assim

vc manda o objeto e verifica no controller… vc faria + - assim

Ajax:

$("inputDoNomeDoProduto").blur(function(){

  var produto = {
      "produto.nome" : $("#idDoInput").val();
  }

  $.ajax({
    url: "produtos/valida",
    type: "POST",
    data : produto,
    dataType: "application/json",
    success : function(data){
        // faz alguma coisa se der certo
    }, 
    error : function () {
        // faz a lógica dependendo do status...
    }
  });
});
  
})

Controller:

public class ProdutoController{

    private Result result; 

    public ProdutoController(Result result){
        this.result = result;
    }

    @Get("/produtos/valida")
    public void validaProduto(Produto produto){
        //valida da forma que vc achar melhor

       //aqui tem várias formas...
       // retornar true ou false
       result.use(Results.json).from(expressãoBooleana).serialize();
     
       // ou tb se não tiver o produto devolve um status 200 
       result.nothing();

       // e se tem o nome daquele produto lança uma exceção  
    }

}

não sei se ficou muito claro pra vc… tenta aih

L

um jeito bom é usar as anotações do bean validations… tipo @NotNull, @NotEmpty, @Length, etc… e no VRaptor usar só:

validator.validate(objeto);
V

Pessoal.

Acho que esse modo vai resolver meu problema. Mas gostaria que fosse algo assim.

Ao enviar o formulário eu faço um monte de validação via javascript como se os campos estão no formato válido etc …
Gostaria uma requisição ajax que chamasse o método pra adicionar o produto e neste método tem as validações do tipo se já existe.
Caso tenha sucesso ou erro eu devo retornar uma mensagem específica pra tela e mostrar num alert por exemplo sem que seja necessário recarregar a página.

Como faria isso de um modo limpo ?
Eu implemento no .submit() do formulário umas validações javascript mesmo, mas necessito dessa lógica de validação também na camada da aplicação.

Agradeço a paciência ai !
Caso puderem dar um exemplo simples ou enviar alguma página que contenha um exemplo melhor ainda !

Abraços !

Vitor Morales

K

Eai vitor!

vc pode fazer por ajax msm! o exemplo que te dei funciona para o seu caso! ou não?

por exemplo… se vc quer validar se o login de um usuário já foi cadastrado… no envento onblur do seu input vc teria um evento

e nele teria uma função ajax que bateria no controller e o controller te retornaria uma resposta de que achou ou não esse nome no banco! ou qualquer outra lógica de validação que vc precisar!

qual o problema que vc está tendo?

V

É mais ou menos isso …
Mas como eu faço pra retornar um mensagem de erro do controlador pra página ?

Do tipo … dentro do método de adição possui alguns validações e pra cada validação eu preciso retornar uma mensagem diferente.

Como faço isso ?

e eu tenho essas validações javascript que não foram feitas por mim … como integraria isso dentro da função ajax submit ?

$('#newNetworkForm').submit(function() {         
         
        //Validações antes de executar o comando final
        if($("#nomeRede").val() == ""){            
            $('#nomeRede').css('border','red solid 1px');
            alert("Digite um nome");
            $('#nomeRede').focus();
            return false;
        }
        else
        if($("#localRede").val() == ""){
            
            $('#localRede').css('border','red solid 1px');
            alert("Digite um Local");
            $('#localRede').focus();
            return false;
        }
        else
        if($("#ipRede").val() == ""){
            
            $('#ipRede').css('border','red solid 1px');
            alert("Digite um IP");
            $('#ipRede').focus();
            return false;
        }
        else
        if($("#mascaraRede").val() == ""){
            
            $('#mascaraRede').css('border','red solid 1px');
            alert("Digite uma Máscara");
            $('#mascaraRede').focus();
            return false;
        }
        else
        //Validação de Ip e Mask
        if(validarIP($("#ipRede").val()) == false){
            
            alert("Digite um IP válido");
            $("#ipRede").val("");
            $("#ipRede").focus();
            return false;
        }
        else
        if(validarIP($("#mascaraRede").val()) == false){
            
            alert("Digite uma Máscara válida");
            $("#mascaraRede").val("");
            $("#mascaraRede").focus();
            return false;
        }
        else
        if((validarIP($("#gatewayRede").val()) == false))
        {
            alert("Digite um Gateway válido.");
            $("#gatewayRede").val("");
            $("#gatewayRede").focus();
            return false;
            
        }
    
        $("#ipRede").val(ip2long($("#ipRede").val()));        
        $("#mascaraRede").val(ip2long($("#mascaraRede").val()));       
        $("#gatewayRede").val(ip2long($("#gatewayRede").val()));
        
        
    });

Sem que eu precise redirecionar ou recarregar a página até pq a navegação tbm ta via ajax.
Ao clicar num item do menu ele carregar uma outra página dentro de um div na página principal

L

se vc quiser fazer isso batendo no servidor, vc pode fazer algo do tipo:

@Get("/bla")
public void valida(Objeto objeto) {
  validator.validate(objeto);
  validator.onErrorSendBadRequest();
  result.nothing();
}

daí vc pode fazer no javascript, antes do submit:

$.getJSON('.../bla').success(function() { form.submit() }).error(function(errors) {
   //mostra os erros
});
L

ah… use o jquery validator, é melhor.

V

Estou tentando da forma que foi passada ali via ajax

Mas me parece que tem algum erro na função. Alguma idéia ?
O método no controlador não está sendo chamado. O blur funciona se tirar o método $.ajax

Acho que aquilo lá resolve mesmo.

V

Resolvi

$("#nomeRede").blur(function(){  
        alert("Blur");        
        
        $.ajax({  
            url: '<c:url value="/network/validate"/>',  
            type: "POST",  
            data : {
                p: $("#nomeRede").val()
            }, 
            dataType: "application/json",  
            success : function(data){  
                alert("ok");
            },   
            error : function () {  
                alert("erro");  
            }
        });

Vou tentar fazer o que tinha imaginado aqui e respondo.

Vlw pessoal.

V

Ainda assim o método no controlador não foi chamado … o que pode ser ?
Ele sempre caio no caso de error do ajax;

Resolvi retirando o @Get do método e colocando @Path

L

é por causa do type: “POST”, … só trocar pra GET

V

Como faço pra retornar um texto no caso de erro pra função pra poder imprimir isso no alert?

Do tipo “Nome de rede existente”.

L

se vc usar o esquema do validator.onErrorSendBadRequest(), só adicionar uma validação antes disso:

if (alguma coisa)
  validator.add(new ValidationMessage("Nome de rede existente", "algo"));

isso vai estar disponível na função de success.

V

e como é esse esquema do validator.onErrorSendBadRequest() ?
hahaha

L

o que eu tinha falado numa msg anterior:

http://www.guj.com.br/java/293030-vraptor---forma-de-validacao#1558899

V

Eu mudei tudo.

Não consegui fazer da forma que eu queria.

O meu formulário agora envio via ajax e faço as validações dentro do metodo addNetwork.
Mas como eu retorno uma mensagem de erro dessa forma pra ser exibido no error: do ajax ?

L

tb falei numa msg anterior:

http://www.guj.com.br/java/293030-vraptor---forma-de-validacao/2#1559012

só adicionar erros de validação.

V

E como eu faço pra pegar essa mensagem na tela la no success ou no error ? ?

L
success: function(coisa) {
   // coisa é o retorno de sucesso
},
error: function(erros) {
   // só pegar esse erros e fazer o que vc quiser
}
V
function formAjaxSubmit()
    {
        $.ajax({
            type: "POST",
            url: "/network/add",
            data: {
                "p_network.name" : $("#nomeRede").val(),            
                "p_network.comments": $("#comentarioRede").val(),
                "p_network.baseIP": ip2long($("#ipRede").val()),
                "p_network.mask": ip2long($("#mascaraRede").val()), 
                "p_network.VLanID": $("#vlanIDRede").val(),
                "p_network.gateway": ip2long($("#gatewayRede").val()),
                "p_network.dns": $("#dnsRede").val()
            },
            success: function(success) {
                alert("ok");
            },
            error: function(error) {
                alert("Erro: "+ error);
            }
        })
    }
@Restrict
    @Post("/network/add")
    public void addNetwork(Network p_network)
    {                
         if(NETWORK_SERVICE.checkExistentNetwork(p_network.getName())) 
         {
            VALIDATOR.add(new ValidationMessage("Nome de rede existente.", "error")); 
                        
         }
         else
         {
            RESULT.nothing();
         }

    }

Ta imprimindo o object como faço pra pegar a mensagem que coloquei ali ? Essa era a pergunta.
Tem algo de errado nisso ?

K

Ficaria assim o seu controller:

if (NETWORK_SERVICE.checkExistentNetwork(p_network.getName())) {
	validator.add(new ValidationMessage("Nome de rede existente.", "error"));
}
validator.onErrorSendBadRequest();
result.nothing();

e o seu ajax ficaria assim:

function formAjaxSubmit(){
    //....
    success: function(success) {  
         alert("ok");  },
    statusCode: {
	400: function(data) {
	var resposta = JSON.parse(data.responseText);
        //faz qualquer coisa com a resposta... 
    }
}
V

Beleza …
Acho que agora eu entendi … mas fiz esses passos ai e não funcionou ainda.

function formAjaxSubmit()
    {
        $.ajax({
           //....
            success: function(success) {
                alert("Ok");
            },
            statusCode: {
                400: function(data)
                {
                    var response = JSON.parse(data.responseText);
                    alert("Erro:"+response);
                }
            }           
        })
    }
@Restrict
    @Post("/network/add")
    public void addNetwork(Network p_network)
    {                
         if(NETWORK_SERVICE.checkExistentNetwork(p_network.getName())) 
         {
            VALIDATOR.add(new ValidationMessage("Nome de rede existente.", "error"));                         
         }
         VALIDATOR.onErrorSendBadRequest();  
         RESULT.nothing;
         //...
L

ele chega a passar pelo controller?

V

Ta passando sim .

Tive que alterar só o endereço no ajax de “/network/add” para "network/add"
Mas ainda a mensagem não ta sendo exibida.

K

posta o código!

V
function formAjaxSubmit()
    {
        $.ajax({
            type: "POST",
            url: "network/add",
            data: {
                "p_network.name" : $("#nomeRede").val(),            
                "p_network.comments": $("#comentarioRede").val(),
                "p_network.baseIP": ip2long($("#ipRede").val()),
                "p_network.mask": ip2long($("#mascaraRede").val()), 
                "p_network.VLanID": $("#vlanIDRede").val(),
                "p_network.gateway": ip2long($("#gatewayRede").val()),
                "p_network.dns": $("#dnsRede").val()
            },
            success: function(success) {
                alert("Ok");
            },
            statusCode: {
                400: function(data)
                {
                    var response = JSON.parse(data.responseText);
                    alert("Erro:"+response);
                }
            }           
        })
    }
@Restrict
    @Post("/network/add")
    public void addNetwork(Network p_network)
    {                
         if(NETWORK_SERVICE.checkExistentNetwork(p_network.getName())) 
         {
            VALIDATOR.add(new ValidationMessage("Nome de rede existente.", "error"));                         
         }
         VALIDATOR.onErrorSendBadRequest();  
         RESULT.nothing();
         
//        NETWORK_SERVICE.addOrUpdateNetwork(p_network);
//        RESULT.nothing();
    }
L

troca tudo por:

$.getJSON("network/add", 
     {  
        "p_network.name" : $("#nomeRede").val(),              
        "p_network.comments": $("#comentarioRede").val(),  
        "p_network.baseIP": ip2long($("#ipRede").val()),  
        "p_network.mask": ip2long($("#mascaraRede").val()),   
        "p_network.VLanID": $("#vlanIDRede").val(),  
        "p_network.gateway": ip2long($("#gatewayRede").val()),  
        "p_network.dns": $("#dnsRede").val()  
     }).success(function(success) {  
         alert("Ok");  
     }).error(function(data) {  
               alert("Erro:"+data);              
     }) ;

e troque de @Post("/network/add") pra @Get("/network/add")

V

E é correto fazer isso usando Get ? formulários de cadastro do tipo não deveriam ser requisições Post não ?

K

V

Funfou porém a mensagem de erro ta “Erro: Object [objetc]” … algo do tipo.

V

O que ? … Falei besteira ? kkkkk

K

n, apenas respondi atrasado, n tinha visto q o lucas tinha respondido! rs

L

apareceu [object Object] pq é um json… um objeto javascript…

pra vc imprimir as mensagens vc pode fazer algo como:

.error(function(messages) {
     $(messages).each(function() {
         alert(this.message);
     });
});
V

Beleza… agora ta correto.
Mas a mensagem exibida esta sendo “Undefined”

E volta a pergunta … é correto usar requisições do tipo Get para cadastro e não Post ?

L

troque o alert por console.log(messages) e veja isso no console do browser (Developer tools no Chrome, Firebug no Firefox)

V

No final ta assim

responseText:"{“errors”: [{“message”: “Nome de rede existente.”,“category”: “error”}]}", status:400, statusText:“Bad Request”})

Interessante isso … usava essa ferramente mas não com log e console assim.

E ai ?

L

bom, como você viu a mensagem tá aí, só usá-la pra mostrar na tela do jeito que vc achar melhor.

V

Mas como eu pego a messagem … essa é a questão…

E sobre o envio do formulário ? É correto enviar pelo método Get ? Não post ?

L

dá uma olhada:

{\"errors\": [{\"message\": \"Nome de rede existente.\",\"category\": \"error\"}]}

ou seja, da variável que veio na função, vc tem que chamar variavel.errors[0].message

ex:

.error(function(data) {
 var mensagem = data.errors[0].message;
  alert(mensagem); // ou algo melhor
});

o formulário tem que ser @Post, mas nesse caso vc tá fazendo um ajax ANTES de submeter o formulário, só pra verificar se a validação está correta. Como esse ajax não modifica nada no servidor, pode ser @Get sem problemas.

V

entendi ali em cima …

Mas nesse caso cara
Eu vou fazer essa validação na hora que enviar o formulário e se caso existir algum registro com o mesmo nome eu retorno o erro senão já faço o cadastro no banco
Então deveria nesse caso enviar por post mesmo … tem alguma forma ?

L

o ideal é vc no success fazer um form.submit() de verdade… algo como isso:

$('#seu-form').submit(function() {
   var form = this;
   $.getJSON(.....)
     .success(function() {
         form.submit();
     }).error(.....);
});

assim se a requisição ajax deu tudo certo vc faz o submit de tudo.

L

faltou uma coisa, tem que dar um return false no final desse callback de submit

V

Entendi … mas como eu faço para não realizar o submit no caso de erro ?

E no caso de sucesso eu não gostaria de retornar pra nenhuma outra página … mas só enviar de volta uma mensagem de sucesso que vai aparecer num alert do tipo "Cadastro realizado’.

L

então o que vc quer é mais parecido com esse plugin do jquery:

http://malsup.com/jquery/form/

ele transforma o submit de um form qualquer em ajax.

V

Cara … perfeito … agora ta redondo … da uma olhada no código…

Só to com dificuldade pra descobrir ainda como imprimir a mensagem que enviei no validator do controller no caso de erro.

var formOptions = {
        beforeSubmit: validate,
        success: showSuccess,
        error: showError        
    };
    
    $('#newNetworkForm').ajaxForm(formOptions);
    
    function showError(responseText, status, err){
       
        console.log(status);
        alert("Errors");
    }
    
    function showSuccess(responseText, statusText, xhr, jqForm ){
        alert("Sucesso");       
    }
    
    function validate(formData, jqForm, options){
           
        
//....
V

coloquei esse código na função validate…

mas como no caso eu faço pra caso caia no error … ele retornar falso e cancelar o submit ?

$.getJSON("network/validate",   
         {    
            "p_network.name" : $("#nomeRede").val()           
        
         })   
         .error(function(data) {    
                   alert("Existe rede com o mesmo nome");
                   return false;
         }) ;
L

se vc vai fazer um ajaxForm já, faz a validação já no método que recebe o post do form, não precisa criar um método a mais…

daí vc consegue tratar o erro já no showError

V

Ok …
E no showError como receber a mensagem do validator ? To procurando aqui no console mas não to conseguindo.
Na variavel err vem o valor Not Found não a mensagem

L

a variavel responseText deveria ter o json, se passou por aquele onErrorSendBadRequest…

na verdade vc pode mudar esse onErrorSendBadRequest por:

validator.onErrorUse(json()).withoutRoot().from(validator.getErrors()).serialize();

o badRequest deve estar procurando uma jsp que não existe.

V

Ok …

Nesse código que passou o IDE não consegue resolver o json()… ta correto a escrita ?

L

Results.json() e esse Results é do VRaptor

V

Agora funcionou porém mesmo com os erros ta caindo no caso success do ajax

L

justo…
volta pro onErrorSendBadRequest e faz no javascript, muda o formOptions pra:

var formOptions = {  
        beforeSubmit: validate,  
        success: showSuccess,
        dataType: "json",
        error: showError          
    };

e veja se no error aparece o json

V

Blz

Funcionou … porém olha que estranho.

function showError(responseText, status, err){     
        alert('teste');
        console.log(responseText);
        alert("tam"+responseText.length); 
        for(var count = 0; count < responseText.length; count++)
        {
            alert(responseText[count].message);            
        }           
        
    }

No Console aparece o objeto responseText com as mensagens certinho … mas vou imprimir no alert aparece undefined ?
O que fiz de errado ai ?

L

o responseText tá aparecendo como String ou como Object no console log?

V

object

L

e qual é a estrutura desse object? esse for que vc postou só serve se ele for um array… se for um:

{ "errors" : [ { "message": ".....", .... } ] }

vc tem que iterar em responseText.errors

V
console.log(responseText);
console.log(responseText.errors);

//---------------------

responseText:"{\"errors\": [{\"message\": \"Nome de rede existente\",\"category\": \"existentError\"}]}", status:400, statusText:"Bad Request"})

undefined
undefined

E ai ?

L

ele tá vindo como string então… vc tem que mudar o dataType da requisição ajax pra “json”, ou fazer um:

var json = JSON.parse(responseText);
var errors = json.errors;
//  imprimir esses errors.
V
var formOptions = {
        beforeSubmit: validate,    
        success: showSuccess,  
        dataType: "json",  
        error: showError                  
    };

Já esta json …

Tentei sem e utilizando esse JSON.parse e ocorre um erro “JSON. parser unexpected charcter”

L

aqueles console.log estão em qual função? na showSuccess? na showError? na validate?

V

showError

L

se o dataType tá como json, o responseText deveria ser o JSON já parseado… não uma string…

tem algo bem estranho acontecendo…

só pra ficar na mesma página, tenta fazer assim:

var formOptions = {  
    beforeSubmit: validate,      
    success: showSuccess,    
    dataType: "json",    
    error: function(json) {
         console.log(json);

         console.log(json.errors);
         console.log(json.errors[0].message);
    }                    
};

e veja o que aparece

V

Resolvi aqui.

Parece que apesar de JSON estar definido lá ele vem em string.

Daí fiz isso.

function showError(response, status, err){     
                   
        var resposta = $.parseJSON(response.responseText);
        $.each(resposta.errors, function(i, erro) {
            alert(this.message);
        });
    }

Agora ta certo.
Vlw cara ! Muito obrigado ai ! … Aprendi até mais do que precisava.

Abraços !

Criado 6 de fevereiro de 2013
Ultima resposta 28 de fev. de 2013
Respostas 67
Participantes 3