Segue o pequeno tutorial que mostra um exemplo simples de como fazer a validação programática no VRaptor.
No final o tutorial explica porque (ainda) não existe um jeito de fazer as validações com anotações.
Tuda explicação é bem prática, porém o hibernate validator plugin é ainda mais vantagoso.
Vamos escrever uma classe como modelo que representa uma pessoa. Crie o código seguinte:
package org.vraptor.examples.validation; public class Person { private String name; private String address; private Long preferredNumber; // getters e setters @Override public String toString() { return String.format("[Person %s,%s,%d]", name, address, preferredNumber); } }
Vamos continuar e configurar a lógica para adicionar uma pessoa.
Chamaremos o componente person e o método add que adiciona a pessoa.
Isso significa quando o url person.add.logic é chamado, o componente será criado, o objeto person será preenchido com os parâmetros da requisição e o método add será executado.
package org.vraptor.examples.validation; import org.vraptor.annotations.Component; import org.vraptor.annotations.Logic; import org.vraptor.annotations.Parameter; @Component public class PersonLogic { public void add(Person p) { System.out.printf("Adding %s to the database!%n", p); } }
Vamos validar os dados da pessoa:
package org.vraptor.examples.validation; import org.vraptor.annotations.Component; import org.vraptor.validator.*; import org.vraptor.i18n.*; @Component public class PersonLogic { public void add(Person p) { System.out.printf("Adding %s to the database!%n", p); } /** * Validação do método add */ public void validateAdd(ValidationErrors errors, Person p) { // verifique se nulo ou vazio if(StringValidation.isBlank(p.getName())) { errors.add(new Message("name","empty_name")); } // verifique se nulo ou vazio if(StringValidation.isEmpty(p.getAddress())) { errors.add(new Message("address","empty_address")); } // verifique se nulo if(p.getPreferredNumber()==null) { errors.add(new Message("number","empty_number")); } } }
Nosso método add na lógica só será chamado se a validação não registrou nenhum erro!
Então: se nenhum erro aconteceu, errors.size()==0, o Vraptor continua e chama person/add.ok.jsp:
<html> Você criou uma pessoa chamada ${person.name}, que vive em ${person.address} e o numero preferido é ${person.preferredNumber}. </html>
Se errors.size()!=0 pelos menos um erro aconteceu ... VRaptor retorna invalid que redireciona ao component/logic.invalid.jsp, no nosso exemplo: person/add.invalid.jsp:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <html> Um erro na validação aconteceu: <div id="errors"> <ul> <c:forEach var="error" items="${errors.iterator}"> <li>${error.key}</li> </c:forEach> </ul> </div> </html>
Vamos criar uma página simples index.jsp que contém um formulário para uma pessoa:
<html> <form action="person.add.logic" method="get"> Nome: <input name="person.name"/><br/> Endereço: <input name="person.address"/><br/> Numero preferido: <input name="person.preferredNumber"/><br/> <input type="submit"/> </form> </html>
Estamos preparados para testar a nossa lógica!
Mas o que nós fizemos? Vamos reparar:
Vamos configurar VRaptor para voltar ao formulário em caso de um erro de validação acontecer.
Primeiro cria o arquivo views.properties no seu classpath (diretório java source ou resources).
Nos podemos mapear componentName.logic.invalid para qualquer arquivo desejado ... então vamos redirecionar ao nosso formulário.
person.add.invalid = /index.jsp
E alteraremos o arquivo index.jsp para mostrar os valores padrões da pessoa:
<html> <form action="person.add.logic" method="get"> Nome: <input name="person.name" value="${person.name}"/><br/> Endereço: <input name="person.address" value="${person.address}"/><br/> Numero preferido: <input name="person.preferredNumber" value="${person.preferredNumber}"/><br/> <input type="submit"/> </form> </html>
Mensagens de erros deveriam ser implementadas de maneira internacional, por isso podemos usar o tag fmt:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <div id="errors"> <ul> <c:forEach var="error" items="${errors.iterator}"> <li><fmt:message key="${error.key}"/></li> </c:forEach> </ul> </div>
Não esqueça de configurar o resource bundle! (leia a documentação sobre fmt jstl ou download a aplicação amostra do VRaptor).
VRaptor já tem alguns mensagens padrão. Você deveria adicionar elas no seu arquivo de properties.
no_converter_found = Nenhum conversor foi encontrado. invalid_converter = Não conseguir criar o conversor. invalid_date = Data inválida. invalid_time = Hora inválida. invalid_value = Valor inválida. invalid_number = Numero inválida. invalid_character = Caracter inválida.
A interface básica de mensagem chama ValidationMessage enquanto a internacionalizada é Message (devido a problemas de compatibilidade).
Para misturar os dois tipos de mensagens, com e sem i18n, você deve usar a classe FixedMessage.
Ambas implementam o método isAlreadyLocalized: Message devolve false, enquanto FixedMessage develove true, portanto a sua view fica algo como:
<c:if test="${error.alreadyLocalized}"> ${error.key} </c:if> <c:if test="${not error.alreadyLocalized}"> <fmt:message key="${error.key}"/> </c:if>
Você pode usar a propriedade path para acessar exatamente qual campo gerou o erro.
O Vraptor dá suporte ao Hibernate Validator.