Centro Universitário de Formiga UNIFOR-MG Ciência da Computação 8º período Disciplina: Laboratório de Programação IV Professor: Michel Pires Silva Alunos: Valter Ribeiro Lima Júnior Hibernate Validator Formiga, Outubro 2011.
Introdução A Bean Validation API, representada pela JSF 303, foi disponibilizada em dezembro de 2009. O Hibernate Validator surgiu como a implementação de referência desta API e permite utilizar Annotations para validar dados de forma fácil e rápida. A grande vantagem é que a Bean Validation API independe de camada da aplicação onde é usada como forma de programar, podendo ser utilizada tanto para aplicações web como para desktop.
Tutorial Este tutorial tem o objetivo de esclarecer dúvidas sobre a instalação, configuração e utilização do Hibernate Validator. Este framework foi testado com os seguinte componentes: JDK 1.7 Netbeans 7.0.1 Mysql 5.1.58 Apache Tomcat 7.0.1 Hibenate Validator 4.1.0 Obs.: Todos os recursos funcionaram perfeitamente com as versões dos componentes acima, não garanto o funcionamento perfeito com outras versões. Download do Framework O pacote com os JAR's pode ser gratuitamente baixados do link: http://sourceforge.net/projects/hibernate/files/hibernate-validator/ disponibilizado pelo site Hibernate.org. Após acessar clique em 4.1.0 Final.
Escolha em qual formato deseja baixar,.zip ou tar.gz. Dentro do arquivo compactado estão os seguintes JAR's que são essenciais para a utilização do Hibernate Validator : hibernate-jpa-2.0-api-1.0.0.final.jar hibernate-validator-4.1.0.final.jar log4j-1.2.14.jar slf4j-api-1.5.6.jar slf4j-log4j12-1.5.6.jar validation-api-1.0.0.ga.jar Caso esteja usando a versão 5 do java, também serão necessários: jaxb-api-2.2.jar jaxb-impl-2.1.12.jar Definindo restrições com o uso de Annotations As restrições são utilizadas para definir regras a respeito dos dados de um objeto. Quando um processo de validação de dados é executado, é feita uma verificação para checar se os dados
estão de acordo com as regras estabelecidas. O Hibernate Validator já possui um grupo de annotations para validações mais comuns, embora possibilite que o programador faça customizações. Existem dois locais onde as restrições podem ser aplicadas: a primeira é diretamente no atributo de uma classe modelo; a outra forma é utilizada quando a classe segue a especificação de um JavaBean, sendo possível usar a annotation em uma método getter. As restrições padrão são: @NotNull: Verifica se um dado é não nulo; @AssertFalse e @ AssertTrue: Verificam se o dado é verdadeiro ou falso, e podem ser aplicados ao tipo primitivo boolean ou a classe Boolean; @Min e @Max: Validam um valor mínimo ou valor máximo para os tipos BigDecimal, BigInteger, String, byte, short e suas classes wrappers correspondentes; @Size: Valida se o tamanho do dado está entre os valores especificados nos atributos min e max, esta annotation deve ser aplicada à String, arrays e objetos dos tipos Collection e Map; @Pattern: Valida o dado de acordo com uma expressão regular especificada pelo atributo regexp, funciona somente para dados do tipo String; @Valid: Utilizado para validar atributos que referenciam outras classes; À seguir veja algumas aplicações das annotations: @NotNull private Integer codigo; @AssertTrue private Boolean maioridade; @AssertFalse private Boolean motorfundido; @Min(18) private int idade; @Max(100) private int notamatermatica; @Size(min = 1, max = 30) private String nome; @Pattern(regexp = [0-9]{5-[0-9]{3 ) private String cep; @Valid private Aluno aluno; Personalizar Mensagens de Erro Como visto anteriormente cada annotation realiza uma validação de um atributo de classe modelo, caso ocorra erros na validação da classe, o Hibernate Validator gera um Set<ConstrainsViolation<T>> com as mensagens de erro. Por padrão as mensagens de erro das annotations já descritas são:
@NotNull: may not be null @AssertFalse: must be false @AssertTrue: must be true @Min: must be greater than or equal to {value @Max: must be less than or equal to {value @Size: size must be between {min and {max @Pattern: must match "{regexp" Estas mensagens pode não atender as necessidades do programador. Porém é possível personalizar as mensagens de duas formas. A primeira forma seria alterar as mensagens direto na arquivo /org/hibernate/validator/validationmessages.properties localizado dentro do JAR hibernatevalidator-4.1.0.final.jar. Neste arquivo você encontrará algo como: javax.validation.constraints.max.message=must be less than or equal to {value javax.validation.constraints.min.message=must be greater than or equal to {value javax.validation.constraints.notnull.message=may not be null O programador pode alterar as mensagem como desejar. Veja o exemplo abaixo: javax.validation.constraints.max.message=o valor deve ser maior ou igual a {value javax.validation.constraints.min.message=o valor deve ser menos ou igual a {value javax.validation.constraints.notnull.message=o valor não deve ser nulo A segunda forma seria personalizar a mensagem ao declarar a annotation com o atributo message, como no exemplo: @NotNull(message = O valor não pode ser nulo ) private String nome; Exemplo de Utilização Para exemplificar a utilização criaremos uma aplicação java J2EE, que cadastre dados de uma configuração de hardware de um computador, onde os dados serão obtidos de uma página JSF e armazenadas num SGBD Mysql, lembrando que o Hibernate Validator também pode ser utilizado em uma aplicação para desktop J2SE. Crie um banco de dados no Mysql com o nome trabalho_framework, dentro dele crie uma tabela chamada computador que deve conter os atributos idênticos aos da imagem abaixo.
Crie um novo projeto, escolha Java Web e logo após Aplicação Web e clique em Próximo. Dê o nome e localização desejados ao projeto e clique em Próximo.
Selecione o Servidor Web Apache Tomcat e clique em Próximo. Obs.: Caso queira utilizar o Servidor Web Glassfish não será necessário baixar os JAR's do Hibernate Validator, pois ele já vem com a API Bean Validator por padrão. O arquivo desta API encontra-se no diretório /usr/local/glassfish-3.1.1/glassfish/modules/bean-validator.jar. Marque a opção Java Server Faces, logo após clique na aba Configuração, no campo Padrão de URL do servelet JSF digite *.faces e na caixa de escolha Idioma preferido da página selecione JSP. Logo após clique em Finalizar.
Após criado todas as pacotes, classes e páginas, o projeto desta aplicação deverá conter todos os arquivos listados ao lado. Obs.: É importante que após criado o projeto, criar uma pasta chamada lib dentro da pasta da aplicação, copiar os arquivos JAR's necessários para o funcionamento do Hibernate Validator para dentro dela e depois adicionar estes arquivos nas Bibliotecas da aplicação. O primeiro passo será criar um arquivo de configuração JSF, também conhecido com facesconfig.xml. Para criá-lo clica com o potão direito do mouse no projeto, vá até Outros..., após abrir a nova janela, clique em Java Server Faces na coluna Categorias e logo após em Configuração do JSF Faces na coluna Tipo de Arquivo. O arquivo deve ficar com o aspecto da imagem a seguir. O próximo passo é criar a página JSF por onde entrarão os dados. Abra o arquivo welcomejsf.jsp e cole o seguinte código dentro da tag <body>. <center><h:form id="formulario"> <h:panelgrid columns="2" bgcolor="#f5f5f5" > <f:facet name="header"> <h:outputtext value="cadastrar" /> </f:facet> <h:outputtext value="marca do Processador" /> <h:inputtext id="marcaprocessador" value="#{controller.config.marcaprocessador" /> <h:outputtext value="modelo do Processador" /> <h:inputtext id="modeloprocessador" value="#{controller.config.modeloprocessador" /> <h:outputtext value="frequência do Processador (Mhz)" />
<h:inputtext id="frequenciaprocessador" value="#{controller.config.frequenciaprocessador" /> <h:outputtext value="capacidade da Memória Ram (MB)" /> <h:inputtext id="capacidadememram" value="#{controller.config.capacidadememram" /> <h:outputtext value="frequência da Memória Ram (Mhz)" /> <h:inputtext id="frequenciamemram" value="#{controller.config.frequenciamemram" /> <h:outputtext value="marca do HD" /> <h:inputtext id="marcahd" value="#{controller.config.marcahd" /> <h:outputtext value="capacidade do HD (GB)" /> <h:inputtext id="capacidadehd" value="#{controller.config.capacidadehd" /> <h:outputtext value="marca da Placa de Vídeo" /> <h:inputtext id="marcavga" value="#{controller.config.marcavga" /> <h:outputtext value="modelo da Placa de Vídeo" /> <h:inputtext id="modelovga" value="#{controller.config.modelovga" /> <h:outputtext value="memória da Placa de Vídeo (MB)" /> <h:inputtext id="memoriavga" value="#{controller.config.memoriavga" /> </h:panelgrid> <h:commandbutton value="salvar" action="#{controller.salvar()" /> <h:commandbutton value="limpar" type="reset" /> <br><br> <h:messages/> </center></h:form> Este código gerará a seguinte tela. Para manter o padrão MVC, crie quatro pacotes dentro de Pacotes de Código Fonte: br.com.framework.controle br.com.framework.dao
br.com.framework.modelo br.com.framework.util Crie uma classe comum java com o nome ConexaoMysql dentro do pacote br.com.framework.util, ela deve ter o seguinte código: public class ConexaoMysql { public static String status = "Não conectou..."; public static Connection connection; //Método Construtor da Classe// public ConexaoMysql() { this.getconexaomysql(); //Método de Conexão// public static Connection getconexaomysql() { try { // Carregando o JDBC Driver padrão String drivername = "com.mysql.jdbc.driver"; Class.forName(driverName); // Configurando a nossa conexão com um banco de dados// String servername = "localhost"; //caminho do servidor do BD String mydatabase = "trabalho_framework"; //nome do seu banco de dados String url = "jdbc:mysql://" + servername + "/" + mydatabase; String username = "root"; //nome de um usuário de seu BD String password = "123"; //sua senha de acesso connection = DriverManager.getConnection(url, username, password); //Testa sua conexão// if (connection!= null) { status = ("STATUS--->Conectado com sucesso!"); else { status = ("STATUS--->Não foi possivel realizar conexão"); return connection; catch (ClassNotFoundException e) { //Driver não encontrado System.out.println("O driver expecificado nao foi encontrado."); return null; catch (SQLException e) { //Não conseguindo se conectar ao banco System.out.println("Nao foi possivel conectar ao Banco de Dados."); return null;
//Método que retorna o status da sua conexão// public static String statusconection() { return status; //Método que fecha sua conexão// public static boolean FecharConexao() { try { ConexaoMysql.getConexaoMySQL().close(); return true; catch (SQLException e) { return false; //Método que reinicia sua conexão// public static java.sql.connection ReiniciarConexao() { FecharConexao(); return ConexaoMysql.getConexaoMySQL(); //Fim da Classe O próximo passo é criar uma classe para fazer manipulações dos dados no banco, crie uma classe dentro do pacote br.com.framework.dao chamada ConfiguracaoDAO, como seguinte o código: public class ConfiguracaoDAO { public Boolean adicionar(configuracao pc) { try { ConexaoMysql con = new ConexaoMysql(); String sql = "insert into computador (marcaprocessador, modeloprocessador, + frequenciaprocessador, capacidadememram,frequenciamemram, marcahd, + capacidadehd, marcavga, modelovga, memoriavga) values " + "('" + pc.getmarcaprocessador() + "', '" + pc.getmodeloprocessador() + "', " + pc.getfrequenciaprocessador() + ", " + pc.getcapacidadememram() + ", " + pc.getfrequenciamemram() + ", '" + pc.getmarcahd() + "', " + pc.getcapacidadehd() + ", '" + pc.getmarcavga() + "', '" + pc.getmodelovga() + "', " + pc.getmemoriavga() + ");"; Statement stmt = con.connection.createstatement(); stmt.execute(sql); stmt.close(); return true; catch (Exception e) { System.out.println("\nerro: " + e); return false;
//Fim da Classe O próximo passo é criar a nossa classe java comum que será nosso modelo, nela estarão contidas as annotations que farão a validação dos atributos. Crie uma classe chamada Configuracao dentro do pacote br.com.framework.modelo com o seguinte código: public class Configuracao { private int idcompuador; /*A annotation no atributo marcaprocessador validará a sua string verificando se seu tamanho tem entre 1 e 30 caracteres e esses caracteres são letras maiúsculas e minúsculas; repare que foi utilizado o atributo message da annotation para personalizar a mensagem de erro caso ocorra; também foi usado o parâmetro {config.marcaprocessador que está armazenado dentro do arquivo ValidationMessages.properties (toda configuração do arquivo pode ser vista na próxima imagem).*/ @Pattern(regexp = "[a-za-z]*", message = "O campo {config.marcaprocessador deve conter somente letras!") @Size(min = 1, max = 30, message = "O campo {config.marcaprocessador deve conter de 1 a 30 caracteres! ") private String marcaprocessador; private String modeloprocessador; private int frequenciaprocessador; /*A annotation no atributo capacidadememram validará o dado inserido e apresentará uma mensagem de erro caso o número inserido for menor ou igual a 512. Repare que não foi utilizado o atributo message da annotation, porém foi alterada a mensagem de erro no arquivo ValidationMessages.properties como visto na imagem abaixo.*/ @Min(512) private int capacidadememram; private int frequenciamemram; /*A annotation no atributo marcahd validará a sua string verificando se seu tamanho tem entre 1 e 30 caracteres e esses caracteres são letras maiúsculas e minúsculas; repare que foi utilizado o atributo message da annotation para personalizar a mensagem de erro caso ocorra; também foi usado o parâmetro {config.marcahd que está armazenado dentro do arquivo ValidationMessages.properties (toda configuração do arquivo pode ser vista na próxima imagem).*/
@Pattern(regexp = "[a-za-z]*", message = "O campo {config.marcahd deve conter somente letras!") @Size(min = 1, max = 30, message = "O campo {config.marcahd deve conter de 1 a 30 caracteres! ") private String marcahd; private int capacidadehd; /*A annotation no atributo marcavga validará a sua string verificando se seu tamanho tem entre 1 e 30 caracteres e esses caracteres são letras maiúsculas e minúsculas; repare que foi utilizado o atributo message da annotation para personalizar a mensagem de erro caso ocorra; também foi usado o parâmetro {config.marcavga que está armazenado dentro do arquivo ValidationMessages.properties (toda configuração do arquivo pode ser vista na próxima imagem).*/ @Pattern(regexp = "[a-za-z]*", message = "O campo {config.marcavga deve conter somente letras!") @Size(min = 1, max = 30, message = "O campo {config.marcavga deve conter de 1 a 30 caracteres! ") private String marcavga; private String modelovga; /*A annotation no atributo memoriavga validará o dado inserido e apresentará uma mensagem de erro caso o número inserido for menor ou igual a 8. Repare que foi utilizado o atributo message da annotation para personalizar a mensagem de erro caso ocorra; também foi usado o parâmetro {config.memoriavga que está armazenado dentro do arquivo ValidationMessages.properties (toda configuração do arquivo pode ser vista na próxima imagem).*/ @Min(value = 8, message = "O campo {config.memoriavga deve conter o valor maior ou igual a 8! ") private int memoriavga; //Fim da Classe //Construtores aqui... //Métodos setter's e getter's aqui...
A próxima classe java simples a ser criada se chamará Validacao e deve estar localizada dentro do pacote br.com.framework.controle. Está classe é de suma importância pois ela fará a validação dos atributos contidos na classe Configuracao. Deverá ter o seguinte código: public class Validacao { private ValidatorFactory factory; //Objeto utilizado para construir um objeto do tipo Validator private Validator validator; //Objeto validador private Set<ConstraintViolation<Configuracao>> erros; //Armazena mensagens de saída de erros //O próprio construtor da classe faz a validação do objeto config passado por parâmetro public Validacao(Configuracao config) { try { // Faz referência à factory com o método estático da classe Validation factory = Validation.buildDefaultValidatorFactory(); //Faz referência à validator com o método getvalidator() validator = factory.getvalidator(); //Valida os dados da classe passada por parâmetro e armazena a saída no atributo erros erros = validator.validate(config); catch (Exception e) { public Set<ConstraintViolation<Configuracao>> geterros(){ return erros; //Fim da Classe A última classe a ser criada é um Bean gerenciado JSF que deve se chamar Controller e deve estar localizada dentro do pacote br.com.framwork.controle. Para criá-lo clique com o botão direito do mouse na aplicação, vá em Novo e depois em Outros...; após abrir a nova java nela clique em JavaServer Faces na coluna Categorias e depois em Bean gerenciado JSF na coluna Tipos de Arquivo; clique no botão Próximo para uma nova janela; nesta janela adicione o nome e localização e clique em Finalizar. Após criado o Bean gerenciado JSF como nos procedimentos anteriormente descritos, adicione o seguinte código: @ManagedBean (name = "controller") @RequestScoped public class Controller { //Objeto em que contém as annotation para validação private Configuracao config; //Objeto com os métodos de manipulação dos dados no banco private ConfiguracaoDAO configdao; //Método construtor da classe public Controller() { //Deve conter a instância da classe Configuração para o Bean gerenciado fazer referência à ela
config = new Configuracao(); //Método que retorna a o objeto config public Configuracao getconfig() { return config; //Método para setar valores ao objeto config public void setconfig(configuracao config) { this.config = config; //Método que invoca a validação e armazenamento no banco public String salvar() { //Faço uma instância da validação passando o objeto a ser validado Validacao validacao = new Validacao(config); //Instância de um contexto para exibir as mensagens na tela FacesContext contexto = FacesContext.getCurrentInstance(); //Caso não tenha gerado nenhum erro na validação este bloco fará armazenamento no banco de dados if (validacao.geterros().isempty()) { FacesMessage msg; this.configdao = new ConfiguracaoDAO(); if (this.configdao.adicionar(config)) msg = new FacesMessage("Dados adicionados com sucesso!"); else msg = new FacesMessage("Um erro foi encontrado ao salvar os dados!"); contexto.addmessage("formulario", msg); //Caso gere algum erro a próxima condição o tratará else { //Percorrerá todo o Set com os erros gerados for (ConstraintViolation<Configuracao> erro : validacao.geterros()) { //Instância da mensagem com o erro gerado FacesMessage msg = new FacesMessage(erro.getMessage()); //Mensagem de erro exibida na tela contexto.addmessage("formulario", msg); //Limpar campos da tela config = new Configuracao(); //Retorno para voltar para a mesma página return "salvo"; //Fim da Classe
Teste e Resultados Após realizado todos os procedimentos destes tutorial rode sua aplicação. Foi feito um teste para salvar com todos campos da página em branco e gerou o seguinte resultado: Foram gerados os erros dos seguintes campos: Memoria da Placa de Vídeo, pois o valor validado foi 0; Marca do HD, pois o campo está vazio; Capacidade da Memória Ram, pois o valor validado foi 0; Marca do Processador, pois o campo está vazio; Marca da Placa de Vídeo, pois o campo está vazio.