- O que é interceptor?
- Passos para criação do interceptor BeanValidationAttribute
- Passo 1 – Criação da nova annotation BeanValidationAttribute
- Passo 2 -Criação do Interceptor
- Passo 2.1 – Declaração da classe e annotations iniciais
- Passo 2.2 – Implementação do método base
- Passo 2.3 – Inserir o código comum dentro do método base
- Passo 3 – Adicionar o interceptor no arquivo beans.xml
- Passo 4 – Utilizar a annotation nos lugares desejados
- finnaly{
Olá Pessoal, tudo bom?
No artigo de hoje vamos fazer um passo a passo da construção de um interceptor chamado BeanValidationAttribute, que servirá para validar as annotations Bean Validation dos atributos de uma classe. Veja na continuação…
O que é interceptor?
Se você não sabe o que é um interceptor dá uma olhada nesse artigo.
Passos para criação do interceptor BeanValidationAttribute
A primeira coisa que deve ser pensada ao criar um interceptor é quais atividades comuns ele irá realizar. No caso do BeanValidationAttribute em vários trechos do código existem validações dos atributos verificando nulidade, tamanho de Strings entre outros. Assim esse trecho de validação pode ser modificado para que possa ser utilizado a biblioteca Bean Validation. Esse interceptor se utiliza de duas alterações básicas no código. A primeira é que a validação estará no interceptor e a segunda é a necessidade de inserir as annotations nos atributos das classes que serão validadas.
Agora vamos fazer os 4 passos básicos para a criação de um interceptor:
- Criar uma annotation própria para identificar o interceptor
- Criar a classe que implementa o interceptor
- Adicionar o interceptor no arquivo beans.xml
- Utilizar a nova annotation no trecho de código desejado
Passo 1 – Criação da nova annotation BeanValidationAttribute
No package desejado, por exemplo br.com.mauda.seminario.cientificos.interceptor, crie uma annotation chamada BeanValidationAttribute, conforme o código abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package br.com.mauda.seminario.cientificos.interceptor; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.interceptor.InterceptorBinding; @InterceptorBinding @Target({ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) public @interface BeanValidationAttribute { } |
Algumas explicações:
- A annotation @InterceptorBinding indica que essa annotation está vinculada a um interceptor.
- A annotation @Target indica em quais estruturas do java a annotation pode ser utilizada. No nosso exemplo, pode ser utilizada para anotar métodos (method) e classes (type)
- A annotation @Retention indica quando a JVM pode descartar a annotation. Existem 3 tipos, Class, Runtime e Source. Como o Java possui 3 fases de compilação, Código -> byteCodes -> Execução. Cada um desses 3 tipos está vinculado a uma fase desta. Como queremos que a annotation permaneça mesmo após a execução, escolhemos a constante RUNTIME.
Passo 2 -Criação do Interceptor
Nesse passo a classe que faz o trabalho do interceptor será criada.
Passo 2.1 – Declaração da classe e annotations iniciais
Primeiro a classe deve ser criada.
Após inserir na declaração da classe a annotation@Interceptor, a qual indica que a classe é uma interceptor para o CDI.
Por fim inserir a annotation recém criada @BeanValidationAttribute.
O código abaixo mostra como ficou a classe:
1 2 3 4 5 6 7 8 9 |
package br.com.mauda.seminario.cientificos.interceptor; import javax.interceptor.Interceptor; @Interceptor @BeanValidationAttribute public class BeanValidationAttributeInterceptor { } |
Passo 2.2 – Implementação do método base
Esse próximo sub-passo é implementar o método que irá realizar o código comum antes de chamar o método original.
O método pode ter qualquer nome, no caso aqui colocamos manage. O mais importante aqui é este possuir apenas um parâmetro do tipo InvocationContext, estar annotado com @AroundInvoke e lançar uma Exception no caso de exceções.
O código abaixo mostra como ficou a classe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package br.com.mauda.seminario.cientificos.interceptor; import javax.interceptor.AroundInvoke; import javax.interceptor.Interceptor; import javax.interceptor.InvocationContext; @Interceptor @BeanValidationAttribute public class BeanValidationAttributeInterceptor { @AroundInvoke public Object manage(InvocationContext ctx) throws Exception { } } |
Passo 2.3 – Inserir o código comum dentro do método base
Agora nesse sub-passo, vamos inserir o código de validação dentro do método criado.
Para isso vamos utilizar uma javax.validation.ValidatorFactory, linha 24, que será responsável por criar uma classe javax.validation.Validator, linha 30, para realizar a validação com o método validate(), linha 31. Caso ocorra alguma exception durante a validação o catch, linha 33, ira apenas logar o erro, utilizando a biblioteca Log4J, não lançando a exception, permitindo a continuação do for.
Caso ocorra alguma violação, após o for finalizar, linha 39, será lançada uma ConstraintViolationException, linha 40.
Caso contrário o interceptor irá chamar o método original interceptado, linha 43. A chamada via InvocationContext ao método original, utilizando o método proceed(). Essa linha irá chamar o método que foi interceptado pelo interceptor. E com isso está encerrado o código dessa classe.
O código abaixo mostra como ficou a classe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
package br.com.mauda.seminario.cientificos.interceptor; import java.util.HashSet; import java.util.Set; import javax.interceptor.AroundInvoke; import javax.interceptor.Interceptor; import javax.interceptor.InvocationContext; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import javax.validation.UnexpectedTypeException; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import org.apache.logging.log4j.LogManager; @Interceptor @BeanValidationAttribute public class BeanValidationAttributeInterceptor { @AroundInvoke public Object manage(final InvocationContext ctx) throws Exception { ValidatorFactory dfv = Validation.buildDefaultValidatorFactory(); Set<ConstraintViolation<?>> violations = new HashSet<>(); for (Object params : ctx.getParameters()) { if (params != null) { try { Validator validator = dfv.getValidator(); violations.addAll(validator.validate(params)); } catch (UnexpectedTypeException cause) { LogManager.getLogger(ctx.getTarget().getClass()) .error(ctx.getMethod() + "Erro inesperado ao validar com o Bean Validation", cause); } } } if (!violations.isEmpty()) { throw new ConstraintViolationException(violations); } return ctx.proceed(); } } |
Passo 3 – Adicionar o interceptor no arquivo beans.xml
Esse passo irá adicionar o interceptor dentro do arquivo beans.xml.
Para adicionar é necessário utilizar a tag <interceptors> e dentro dessa tag colocar uma tag <class> com o package completo mais o nome da classe Interceptor e não a annotation.
Caso seja necessário adicionar mais interceptor, apenas adicione mais uma tag <class> dentro da tag <interceptors> da mesma forma que a primeira.
As linhas destacadas abaixo mostram essas modificações:
1 2 3 4 5 6 7 8 9 |
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="all"> <interceptors> <class>br.com.mauda.seminario.cientificos.interceptor.BeanValidationAttributeInterceptor</class> </interceptors> </beans> |
Passo 4 – Utilizar a annotation nos lugares desejados
Por fim agora é só utilizar a annotation criada nos métodos desejados para que estes sejam interceptados e seu parâmetro validado, como mostra o trecho de código abaixo:
1 2 3 4 5 6 7 8 9 |
//Importando a annotation @BeanValidationAttribute import br.com.mauda.seminario.cientificos.interceptor.BeanValidationAttribute; // Utilizando no método desejado @BeanValidationAttribute public void insert(Musica musica) { //Codigo do método insert } |
finnaly{
Duvidas ou sugestões? Deixe seu feedback! Isso ajuda a saber a sua opinião sobre os artigos e melhorá-los para o futuro! Isso é muito importante!
Até um próximo post!
Leave a Reply