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.