DevMedia
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Este é um post disponível para assinantes MVP
Este post também está disponível para assinantes da Java Magazine DIGITAL
ou para quem possui Créditos DevMedia.

Clique aqui para saber como acessar este post

1) Torne-se um assinante MVP e por apenas R$ 59,90 por mês você terá acesso completo a todos os posts. Assinar MVP

2) Adquira Créditos: comprando R$ 180,00 em créditos esse post custará R$ 1,20. Comprar Créditos

post favorito     comentários
Java Magazine 95 - Índice

Seam 3: complementando a lógica com Weld - Revista Java Magazine 95

Este artigo apresenta ao leitor as funcionalidades de interceptadores, decoradores, eventos e estereótipos, da maneira como são implementadas em Weld.

[fechar]

Você não gostou da qualidade deste conteúdo?

(opcional) Você poderia comentar o que não lhe agradou?

Confirmo meu voto negativo

Conforme vimos no artigo anterior, Seam 3, o novo framework da JBoss, é baseado na especificação CDI e roda sobre sua implementação de referência, o Weld. Uma das principais funcionalidades providas pelo Weld é a injeção de dependências. Através dela, CDI fornece uma maneira nativa de se desacoplar componentes, e seu modelo de injeção de dependências usa o poder do sistema de tipos de Java para injetar beans de maneira flexível e, principalmente, segura.

Ademais, Weld também permite o gerenciamento do ciclo de vida de beans baseado em escopos. Os contextos de CDI, semelhantes aos utilizados em JSF 2, são uma opção nativa e formalmente especificada para o gerenciamento do escopo de beans. Em conjunto com a possibilidade de atribuir nomes EL a beans, estas funcionalidades tornam Weld uma opção bastante atrativa para o desenvolvedor da plataforma Java, especialmente aquele que utiliza JSF.

Entretanto, estas não são as únicas necessidades tradicionais do desenvolvimento web que CDI veio satisfazer. Desenvolvedores Java EE, por exemplo, têm a constante necessidade de executar certa lógica para complementar o comportamento de código já escrito – e é possível fazer isto com Weld através de interceptadores, decoradores e eventos. Outras vezes, é preciso atribuir um “rótulo” a um conjunto de beans, de modo que os beans “rotulados” possam ser tratados de maneira diferente. Isto pode ser feito através dos estereótipos.

O conhecimento de tais funcionalidades, além de útil por si só, facilitará nossa compreensão de como o Seam 3 é funcional. Deste modo, neste artigo, veremos cada uma destas facilidades, começando por interceptadores.

 

Interceptadores

Às vezes, precisamos que determinada atividade seja executada sempre em uma determinada situação. É preciso confirmar (ou reverter) alterações quando um código transacional se encerra, registrar nos logs que determinado método foi executado, liberar recursos de um objeto quando ele for destruído, etc. Estas atividades geralmente transcendem a lógica de negócio da aplicação, podendo ser necessárias em vários pontos do software.

A plataforma Java EE utiliza o conceito de interceptadores (ou interceptors) para facilitar este trabalho. Um interceptador é uma classe que captura a linha de execução de uma thread quando um método – o método interceptado – for invocado. Um interceptador pode executar uma ação antes ou depois da execução do método interceptado, ou mesmo impedir que o método interceptado seja, de fato, invocado. É possível interceptar as mais diversas classes e métodos com um interceptador. EJBs, por exemplo, já podiam ser interceptados, mas a maneira de fazê-lo era um tanto problemática, por várias razões.

Interceptor bindings

A JSR-299, felizmente, simplificou bastante o uso de interceptadores. Em CDI, um interceptador é ligado a uma classe ou método através de uma anotação especial, chamada ligador de interceptação, ou interceptor binding. Cada interceptador possui seu próprio interceptor binding. Assim, digamos que queremos registrar no log do servidor a invocação de certos métodos. Para isto, anotaríamos o método (ou mesmo uma classe inteira) com um interceptor binding. Se nosso interceptor binding se chamar @LogarInvocacaoDeMetodos, ele seria aplicado como abaixo:

 

@LogarInvocacaoDeMetodos

public class MeuBean {

    public String getNome() {

        return "nome";

    }

}

 

Como anotações em geral, é fácil declarar um interceptor binding. Para ver como isto é feito, criemos o interceptor binding @LogarInvocacaoDeMetodos. Para declarar que uma anotação é um interceptor binding, a marcamos com a meta-anotação @InterceptorBinding.

 

@InterceptorBinding

 

Outra característica de interceptor bindings é terem como alvo, geralmente, tanto classes quanto métodos. Um interceptor binding deve necessariamente ter classes como alvo, porque o interceptador (isto é, o bean que efetivamente executará ações ao capturar métodos) deve ser anotado com o interceptor binding. Ademais, como frequentemente é necessário anotar apenas alguns métodos de um bean, interceptor bindings geralmente também têm métodos como alvo:

 

@Target({ElementType.METHOD, ElementType.TYPE})

 

Por fim, uma vez que ligações de interceptadores devem estar disponíveis para consulta enquanto a aplicação roda, a anotação deve ser mantida em tempo de execução:

 

@Retention(RetentionPolicy.RUNTIME)

 

Feito isto, declaramos nossa interface. O código completo, incluindo a última linha abaixo, pode ser visto na Listagem 1.

 

public @interface LogarInvocacaoDeMetodos {}

 

Listagem 1. A anotação @LogarInvocacaoDeMetodos: exemplo de interceptor binding.

@InterceptorBinding

@Target({ElementType.METHOD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

public @interface LogarInvocacaoDeMetodos {}

Implementando interceptadores

Declarar o interceptor binding e usá-lo para anotar classes e métodos é fácil, mas a anotação serve apenas para ligar uma classe ou método ao interceptador. É preciso ainda implementar o interceptor, e para isto, devemos criar uma classe. Esta classe deve ser anotada com @Interceptor para ser um interceptador. Além disto, a classe também deve ser anotada com o interceptor binding correspondente. No nosso caso, a implementação do nosso interceptador poderia ser algo assim:

 

@Interceptor @LogarInvocacaoDeMetodos

public class LogarInvocacaoDeMetodosInterceptor {

 

Interceptadores podem executar três tipos de ações (que veremos mais à frente), e cada tipo de ação exige um método diferente. No nosso exemplo, a ação que desejamos executar é capturar a chamada de um método. Métodos de interceptadores que tenham esta função devem ser anotados com @AroundInvoke, pois é assim que Weld saberá que a função do método é interceptar invocações. Estes métodos exigem ter uma assinatura específica: devem receber uma instância de InvocationContext (que representará o método interceptado e detalhes do contexto da invocação), retornar Object e declarar que pode lançar Exception:

 

    @AroundInvoke

    public Object logarInvocacao(InvocationContext context) throws Exception {

 

Dentro do método, executamos o que queremos. No caso, vamos registrar na saída-padrão os nomes da classe e do método invocado:

 

        System.out.println("Classe: " + context.getTarget().getClass().getName());

        System.out.println("Método: " + context.getMethod().getName());"

A exibição deste artigo foi interrompida

Este post está disponível para assinantes MVP.



Desenvolvedor Java há cinco anos e já desenvolveu aplicações Web que utilizavam threads e JNI para acesso a hardware.

O que você achou deste post?
Publicidade
Serviços

Mais posts