Estou estudando o framework JSF 2.0 juntamente com CDI. Os exemplos que vi até o momento utilizam o escopo de sessão nos MenagedBeans. No entanto já li também que não é recomendado utilizar muito o @SessionScoped, visto que pode trazer problema de desempenho. Sendo assim, eu gostaria de saber qual é o escopo mais indicado para colocar os MenagerBeans quando é necessário implementar CRUDs, tipo cadastro de produto, cadastro de usuários, etc. Gostaria de saber se o @ConversationScoped pode ser bastante usado neste casos ou se tem alguma restrição.
Realmente é bom evitar o @SessionScoped. Um bom uso dele é um carrinho de compras por exemplo, que guardaria os itens comprados pelo usuário enquanto este está na página.
Para o seu caso de CRUD voce poderia trabalhar com o @RequestScoped(padrão) já que após o cadastro você não precisa mais daquele Bean (salvo alguma exceção sua).
A minha dúvida foi sanada com a opinião de vocês. Agora eu gostaria de um auxilio para implementar um cadastro com o @ResquestScoped.
Inicialmente eu tenho uma pagina com um CommandLink que aponta para o método listaContatos(), o qual lista os objetos corretamente no DataTable da pagina list.xhtml. Nesta página, tenho um um link para adicionar um novo Contato que chama o metodo doNewContato(). Mas como a cada nova requisição os dados são perdidos os que foram setados neste método não são visíveis quando for gravar.
Sendo assim, gostaria de saber como poderiam implementar esse MenagerBean para resolver este problema.
Segue o código do MB.
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import br.com.teste.entity.Contato;
import br.com.teste.session.ContatoSession;
@Named("contatoFaces")
@RequestScoped
public class ContatoFaces extends CDIBean<Contato> implements java.io.Serializable{
private static final long serialVersionUID = 1L;
@Inject
private ContatoSession contatoSession;
private List<Contato> lista;
public String listaContatos(){
return "/pages/contato/list.faces?faces-redirect=true";
}
public String doNewContato(){
setSelectedItem(new Contato());
return "/pages/contato/add.faces?faces-redirect=true";
}
public String finishAddContato(){
contatoSession.save(getSelectedItem());
return "/pages/contato/list.faces?faces-redirect=true";
}
public List<Contato> getLista() {
carregaLista();
return lista;
}
private void carregaLista(){
if (this.lista == null || this.lista.isEmpty())
lista = contatoSession.getAll();
}
}
Acho que não entendi a sua dúvida: Você tem um form, que você tem uma opção de inserir um novo contato, ente link ou botao te leva
a um formulário que contém os campos pra vc preencher e em seguida um botão para Enviar/Cadastrar etc correto?
Desta forma o @RequestScope atende bem não?
Desculpe-me pela demora em responder e muito obrigado por responder as minhas perguntas . A dúvida seria como implementar esse bean que postei anteriormente para utilizado no @ResquetScoped. Pois da maneira que está, ele funciona perfeitamente com @SessionScoped, mas se eu colocar no escopo de requisição não funciona, uma vez que os dados se perder a cada requisição.
Na verdade os dados não deveriam ser perdidos justamente por que quando você invoca o método, ainda está na mesma requisição = )
Resumindo teríamos algo como:
@ManagedBean
@RequestScope //Não precisa dele aqui pois é padrão, mas só para visualizar = )
public class ContatoBean {
private nome;
private endereco;
public void cadastra() {
if(nome != null && endereco != null) {
contatoDAO.salva(nome, endereco);
}
}
}
Claro que é um exemplo bem tosco e esse código que coloquei não deveria existir em produção = P
Mas só pra exemplificar. Quando você tem um form com os dados deste bean (lá no form teríamos contatoBean.nome e contatoBean.endereco) e clica em um botao
para envio dos dados (botao com a action invocando o método cadastra()) então estamos enviando uma requisição e seus dados “nome” e “endereço” estarão preenchidos.
Entendi perfeitamente agora. Na verdade era uma falta de entendimento do ciclo de vida. Como a cada requisição o meu Bean é instaciado novamente, eu coloquei no construtor um código para instanciar a minha entidade contato. Dessa forma, quando eu clico no botão Salvar, ele instancia a entidade e salva na mesma requisição. O problema da minha implementação anterior é que eu instanciava a minha entidade na requisição anterior quando eu ia da pagina de listagem para a página de cadastro. Dessa forma quando clicava em salvar já não era mais a mesma instancia da entidade.
Segue o código do MenagedBean para cadastro:
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import br.com.teste.entity.Contato;
import br.com.teste.session.ContatoSession;
@Named("contatoFaces")
@RequestScoped
public class ContatoFaces extends CDIBean<Contato> implements java.io.Serializable{
private static final long serialVersionUID = 1L;
@Inject
private ContatoSession contatoSession;
private List<Contato> lista;
public ContatoFaces(){
setSelectedItem(new Contato());
}
public String doNewContato(){
return "/pages/contato/add.faces?faces-redirect=true";
}
public String finishAddContato(){
contatoSession.save(getSelectedItem());
return "/pages/contato/list.faces?faces-redirect=true";
}
}
Gostaria de agradecê-lo pela ajuda.
Muito Obrigado.