[RESOLVIDO] Como manter o estado de um managedBean entre duas páginas com JSF 2?

29 respostas
lindberg713

Pessoal, comecei agora a ver JSF 2, sempre trabalhei com o 1 e me deparei com um problema que já pesquisei e não consegui resolver ainda. Como faço pra manter o estado de um bean, ou seja manter a instância de uma managedBean entre duas páginas que usam o mesmo managedBean? No 1, usando rich usando richfaces bastava um a4j:keepAlive que já resolvia. Agora não estamos mais usando o richfaces e sim o primefaces, então como posso fazer isso? Tenho uma página e quero ir para outra página que usa o mesmo managedBean e manter a instância desse MB. O jsf está criando uma nova instância.

Já dei uma olhada nos escopos do JSF 2 e vi que tem um @ViewScoped mas ele só faz o trabalho do keepAlive em parte pois só funciona para a mesma página pois se mudar de página uma nova instância é criada. Preciso manter a mesma enquanto o managedBean estiver sendo usado.

Obrigado!

29 Respostas

Hebert_Coelho

Na verdade o @ViewScoped funciona quando você utiliza CDI, se você utilizar ManagedBean normal mesmo ele não funciona.

O que você pode fazer é:

  1. Colocar seu MB como SessionBean
  2. Carregá-lo sempre de um para o outro e manter o MB como request. Por exemplo você tem o objeto Arvore na tela A. No managedBean você teria um get/set. E vai para tela B. Nessa tela B vc coloca todos os campos lá e get/set no novo mangedBean. E assim vai. [=
lindberg713

jakefrog:
Na verdade o @ViewScoped funciona quando você utiliza CDI, se você utilizar ManagedBean normal mesmo ele não funciona.

O que você pode fazer é:

  1. Colocar seu MB como SessionBean
  2. Carregá-lo sempre de um para o outro e manter o MB como request. Por exemplo você tem o objeto Arvore na tela A. No managedBean você teria um get/set. E vai para tela B. Nessa tela B vc coloca todos os campos lá e get/set no novo mangedBean. E assim vai. [=

Obrigado pela resposta, cara colocar como session resolve mas não é o que eu quero. Isso vai fazer com que o bean esteja vivo sempre na sessão mesmo quando este não estiver sendo usado. Sem contar que será uma instância para cada sessão de usuário. Esse não é o comportamento que eu gostaria.

A sua segunda alternativa pelo que entendi foi o que pensei em fazer também, mas acredito que deve haver uma forma mais simples e prática de fazer isso. Se não tiver como fazer de uma forma simples no JSF 2 é uma pena, pois eles poderiam ter colocado um scopo desse, tipo conversation entre as paginas enquanto o bean estiver sendo usado, quando for pra uma pagina que não use esse bean então descarta essa instância.

Se não tiver, vou parar em breve e estudar uma forma de implementar algo que faça e seja algo simples de ser usado ai vou publicar como um simples jar para quem quiser usar. Penso algo como um novo scopo tipo @blablabla que vc vai colocar no seu bean e ele vai funcionar assim. Se realmente nao tiver, vou estudar bem como funciona o JSF 2, seus pontos de extensão e eu vou fazer isso.

Hebert_Coelho

Existir existe, que é o @ViewScope. Mas você terá que utilizar por CDI (que é a nova “vibe” do JSF). [=

L

Pode fazer uma conversação.

import java.io.Serializable;

import javax.annotation.ManagedBean;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;

@ManagedBean
@ConversationScoped
public class UsuarioBean implements Serializable {
    @Inject
    private Conversation		conversation;

    public String begin() {
        this.conversation.begin();
        return "pagina-de-inicio-da-conversacao";
    }

    public String end() {
        this.conversation.end();
        return "pagina-final-da-conversacao";
    }
}
lindberg713
lsjunior:
Pode fazer uma conversação.
import java.io.Serializable;

import javax.annotation.ManagedBean;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;

@ManagedBean
@ConversationScoped
public class UsuarioBean implements Serializable {
    @Inject
    private Conversation		conversation;

    public String begin() {
        this.conversation.begin();
        return "pagina-de-inicio-da-conversacao";
    }

    public String end() {
        this.conversation.end();
        return "pagina-final-da-conversacao";
    }
}

Obrigado pela dica cara,, mas testei aqui da forma como você falou e não funciona. Ele simplesmente quando eu mudo de página cria uma nova instância do managedBean então eu perco o estado do bean. Só pra contar, estou usando CDI.

alias

Amigos, aproveitando o gancho do tópico, o ViewScoped não é apenas para persistir o bean na mesma pagina? Achava que ele mantinha o estado ENQUANTO as requests feitas fossem para a mesma página…não é isso?

Ao colega lindberg713, o Seam tem o escopo Conversation, que faz isso que voce quer. Pode ser uma opção.

lindberg713

alias:
Amigos, aproveitando o gancho do tópico, o ViewScoped não é apenas para persistir o bean na mesma pagina? Achava que ele mantinha o estado ENQUANTO as requests feitas fossem para a mesma página…não é isso?

Ao colega lindberg713, o Seam tem o escopo Conversation, que faz isso que voce quer. Pode ser uma opção.

Eu conheço o Seam mas o nosso projeto aqui não usa. Estou lendo a documentação aqui do CODI. Que é a extensão do apache myfaces do CDI e que tem um escopo ViewAccessScoped que faz exatamente isso que quero. Se eu conseguir resolver usando isto eu posto aqui.

L

Fiz um projeto bem simples com 3 xhtml e um bean, vê se é mais ou menos isso que vc quer.

O anexo é um projeto Eclipse Web, testei no JBoss AS 7.0.2.

lindberg713

lsjunior:
Fiz um projeto bem simples com 3 xhtml e um bean, vê se é mais ou menos isso que vc quer.

O anexo é um projeto Eclipse Web, testei no JBoss AS 7.0.2.

Vou testar, obrigado!

lindberg713

Resolvido.

Adicionei o apache myfaces CODI (http://myfaces.apache.org/extensions/cdi/) que é uma extensão do CDI e que adiciona novos escopos de beans. O CODI provê dentro vários recursos e escopos de beans o escopo @ViewAccesScoped que é exatamente o que preciso. Enquanto o usuário estiver em uma página que use o managedBean o estade deste bean é mantido.

Para maven basta adicionar as dependencias abaixo (caso esteja usando JSF 2):

org.apache.myfaces.extensions.cdi.modules myfaces-extcdi-jsf20-module-api 1.0.1 compile
<dependency>
		<groupId>org.apache.myfaces.extensions.cdi.modules</groupId>
		<artifactId>myfaces-extcdi-jsf20-module-impl</artifactId>
		<version>1.0.1</version>
		<scope>runtime</scope>
	</dependency>
	
	<dependency>
		<groupId>org.apache.myfaces.extensions.cdi.core</groupId>
		<artifactId>myfaces-extcdi-core-api</artifactId>
		<version>1.0.1</version>
		<scope>compile</scope>
	</dependency>

	<dependency>
		<groupId>org.apache.myfaces.extensions.cdi.core</groupId>
		<artifactId>myfaces-extcdi-core-impl</artifactId>
		<version>1.0.1</version>
		<scope>runtime</scope>
	</dependency>
alias

Sensacional essa feature cara, muito bom, mas nao entendi o funcionamento, voce diz que enquanto o managed bean for usado na pagina X o estado será mantido, e quando o usuario for pra pagina Y, que era o que voce queria? O mesmo estado é mantido? Ele usa a sessão pra fazer isso?

lindberg713

O funcionamento é o seguinte. Enquanto o usuário estiver navegando em alguma pagina que uso aquele bean ele mantem o estado. Por exemplo, o usuário ta na pagina A que usa o bean X. Entao muda pra pagina B que também usa o bean X. Então de A para B o estado do bean X é mantido. Da mesma forma, se ele for de B para C e C tb usar o bean X o estado continua. Agora se por exemplo ele for para pagina D e esta não faz qualquer referencia ao bean X, então é estado do bean é destruido.

Como ele faz eu não sei pois não me aprofundei na implementação deste recurso, mas dei uma olhada na documentação e é muito boa.

alias

lindberg713:
O funcionamento é o seguinte. Enquanto o usuário estiver navegando em alguma pagina que uso aquele bean ele mantem o estado. Por exemplo, o usuário ta na pagina A que usa o bean X. Entao muda pra pagina B que também usa o bean X. Então de A para B o estado do bean X é mantido. Da mesma forma, se ele for de B para C e C tb usar o bean X o estado continua. Agora se por exemplo ele for para pagina D e esta não faz qualquer referencia ao bean X, então é estado do bean é destruido.

Como ele faz eu não sei pois não me aprofundei na implementação deste recurso, mas dei uma olhada na documentação e é muito boa.

Entendi, legal…mas suponho que ele use a sessão para armazenar isso, ao menos nao vejo outra forma de fazer. De qualquer forma, deveras útil.

R

olá lindberg bom dia,
quanto ao Apache CODI vc só baixou os jars pelo mavem e adiciou-los no classpath ou tem que fazer alguma configuração a mais tipo no web.xml ou outro arquivo?é só baixar e usare?
tipo não gosto do maven quero baixar manualmente ,quais são os jars necessários??

aguardando a resposta!
vlw ! obrigado!

lindberg713

rjpereira1000000:
olá lindberg bom dia,
quanto ao Apache CODI vc só baixou os jars pelo mavem e adiciou-los no classpath ou tem que fazer alguma configuração a mais tipo no web.xml ou outro arquivo?é só baixar e usare?
tipo não gosto do maven quero baixar manualmente ,quais são os jars necessários??

aguardando a resposta!
vlw ! obrigado!

Bom dia cara, eu só declarei no meu pom.xml do meu maven e pronto. Ele já sobe junto com a aplicação. Dei uma olhada rapida aqui pra ver se precisei fazer mais alguma coisa e nao me recordei de nada a mais. Caso não funcione fala ai. Como uso o maven, ele ja baixa as dependencias necessárias então não preciso me preocupar. Neste caso como nao vai usar, empacotei os jars do myfaces-codi que vao dentro do meu war a partir do maven. Então se falatar alguma dependencia fala ai tb, mas acredito que ta tudo ai pois dei uma olhada na hierarquia de dependencias do maven para o codi e só tem isso que to te mandando. Coloquei os jars num .zip no link abaixo. Baixa ai rapido que mais tarde vou remover desse link. Abraço.

www.lindbergframework.org/diversos/codi.zip

lindberg713

lindberg713:
rjpereira1000000:
olá lindberg bom dia,
quanto ao Apache CODI vc só baixou os jars pelo mavem e adiciou-los no classpath ou tem que fazer alguma configuração a mais tipo no web.xml ou outro arquivo?é só baixar e usare?
tipo não gosto do maven quero baixar manualmente ,quais são os jars necessários??

aguardando a resposta!
vlw ! obrigado!

Bom dia cara, eu só declarei no meu pom.xml do meu maven e pronto. Ele já sobe junto com a aplicação. Dei uma olhada rapida aqui pra ver se precisei fazer mais alguma coisa e nao me recordei de nada a mais. Caso não funcione fala ai. Como uso o maven, ele ja baixa as dependencias necessárias então não preciso me preocupar. Neste caso como nao vai usar, empacotei os jars do myfaces-codi que vao dentro do meu war a partir do maven. Então se falatar alguma dependencia fala ai tb, mas acredito que ta tudo ai pois dei uma olhada na hierarquia de dependencias do maven para o codi e só tem isso que to te mandando. Coloquei os jars num .zip no link abaixo. Baixa ai rapido que mais tarde vou remover desse link. Abraço.

www.lindbergframework.org/diversos/codi.zip

Fiz melhor, coloquei no 4shared.com no link abaixo, ai fica disponível sempre pra todo mundo que precisar.

http://www.4shared.com/file/yKurRw7B/apache-myfaces-codi.html?

R

obrigado por compartilhar,obrigado mesmo!!

R

Olá pessoal, estou com o mesmo problema no meu projeto, estou utilizando o JSF 2 + Primefaces 3 + Spring + Tomcat. Na versão antiga eu resolvia esse problema utilizando o KeepAlive mas nesse nova versão eu não tenho essa possibilidade, desta forma, lendo o post do lindberg71, resolvi adicionar ao meu projeto o apache CODI para poder utilizar o ViewAccessScoped e adicionei os jars disponibilizados pelo lindberg71, entretanto, ao levantar minha aplicação está dando um erro:

com.sun.faces.config.ConfigurationException: Factory javax.faces.context.FacesContextFactory was not configured properly.

at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:292)

at com.sun.faces.config.processor.FactoryConfigProcessor.process(FactoryConfigProcessor.java:209)

at com.sun.faces.config.ConfigManager.initialize(ConfigManager.java:332)

at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:220)

at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4723)

at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5226)

at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5221)

at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)

at java.util.concurrent.FutureTask.run(FutureTask.java:138)

at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)

at java.lang.Thread.run(Thread.java:619)

Caused by: javax.faces.FacesException: org.apache.myfaces.extensions.cdi.jsf2.impl.listener.request.CodiFacesContextFactory

at javax.faces.FactoryFinder.getImplGivenPreviousImpl(FactoryFinder.java:589)

at javax.faces.FactoryFinder.getImplementationInstance(FactoryFinder.java:468)

at javax.faces.FactoryFinder.access$400(FactoryFinder.java:135)

at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:792)

at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:302)

at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:290)

Precisa fazer alguma configuração no web.xml ?? O meu está assim:

<?xml version="1.0" encoding="UTF-8"?>
<display-name>cubo</display-name>

<servlet>
	<servlet-name>Faces Servlet</servlet-name>
	<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>

<context-param>
	<param-name>javax.faces.PROJECT_STAGE</param-name>
	<param-value>Development</param-value>
</context-param>

<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
</servlet-mapping>

<welcome-file-list>
    <welcome-file>index.html</welcome-file>
</welcome-file-list>

<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>classpath:applicationContext.xml</param-value>
</context-param>

<context-param>
	<param-name>primefaces.skin</param-name>
	<param-value>none</param-value>
</context-param>
A

Olá lindberg713.

Estou com o mesmo problema!

Adicionei os Jars do CDI e configurei meu bean conforme abaixo:

import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.ViewAccessScoped;
import javax.faces.bean.ManagedBean;
@ManagedBean
@ViewAccessScoped
public class beanMB{
...
}

Na view eu tenho um rich:tabPanel com várias páginas, sendo que, a primeira é a pequisa. O usuário efetua a pesquisa na primeira tab e clica em editar, com isso a segunda e terceira tabs são desbloquedas. Na segunda tab tudo funciona normamente, porém na terceira existe uma opção de um relatório e quando eu clico no botão para imprimir o relatório (em outra janela), o bean é recriado.

Com o KeepAlive funcionava normalmente.

Alguém sabe a causa desse problema?

alandiniz

muito interessante isso ai… eu precisei no meu projeto esses dias e tive que fazer uma verdadeira “gambiarra”…

será que tem algum tutorial ou alguma explicação mais detalhada de como implementar em um projeto?

é que eu não uso maven, e não entendi muito bem os códigos acima.

Obrigado.

A

A dica abaixo esta no site da apache.org na parte que fala sobre @ViewAccessScoped. Mas eu não faço idéia de como fazer isso funcionar, se alguém souber por favor informe.

https://cwiki.apache.org/confluence/display/EXTCDI/JSF+Usage#JSFUsage-ViewAccessScope

Hint
@ViewAccessScoped beans are best used in conjunction with the CODI ClientSideWindowHandler, which ensures a clean browser-tab separation without touching the old windowId. Otherwise a ‘open in new tab’ on a page with a @ViewAccessScoped bean might cause the termination (and re-initialization) of that bean.

lindberg713

Pessoal, desculpa a demora em responder. É que por algum motivo eu não to recebendo email dos posts do guj. Por acaso foi que eu vi agora.

IMPORTANTE: Enifm, antes de mais nada, quero dizer que o myfaces CODI é uma extensão do CDI. Então para que seu projeto funcione e tenha esse recurso do ViewAccessScoped seu projeto deve ser baseado no CDI. A implementação de referencia do CDI é o JBoss Weld. Vejam na descrição do projeto CODI ,“MyFaces CODI is your best friend for CDI based projects”, que ele diz que é o seu melhor amigo para projetos baseados em CDI. Ou seja, para funcionar seu projeto tem que usar o CDI.

IMPORTANTE: Um outro detalhe importante é que o managedbean tem que ser Serializable. Tanto o managedbean quanto o que beans que vc usa dentro do managedbean. Por exemplo, uma fachada ou bc que vc injeta no seu MB devem ser Serializable.

Vi que muitos perguntaram se eu adicionei alguma coisa no meu web.xml, seu eu fiz alguma configuração e tal. Nao precisei fazer nada. Só adicionei as dependencias no pom do maven, para quem nao usa maven é equivalente a adicionar as libs no meu WEB-INF/lib, e prontsó subi a aplicação e ta funcionando. Mas repito. O meu projeto, mesmo contra minha vontade pois é la do meu trabalho e prefiro usar o spring, é baseado no CDI.

De qualquer forma, vejo que esse é um problema universal. Todo mundo passa por isso, todo mundo quer esse escopo e todo mundo fica se perguntando como fazer. Neste exato momento estou precisando disso em um projeto que comecei aqui em casa e nao estou usando o CDI, pois como falei, prefiro muito mais o spring 3.

Então, vou desenvolver esse novo scopo de conversação entre paginas para o JSF 2, como uma extensão, vou tentar fazer algo simples e plugavel, de modo que seja facil que nem fazer miojo colocar e usar. Esses dias ainda volto aqui pra dizer como resolvi esse problema sem usar o CDI. Seja usando spring atraves da criação de um novo scopo ou direto no JSF 2. Enfim, aguardem que esses dias eu retorno.

Quem tiver usando CDI basta colocar as libs que compartilhei e subir a aplicação que funciona.

Qualquer duvida posta ae.

lindberg713

Pessoal, consegui.

Passei essa noite trabalhando em como fazer para implantar o escopo de conversação e view no JSF baseado em beans do spring e depois de muito estudar e pesquisar consegui colocar o escopo de conversação (enquanto uma página estiver usando o managedbean) e o escopo de view (o estado permanece ativo para a página atual).

Ficou, show de bola, funcionando beleza. Tive um bom trabalho pesquisando, estudando e colocando em pratica.

O único detalhe é que tem que usar o spring. Pois os dois novos escopos serão gerenciados pelo spring e o managedbean tem que ser um bean do spring.

Como o mais normal é usarmos um container de inversão de controle para injeção de dependencias, creio que todos aqui usam, seja spring ou seja uma implementação do CDI, então creio que o problema ta resolvido. Pois se o projeto usar CDI, o que to usando la no meu trabalho, basta adicionar o apache myfaces CODI como eu disse aqui neste topico nos posts anteriores. Se usar o spring, que é minha preferencia e o que to usando no meu projeto particar, basta usar a solução que apliquei trabalhando esta noite.

Mas vcs devem ta se pergutando e cade a solução, cade o diabo da solução.

Calma, calma… Eu vou fazer o acabamento, até amanha e gerar uma lib de modo que pra vc seja o mais simples e transparente de modo que para usar e configurar seja simples.

Então até amanha faço isso e posto aqui um mini tutorial com as instruções para colocar esses dois escopos.

lindberg713

Pessoal, prometi postar a solução aqui mas como estou viajando daqui a pouco ja pro carnaval e hoje foi muita coisa pra organizar acabei não tendo tempo pra postar aqui. Assim que voltar do carnaval eu posto tudo direitinho aqui.

Abraço.

FilipeNevola

Encontrei este mesmo problema e criei uma solução:

https://bitbucket.org/filipenevola/filipe-nevola-helper/wiki/BeingUsedScope

Enquanto você estiver usando este Bean em requests consecutivos ele continuará vivo.

att,

lindberg713

Pessoal, demorei mas ka estou pra dar o feedback da solução. Tava viajando e só agora puder postar.

Para simplificar toda a configuração, implementei uma lib que já prover os escopos de view e de conversação de forma integrada entre o spring3 e jsf 2. Essa lib se chama myview e ta como submodulo do framework que mantenho chamado lindbdegframework. Nada complicado não. Só coloquei como submodulo do framework de modo a aproveitar todo a infraestrutura que ja tenho configurada do maven, blog, etc… do meu framework. A ideia é a medida que eu for criando soluções para estes tipos de problemas que todo mundo aqui fica atrás, fica postando e fica se arrancando os cabelos atrás, ai eu vou colocando no myview e lançando releases.

Para usar é muito simples. Basta seguir o tutorial do link abaixo. Tem explicando como usar a partir do maven e tb sem usar o maven. Uma vez seguidos os passos do tutorial abaixo, basta anotar seus managedBeans do JSF (gerenciados pelo spring, tem que ser gerenciados pelo spring e no tutorial tem mostrando, caso não saiba, como fazer) com as annotations @AccessScoped para definir um escopo de conversação e manutenção de estado enquanto alguma página estiver acessando o managedbean ou @SameViewScoped para definir um escopo de mesma página, ou seja, que a instancia do managedbean ficará viva enquanto a mesma página estiver ativa.

Sem mais delongas, vamos ao que interessa. Veja o tutorial do myview no link abaixo.

Tutorial do lindbergframework-myview: http://lindbergframework.blogspot.com/2012/02/como-manter-o-estado-de-um-managedbean.html

Abraço, espero ter ajudado.

Sempre a disposição,

Victor Lindberg

gilnei.aquino

Obrigado @lsjunior seu projeto resolveu minhas duvidas sobre ConversationScoped.

lindberg713

Obrigado pelo feedback.

DaniloAndrade

Boa noite pessoal!

Lendo o post e me interessei pelo Apache myFaces CODI e tive os mesmo problemas que vcs para usa-lo… mas depois de ler muito a documentação consegui fazer funciona em um projeto de teste.

segue mini tutorial sobre as dependências do CODI


para usar a extenção do CDI myFaces CODI com o jsf é necessario ter:

  • implementação do JSF

  • implementação do CDI

  • implementação do Bean Validator

e deve se adicionar ao projeto os seguinte modulos do CODI

  • CODI core

  • CODI-JSF module

  • CODI-Message

  • BV-Module

o modulo CODI core possui os seguintes jars:
- myfaces-extcdi-core-api-1.x.x.jar
- myfaces-extcdi-core-impl-1.x.x.jar

o mudulo CODI-JSF possui os seguintes jars:
- myfaces-extcdi-jsf20-module-api-1.x.x.jar
- myfaces-extcdi-jsf20-module-impl-1.x.x.jar

o modulo CODI-Message possui os seguintes jars:
- myfaces-extcdi-message-module-api-1.x.x.jar
- myfaces-extcdi-message-module-impl-1.x.x.jar

o modulo BV possui os seguintes jars:
- myfaces-extcdi-bv1-module-api-1.x.x.jar
- myfaces-extcdi-bv1-module-impl-1.x.x.jar

no projeto teste, utilizei como implementação do JSF o Mojarra 2.1.16, para o CDI utilizei o Weld 1.1.10, e para o Bean Validator o Hibernate Validator 4.3.1

nos seu ManagedBean deveram ser anotados com as annotations do CDI e implementar Serializable

não vou entrar em detalhas sobre a criação do projeto e configuração do JSF e CDI por que ja tem muitos tutoriais aqui e artigos falando sobre o assunto

Criado 3 de novembro de 2011
Ultima resposta 3 de jan. de 2013
Respostas 29
Participantes 11