CDI + JSF no Java EE7

Introdução

Com o lançamento da Java EE 7, as APIs CDI(Context Dependency Injection) e JSF(Java Server Face) receberam novas especificações: a JSR 346, a qual especifica o CDI na versão 1.1 e a JSR 344, referente ao JSF 2.3.

Na versão Java EE 6 a utilização conjunta do CDI com JSF ocasionava alguns problemas, tais como de performance. Logo, compreende-se que não havia uma forte integração entre as tecnologias, pois, o CDI se encontrava em sua versão inicial 1.0, o que o tornava imaturo nas integrações às outras APIs contidas no Java EE.

Após o lançamento das especificações mencionadas, no Java EE 7, iniciou-se um amadurecimento na integração entre as tecnologias do Java EE, o que permite que qualquer bean seja nomeado através da anotação @Named, dessa forma os beans anotados são gerenciados pelo CDI permitindo a injeção de dependência entre si, isso engloba controllers JSF que podem ser adicionados ao contexto do CDI através da anotação @Named.

Essa integração entre CDI e JSF, após o Java EE 7, começa a apresentar efetividade, uma vez que, considerando o propósito do CDI, segundo a especificação, referente ao CDI 1.1, a JSR346, é: “A utilização destes serviços simplifica significativamente a tarefa de criar aplicações Java EE, integrando a camada web Java EE com serviços corporativos Java EE. Em particular, os componentes EJB podem ser utilizados como JSF managed beans, integrando assim os modelos de programação como EJB e JSF.”.

Entretanto, mesmo apresentando um amadurecimento notável na integração entre as diversas tecnologias, o CDI ainda é uma API nova que apresenta lacunas que podem ser facilmente preenchidas em soluções alternativas como, por exemplo, requisitos comumente utilizados por desenvolvedores JSF, tais como, a injeção de dependência em conversores e validadores, ainda não se encontra disponível no CDI e podem ser resolvido utilizando a extensão DeltaSpike da Apache.

Baseado nisto, pode-se afirmar que o CDI vem evoluindo significativamente a cada especificação, o que implica no amadurecimento das integrações com APIs providas no Java EE.

Iniciando com CDI + JSF no Java EE 7

Para melhor compreensão do assunto abordado, será desenvolvido alguns exemplos práticos da utilização integrada de JSF + CDI no Java EE 7.

Como toda especificação, o CDI precisa de uma implementação de referência, a qual deve ser provida pelo application server ou servlet container. Para os exemplos citados neste artigo será utilizado o application server WildFly, da Jboss, na versão 8.2.0.Final. Este possui o Weld como implementação de referência do CDI.

A gestão das bibliotecas utilizadas durante o desenvolvido dos exemplos será utilizado o Maven, uma ferramenta da Apache para automação do build e gestão dos artefatos de um projeto.

Criando o projeto Web com Maven

O projeto utilizando no decorrer do artigo é gerado pelo seguinte comando Maven no terminal: 
mvn archetype:generate -DgroupId=br.com.emmanuelneri -DartifactId=javamagazine-cdi-jsf -DarchetypeArtifactId=maven-archetype-webapp.

Após executado o comando, será necessário confirmar três propriedades: groupId, artifactiId e version, feito isso o processo de geração será finalizado com a mensagem de “BUILD SUCESS”.

Nota: É importante que o JAVA_HOME esteja configurado com JDK 7 ou 8 e o MAVEN_HOME configurado para a versão 3.

Com o projeto criado é preciso configurar o projeto Maven através de seu arquivo de configuração, pom.xml. Durante os exemplos usaremos duas principais dependências o CDI e o JSF, assim precisamos adicionar no arquivo onde estão localizadas e quais suas versões para que o Maven consiga disponibiliza-las a nosso projeto. A seguir, no pom.xml.

Configurando pom.xml
[code language=”Java”]
<project xmlns=”http://maven.apache.org/POM/4.0.0" xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>

<groupId>br.com.emmanuelneri</groupId>
 <artifactId>javamagazine-cdi-jsf</artifactId>
 <packaging>war</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>CDI + JSF no JavaEE 7</name>

<properties>
 <cdi.version>1.1</cdi.version>
 <jsf.version>2.2</jsf.version>
 <java.version>1.7</java.version>
 </properties>

<dependencies>
 <dependency>
 <groupId>javax.enterprise</groupId>
 <artifactId>cdi-api</artifactId>
 <version>${cdi.version}</version>
 </dependency>
 <dependency>
 <groupId>javax.faces</groupId>
 <artifactId>javax.faces-api</artifactId>
 <version>${jsf.version}</version>
 </dependency>
 </dependencies>

<build>
 <plugins>
 <plugin>
 <artifactId>maven-compiler-plugin</artifactId>
 <configuration>
 <source>${java.version}/source>
 <target>${java.version}</target>
 </configuration>
 </plugin>
 </plugins>
 </build>
</project>
[/code]

As dependências serão carregadas do próprio repositório padrão do Maven, o que já está implícito no arquivo de configuração, assim não necessitando referenciar o repositório. Inicialmente sendo necessário adicionar apenas as dependências cdi-api e javax.faces-api nas versões 1.1 e 2.2, respectivamente.

Como vamos utilizar APIs do Java EE 7 precisamos compilar nosso exemplos com a versão 1.7 da JDK(Java Development Kit), com isso na linha 33 adicionaremos o plugin maven-compiler-plugin para que sempre compile o projeto utilizado a versão 1.7.

O arquivo final construído pelo Maven durante o exemplo é um arquivo de projeto web, de extensão WAR(Web application ARchive), o qual foi configurado no pom.xml, na linha 7 da Listagem 1 pelo atributo packaging.

Iniciando exemplo

O exemplo inicial é bem simples, sendo um cadastro de solicitação, composto por três campos de entrada de dados e um botão de envio de solicitação, o objetivo é o usuário adicionar os dados da solicitação e o sistema apresentar uma mensagem de “enviado com sucesso” contendo o nome do solicitante preenchida no cadastro. Dessa forma a aplicação será estruturada com uma classe Solicitacao.java que conterá os atributos referente aos campos da solicitação, um arquivo web solicitacao.xhml responsável pela interface com o usuário, e os mesmo serão gerenciados pelo classe controller SolicitacaoController.java, seguindo o padrão MVC(Model-View-Controller) do JSF.
 
Com o objetivo de simular uma classe de entidade, será criado a classe Solicitacao.java, apenas com o objetivo de transferir as informações referente a uma solicitação, simulando o comportamento de um Model do MVC.

Criando classe Solicitacao.java
[code language=”Java”]
package br.com.emmanuelneri.model;

public class Solicitacao {

private String nome;
 private String email;
 private String telefone;

public String getNome() { return nome; }

public void setNome(String nome) { this.nome = nome; }

public String getEmail() { return email; }

public void setEmail(String email) { this.email = email; }

public String getTelefone() { return telefone; }

public void setTelefone(String telefone) { this.telefone = telefone; }
}
[/code]

Os controllers JSF são responsável pelo gerenciamento da interface com o usuário, então SolicitacaoController.java irá gerenciar o ciclo de vida do objeto solicitacao, que será de uma requisição, por estar anotado com @RequestScoped, o que diz que seu tempo de vida será de uma requisição http e também fará a ação de envio.

Criando classe SolicitacaoController.java
[code language=”Java”]
package br.com.emmanuelneri.controller;
 
import br.com.emmanuelneri.model.Solicitacao;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Named;
 
@Named
@RequestScoped
public class SolicitacaoController {
 
 private Solicitacao solicitacao;
 
 public SolicitacaoController() {
 inicializarSolicitacao();
 } 
 
 private void inicializarSolicitacao() {
 this.solicitacao = new Solicitacao();
 }
 
 public void enviar() {
 FacesContext.getCurrentInstance().addMessage(“”,
 new FacesMessage(String.format(“Olá %s, 
 seu solicitacao foi enviado com sucesso!”, 
 this.solicitacao.getNome())));
 
 inicializarSolicitacao();
 }

public Solicitacao getSolicitacao() {
 return solicitacao;
 }

public void setSolicitacao(Solicitacao solicitacao) {
 this.solicitacao = solicitacao;
 }

}
package br.com.emmanuelneri.controller;
 
import br.com.emmanuelneri.model.Solicitacao;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Named;
 
@Named
@RequestScoped
public class SolicitacaoController {
 
 private Solicitacao solicitacao;
 
 public SolicitacaoController() {
 inicializarSolicitacao();
 } 
 
 private void inicializarSolicitacao() {
 this.solicitacao = new Solicitacao();
 }
 
 public void enviar() {
 FacesContext.getCurrentInstance().addMessage(“”,
 new FacesMessage(String.format(“Olá %s, 
 seu solicitacao foi enviado com sucesso!”, 
 this.solicitacao.getNome())));
 
 inicializarSolicitacao();
 }

public Solicitacao getSolicitacao() {
 return solicitacao;
 }

public void setSolicitacao(Solicitacao solicitacao) {
 this.solicitacao = solicitacao;
 }

}
[/code]

A anotação @Named faz com que a classe controller seja um bean gerenciado pelo contexto do CDI, o que permite ser disponibilizado em xhtml através de EL(Expression Language).

Nota: O import do escopo @RequestScoped tem que ser do pacote javax.enterprise.context para pertencer ao contexto do CDI.

Por fim será criado o arquivo web no formato xhtml, onde é o view do MVC, sendo responsável pela interface web como o usuário, demonstrado a seguir na Listagem 4.

Criando arquivo web solicitacao.xhtml
[code language=”Java”]
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns=”http://www.w3.org/1999/xhtml"
 xmlns:h=”http://java.sun.com/jsf/html">
 
 <h:body>
 <h:form>
 <h1>Solicitação</h1> 
 
 <h:panelGrid columns=”2">
 <h:outputLabel value=”Nome: “ />
 <h:inputText id=”inputNome” value=”#{solicitacaoController.solicitacao.nome}” 
 requiredMessage=”Campo nome é obrigatório” required=”true”/>
 
 <h:outputLabel value=”Email: “ />
 <h:inputText id=”inputEmail” 
 value=”#{solicitacaoController.solicitacao.email}”
 requiredMessage=”Campo email é obrigatório” required=”true”/>
 
 <h:outputLabel value=”Telefone: “ />
 <h:inputText id=”inputTelefone” 
 value=”#{solicitacaoController.solicitacao.telefone}”
 requiredMessage=”Campo telefone é obrigatório” required=”true”
 </h:panelGrid>
 
 <h:commandButton id=”btnEnviar” value=”Enviar” 
 action=”#{solicitacaoController.enviar}” />
 
 <h:messages />
 
 </h:form> 
 </h:body>
</html>
[/code]

Como comentado anteriormente o arquivo web faz referencia ao atributos do controller através da EL, utilizando o padrão “#{nomeDoController.atributo}”.

O primeiro exemplo foi a demonstração da simplicidade em criar projetos utilizando JSF e CDI no Java EE 7, onde foi utilizada apenas anotações e não foi necessário a criação de arquivo de configuração, como soluções similares exigem, exemplo Spring.

Utilizando services em controllers JSF

Continuando o exemplo, será feito uma refatoração no projeto para que o método enviar solicitacao seja executado por uma classe service e se torne um bean, separando assim as responsabilidades e permitindo que essa funcionalidade seja injetada em um controller JSF ou qualquer outro bean gerenciado pelo contexto do CDI.
A seguir, será criado uma classe de serviço, a qual será o novo responsável pelo o envio da solicitação. Com isso, no exemplo, o serviço apenas recebe o parâmetro do tipo Solicitacao, onde será impresso seu atributo nome no console. Seguindo o mesmo padrão dos controllers JSF, os services também podem ser beans nomeados, o que permitem serem utilizados em qualquer lugar que pertença ao mesmo contexto.

Criando classe de SolicitacaoService.java
[code language=”Java”]
package br.com.emmanuelneri.service;
 
import br.com.emmanuelneri.model.Solicitacao;
import org.slf4j.Logger;
import javax.inject.Inject;
import javax.inject.Named;

@Named
public class SolicitacaoService {

@Inject 
 private Logger logger;
 
 public void enviarSolicitacao(Solicitacao solicitacao) {
 logger.info(String.format(“Enviado novo cadastro em nome de %s”, 
 solicitacao.getNome()));
 }
}
[/code]

Alterando classe SolicitacaoController.java
[code language=”Java”]
package br.com.emmanuelneri.controller;
 
import br.com.emmanuelneri.model.Solicitacao;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Named;
 
@Named
@RequestScoped
public class SolicitacaoController {
 
 private Solicitacao solicitacao;
 
 @Inject
 private SolicitacaoService cadastroService;

public SolicitacaoController() {
 inicializarSolicitacao();
 } 
 
 private void inicializarSolicitacao() {
 this.solicitacao = new Solicitacao();
 }
 
 public void enviar() {
 cadastroService.enviarSolicitacao(solicitacao);

FacesContext.getCurrentInstance().addMessage(“”,
 new FacesMessage(String.format(“Olá %s, 
 seu solicitacao foi enviado com sucesso!”, 
 this.solicitacao.getNome())));
 
 inicializarSolicitacao();
 }

public Solicitacao getSolicitacao() {
 return solicitacao;
 }

public void setSolicitacao(Solicitacao solicitacao) {
 this.solicitacao = solicitacao;
 }

}
[/code]

Para que seja possível adicionar services nos controllers, o CDI exige uma configuração para que possa encontrar os beans anotados com @Named em qualquer local do projeto. A configuração a ser feita é adicionar o atributo bean-discovery-mode=”all” no arquivo beans.xml, arquivo de configuração do CDI, permitindo assim que o CDI possa detectar todas as classes nomeadas no projeto. Esse formato utilizado é chamado de arquivo explícito.

Criando arquivo de configuração do CDI beans.xml
[code language=”Java”]
<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”>
</beans> 
[/code]

Transformando o exemplo em um cenário mais conhecido no mercado, as regras de negócio sendo separadas dos controllers, foi necessário a criação de um arquivo de configuração do CDI, no entanto ainda continua simples pois não é preciso manter o arquivo conforme o andamento do projeto, apenas uma configuração para o CDI encontrar os beans nomeados em todo projeto.
Utilizando métodos produtores

No código anterior, foi utilizado uma injeção no atributo do tipo Logger, referente a biblioteca slf4j, na classe SolicitacaoService, isso foi possível utilizando o recurso de métodos produtores (também chamado de produces methods) oferecido pelo CDI, os quais permitem a criação de métodos centralizadores, com objetivo de criação de determinado objeto, de forma que possa ser disponibilizado através de injeção em contextos gerenciados pelo CDI.

Criando classe LoggerProducer
[code language=”Java”]
package br.com.emmanuelneri.utils;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
 
public final class LoggerProducer {

private LoggerProducer() {}
 
 @Produces
 public Logger createLogger(InjectionPoint injectionPoint) {
 return LoggerFactory.getLogger(injectionPoint.getMember()
 .getDeclaringClass().getName());
 } 
}
[/code]

Dessa forma, o @Produces, assinala o método createLogger como um produtor de org.slf4j.Logger. O método recebe por parâmetro um objeto do tipo InjectionPoint, o qual é um recurso do CDI que possibilita obter informações do local da injeção, sendo possível obter informações do local da injeção como, por exemplo, o nome da classe onde foi injetado. 
No exemplo acima, através da injectionPoint, foi obtido o nome da classe, dessa forma, é possível instanciar um Logger de forma dinâmica, apenas utilizando um @Inject em um atributo Logger, onde o método produtor será responsável por criar uma instância através de uma LoggerFactory, de acordo com o nome da classe recebida do parâmetro injectionPoint.

Métodos produtos é uma excelente forma de reduzir código duplicados, o exemplo acima demonstrou como exemplo a criação de logger, caso não fosse usado um método produtor necessário repetir o código de criação do logger em todas as classes que fossem utilizar o recurso, dessa forma o método produtor centralizou a criação em um único ponto e disponibilizou dentro do seu contexto.

Evoluindo a utilização de métodos produtores em controllers

Os métodos produtores ainda podem ser utilizados de inúmeras outras formas, inclusive em conjunto com o JSF, como será demonstrado no exemplo abaixo. O exemplo consiste em criar um método produtor que centralize a captura de valores de parâmetros via GET em uma requisição HTTP, dentro de um contexto JSF. 
Para que a configuração do parâmetro possa ser capturado de forma dinâmica, será criado uma interface chamada HttpParam, apenas contendo um atributo param, o qual será responsável por repassar o nome do parâmetro a ser referenciado no método produtor.

Criando interface HttpParam.java
[code language=”Java”]
package br.com.emmanuelneri.utils.annotations;
 
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
 
@Retention(RUNTIME)
@Target(FIELD)
public @interface HttpParam { 
 public String param(); 
}
[/code]

Após a criação da interface @HttpParam para informar os parâmetros, é necessário o método produtor para receber e executar as devidas ações pare recuperar o valor desejado.

Criando classe HttpParamProducer.java
[code language=”Java”]
 package br.com.emmanuelneri.utils;
 
import br.com.emmanuelneri.utils.annotations.HttpParam;
import javax.enterprise.inject.Produces;
import javax.faces.context.FacesContext;
import javax.servlet.ServletRequest;
 
public class HttpParamProducer {
 
@Produces
@HttpParam(“”)
public String getParamValue(InjectionPoint injectionPoint) {
 final ServletRequest request = (ServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
 return request.getParameter(injectionPoint.getAnnotated().getAnnotation(HttpParam.class).param());
 }
}
[/code]

O objetivo da classe HttpParamProducer é disponibilizar o método getParamValue como produtor, adicionando a anotação: @Produces, o qual recuperará o valor do parâmetro enviado pela requisição dentro do contexto JSF. Dessa forma, atributos anotados com @HttpParam(param = “nomeDoParametro”) serão submetidos a executar o método getParamValue.
Para que possamos ter acesso ao parâmetro da requisição, recuperamos uma ServletRequest do contexto JSF, demonstrado na linha 13. Com isso, é necessário adicionar a dependência da API de servlet no projeto para que possamos referenciar uma ServletRequest. Demonstrado na Listagem 9 logo a seguir.
É importante ressaltar que a instância de FacesContext.getCurrentInstance() utilizada no produtor é a mesma do controller, dessa forma, como estão no mesmo contexto sempre estarão acessando a mesma requisição.

Alterando pom.xml
[code language=”Java”]
<project xmlns=http://maven.apache.org/POM/4.0.0" xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 
 <groupId>br.com.emmanuelneri</groupId>
 <artifactId>javamagazine-cdi-jsf</artifactId>
 <packaging>war</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>Java Magazine CDI + JSF</name>

<properties>
 <cdi.version>1.1</cdi.version>
 <jsf.version>2.2</jsf.version>
 <servlet.version>3.1.0</servlet.version>
 </properties>

<dependencies>
 <dependency>
 <groupId>javax.enterprise</groupId>
 <artifactId>cdi-api</artifactId>
 <version>${cdi.version}</version>
 </dependency>
 <dependency>
 <groupId>javax.faces</groupId>
 <artifactId>javax.faces-api</artifactId>
 <version>${jsf.version}</version>
 </dependency>
 <dependency>
 <groupId>javax.servlet</groupId> 
 <artifactId>javax.servlet-api</artifactId>
 <version>${servlet.version}</version>
 </dependency>
 </dependencies>
….
</project
[/code]

Finalizado a criação do produtor e da anotação o mecanismo está pronto para ser utilizado no atributo de controller, na forma de injeção.

Criando classe HttpParamController.java
[code language=”Java”]
package br.com.emmanuelneri.controller;
 
import br.com.emmanuelneri.utils.annotations.HttpParam;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@RequestScoped
public class HttpParamController {
 
 @Inject
 @HttpParam(param = “parametro”)
 private String parametro;
 public String getParametro() {
 return parametro; 
 }

}
[/code]

Para que um atributo seja preenchido com o valor de um parâmetro ele deve adicionar duas anotações: @HttpParam, para adicionar qual será o nome do parâmetro a ser consultado na request e @Inject, para realizar a chamada do método produtor. Sendo assim, no exemplo, a variável parâmetro será enviada para o método produtor e caso encontrada será preenchido o valor no atributo parâmetro do controller.

Criando arquivo web http-param.xhtml
[code language=”Java”]
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns=”http://www.w3.org/1999/xhtml" 
 xmlns:h=”http://java.sun.com/jsf/html">

<h:body>
 <h:form>
 <h1>HTTP Parametro</h1>
 
 <h:panelGrid columns=”2">
 <h:outputLabel value=”Valor Parametro: “ />
 <h:outputLabel value=”#{httpParamController.parametro}” />
 </h:panelGrid>
 </h:form> 
</h:body> 
</html> 
[/code]

Para testar o exemplo, basta digitar no browser o seguinte link: 
http://localhost:8080/javamagazine-cdi-jsf/http-param.xhtml?parametro=Uma aplicação integrada com JSF

Passagem de parâmetro GET

Dessa forma, o valor a frente do símbolo “=” é atribuído para a variável parâmetro e apresentado logo abaixo, onde o atributo parâmetro do controller está sendo exibido.
Nota: É importante que o Wildfly esteja sendo executado na porta 8080 para que o link acima funcione corretamente.

ViewScope no Java EE 7

Os escopos gerenciados pelo CDI funcionam similar aos escopos JSF, entretanto, para que possam receber as características providas pelo CDI é necessário a utilização dos escopos que pertencem ao pacote javax.enterprise.context.*. É importante atentar-se para não utilizar os escopos nos pacotes do JSF(javax.faces.view.*),
O único escopo que o CDI não implementa é o escopo de visão(ViewScoped), o que o torna uma exceção, pois já existia no Java EE em versões anteriores e a partir da versão 2.2 é oferecido apenas na própria implementação do JSF (encontrado no pacote javax.faces.view.ViewScoped), o qual já possui uma integração com o CDI.
A utilização do escopo de view oferecido pela implementação JSF é similar aos escopos oferecidos pelo CDI, no entanto, é obrigatório a implementação da interface Serializable no controller, o que já era necessário, e em todos os beans que serão utilizados dentro do escopo de visão.

Criando controller ControllerViewScope.java
[code language=”Java”]
01 package br.com.emmanuelneri.controller;
02 
03 import javax.faces.view.ViewScoped; 
04 import javax.inject.Named; 
05 import java.io.Serializable; 
06 
07 @Named
08 @ViewScoped 
09 public class ControllerViewScoped implements Serializable { 
10 } 
[/code]

Futuro das APIs no Java EE 8

Atualmente, o Java EE 8 está em fase de desenvolvimento, onde as APIs CDI na versão 2.0 e o JSF na versão 2.3, farão parte desse pacote. Com isso existe uma expectativa ainda maior para a integração entre as duas APIs, pois um dos propósitos das especificações, é serem arquitetadas de forma 100% integradas. Segundo o documento de proposta da especificação JSR 372, referente ao JSF 2.3, possuirá um grande foco em melhorias do funcionamento em conjunto com o CDI e novos contextos terão suporte a injeção, como FacesContext e ExternalContext. Já no CDI 2.0, o documento de proposta de especificação JSF 365, diz que, a integração com as especificações Java EE estarão por completas, isso inclui o JSF.
Portanto, no Java EE 8, caso as especificações seguirem suas propostas, será possível afirmar que a integração de CDI com JSF estará 100% completa e madura para a utilização em conjunto. No entanto, isso não afirma que a integração terá suporte a todas features existentes em outros frameworks ou extensões já existentes no mercado, como por exemplo, a injeção de dependência em conversores e validadores JSF, ainda não foi mencionado nas especificações.

Conclusão

A integração das APIs CDI e JSF já vem acontecendo a algum tempo desde o lançamento do CDI 1.0 no Java EE 6, entretanto, alguns problemas ocorriam em projetos, isso devido à implementação das APIs que eram desenvolvidas de forma isoladas, sem existir uma preocupação das mesmas funcionarem de forma integrada. Devido essas circunstancias nasceram extensões e bibliotecas, de terceiros, tais como, Deltaspike e OmniFaces para solucionar alguns desses problemas.
A partir do Java EE 7 já houve um amadurecimento das especificações, onde foram arquitetadas para que houvesse uma melhor integração na utilização das mesma, o que conclui-se que hoje estão em um estado estável para utilização integrada. Além disso, esse atual cenário, nos trás uma expectativa ainda maior para o lançamento do Java EE 8, o qual promete uma integração completa do CDI com todas APIs do Java EE, além de aderir ideias já consolidadas no mercado das extensões citadas anteriormente.

Links úteis

Download do Wildfly 8.0.2.Final
http://download.jboss.org/wildfly/8.2.0.Final/wildfly-8.2.0.Final.zip

Especificação CDI 1.1
https://jcp.org/en/jsr/detail?id=346

Especificação JSF 2.2
https://jcp.org/en/jsr/detail?id=372

Show your support

Clapping shows how much you appreciated Emmanuel Neri’s story.