Atenção: esse artigo tem um vídeo complementar. Clique e assista!

De que se trata o artigo:

Este artigo introduz ao leitor a especificação Contexts and Dependency Injection for Java EE 6 (CDI) e sua implementação, Weld, como um passo necessário no estudo do framework web JBoss Seam 3.

Em que situação o tema é útil:

Enquanto queremos apresentar ao leitor o mais novo framework da JBoss e mostrar as ferramentas usadas como base do Seam 3, o tema explorado neste artigo – Weld – pode ser útil também para o desenvolvedor que não pretende conhecer a nova ferramenta da Red Hat. Assim, as tecnologias que veremos são úteis não só como base para conhecer o Seam 3, mas também como ferramentas poderosas para o desenvolvedor Java EE em geral, que busca alternativas poderosas para injeção de dependências, gerenciamento de contextos etc.

Resumo DevMan:

JBoss Seam 3 é um dos mais recentes e modernos frameworks disponíveis para o desenvolvedor web Java. Seu poder, modularidade e flexibilidade derivam de uma das mais novas e poderosas especificações de Java EE 6, CDI, e da implementação mais popular desta tecnologia, Weld. Nosso objetivo é apresentar ao leitor o poderoso framework da JBoss mas, para isto, é importante que o leitor tenha conhecimento da base desta ferramenta. Assim, veremos neste artigo o que é e como utilizar Weld.

Seam 2 é um poderoso framework de desenvolvimento web da JBoss. Ele permite desenvolver aplicações corporativas de maneira mais rápida e menos burocrática. Continuando a evolução de seu framework, a Red Hat, companhia por trás da JBoss, lançou no início de 2011 a versão 3 do Seam. Tal como seu antecessor, o Seam 3 disponibiliza inúmeras facilidades, tanto em sua API quanto em ferramentas para geração de código (caso em que Maven archetypes fazem o papel do antigo seam-gen). Por outro lado, esta nova versão também apresenta características novíssimas.

Uma diferença marcante de Seam 3 para o Seam 2 é a modularidade. Enquanto Seam 2 era uma ferramenta relativamente pesada e complexa, baseada em EJBs e focada em servidores de aplicações corporativas, o novo framework pode ser visto como um conjunto de módulos independentes a serem utilizados à medida que forem necessários.

O Seam 3 se destaca também por ser o primeiro framework baseado em Contexts and Dependency Injection, ou CDI, uma poderosa e flexível especificação para Java EE. CDI é a cola que une os diversos módulos que compõem o Seam 3 e lhe dá tamanha modularidade. Assim, para compreender como funciona o Seam 3, é importante conhecer o CDI.

Na verdade, o Seam 2 foi uma das grandes inspirações por trás do CDI. Deste modo, não é de se surpreender que a JBoss também tenha desenvolvido o Weld, a implementação de referência da nova especificação. Weld não só é a implementação de referência como também é uma das mais usadas, seja em servidores de aplicações como JBoss AS e GlassFish v3, seja em aplicações rodando em containers de servlets como, por exemplo, o Tomcat. Naturalmente, o Weld também é utilizado pelo framework Seam 3. Aliás, mais que meramente utilizado, Weld é o centro do framework.

Deste modo, nosso objetivo é conhecer o Seam 3, mas é impossível compreender este novo framework sem entender CDI e Weld. Assim, neste artigo, estudaremos estes pré-requisitos.

Utilizando o Weld

Há várias maneiras de se utilizar o Weld. A mais simples é implantar a aplicação CDI em algum servidor de aplicação Java EE que já possua Weld por padrão, como o JBoss AS 6 e o GlassFish v3. Se você for implantar sua aplicação em algum destes servidores, basta utilizar as funcionalidades de CDI sem se preocupar em configurar o servidor. Ademais, apenas um servidor de aplicações Java EE 6 pode prover certas funcionalidades intimamente ligadas a CDI, como EJBs.

Entretanto, nem sempre é prático utilizar um servidor de aplicação, que tende a consumir muitos recursos e pode ser um tanto sofisticado de se configurar. Uma alternativa popular é utilizar um container de servlets, como o Tomcat. Neste caso, é necessário acrescentar o Weld à aplicação. Para isto, basta copiar o arquivo weld-servlet.jar para o diretório WEB-INF/lib do seu projeto. (Este arquivo encontra-se em qualquer pacote ZIP baixado do site do Weld. Há um link para a página de downloads ao final do artigo.).

Uma vez que tenhamos acrescentado o Weld ao projeto, devemos configurar o listener de Weld no arquivo web.xml:


  <listener>
      <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
  </listener> 

A partir deste ponto, cada container de servlets pode exigir configurações específicas. Para o Tomcat, por exemplo, é preciso habilitar a comunicação via JNDI do gerenciador de beans do projeto, acrescentando o seguinte conteúdo no arquivo context.xml do projeto (que pode vir dentro do diretório META-INF ou do diretório WEB-INF/classes/META-INF):


  <Context>
     <Resource name="BeanManager" 
        auth="Container"
        type="javax.enterprise.inject.spi.BeanManager"
        factory="org.jboss.weld.resources.ManagerObjectFactory"/>
  </Context> 

Por fim, precisamos declarar este recurso JNDI para a aplicação, acrescentando o seguinte código ao fim do arquivo web.xml:


  <resource-env-ref>
     <resource-env-ref-name>BeanManager</resource-env-ref-name>
     <resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
  </resource-env-ref> 

Isto nos permitirá utilizar quase todas as funcionalidades providas pelo Weld. As exceções são apenas os recursos dependentes de um servidor de aplicações completo: EJBs e eventos transacionais. Ademais, como CDI funciona especialmente bem com JSF, é provável que o desenvolvedor também queira instalar uma implementação JSF, como Mojarra, embora isto não seja estritamente necessário.

De qualquer forma, para utilizar o Weld, seja em um servidor que já o disponibilize, seja em uma aplicação web, é preciso criar um arquivo chamado beans.xml dentro do diretório META-INF (se as classes forem empacotadas como um JAR ou como um WAR) ou do diretório WEB-INF (se as classes estiverem dentro de um WAR). Este arquivo, por sinal, pode ser vazio, de modo que não precisamos nos preocupar com seu conteúdo por ora.

Contexts and Dependency Injection

Como dito, Weld é a implementação de referência da especificação JSR-299, que define um conjunto de novas funcionalidades para a plataforma Java EE 6. Como se vê pelo seu título (Contexts and Dependency Injection for the Java EE Platform, frequentemente abreviada para CDI), a JSR-299 especifica novas ferramentas para injeção de dependências e gerenciamento de contexto. CDI também provê interceptadores, decoradores e eventos mais seguros e práticos. Vários projetos de terceiros fornecem essas funcionalidades, e mesmo a plataforma Java EE já possuía algumas opções nesse sentido. CDI, entretanto, apresenta novas maneiras, mais seguras, flexíveis e poderosas, de se fazer estas tarefas.

Provavelmente o aspecto mais notável de CDI seja a injeção de dependências fortemente tipada. CDI decide que objeto atribuir a um ponto de injeção através de um sofisticado algoritmo que considera o tipo do bean a ser injetado. Vejamos como o Weld faz isto.

Beans e tipos de beans

O termo bean foi largamente usado por desenvolvedores Java sem uma definição clara e precisa, variando de significado dependendo da API considerada ou do contexto. Enquanto os JavaBeans eram componentes manipulados visualmente e Enterprise JavaBeans eram componentes utilizados em servidores de aplicação, outros frameworks passaram a utilizar o mesmo termo, como Spring, Struts (com seus form beans) e JSF (com os beans gerenciados). O termo estava perceptivelmente ligado a uma ideia central, mas, à medida que era reutilizado, passou a ser mais difuso, difícil de definir. Java EE 6, entretanto, tem um conceito próprio e bem definido do que é um bean.

Um bean (ou, mais especificamente, um bean gerenciado) é um componente Java EE cujas instâncias são gerenciadas pelo container. A maior parte dos beans tradicionais, como JavaBeans, EJBs e POJOs, se encaixam nesta definição. Em Weld, porém, estes beans são apenas um subconjunto de todos os beans possíveis.

Formalmente, os beans não são os objetos gerados pelo servidor – estes são as instâncias contextuais do bean. Um bean pode gerar várias instâncias contextuais. Por exemplo, o servidor pode gerar uma instância para cada requisição a ser atendida. Em outras palavras, o bean está para suas instâncias contextuais assim como uma classe está para seus objetos. Coloquialmente, porém, é usual dizer que a instância é, ela mesma, o bean.

Instâncias de beans são geradas (ou obtidas) automaticamente pelo Weld. Tradicionalmente, o servidor gera estes objetos instanciando uma classe com um construtor público sem parâmetros (também conhecido como um construtor padrão). Em CDI, no entanto, há outras maneiras de o servidor fazer isto. Weld pode instanciar classes com construtores anotados com @Inject, invocar métodos produtores ou recuperar atributos produtores. Veremos como utilizá-los em breve.

...

Quer ler esse conteúdo completo? Tenha acesso completo