Fiz um pequeno projeto que é composto por uma única tabela chamada TipoTelefone, com duas colunas (cdTipTel=código do tipo de telefone [pk] e deTipTel=descrição do tipo de telefone), cujo domínio normal seria RES-Residencial, COM-Comercial, CEL-Celular ,FAX-Fax etc).
A tela permite a exibição em um rich:dataTable de todas a linhas da tabela. Através de uma coluna com um h:commandLink é permitida a escolha de um dos elementos da lista.
Coloquei também um h:inputText e um a4j:commandButton que permitem que se filtre as linhas da tabela. Caso o campo esteja vazio é exibida a lista completa.
Quando a lista é filtrada, embora o rich:dataTable esteja exibindo apenas os itens selecionados, quando se clica no link, ele seleciona outro elemento. Troquei para o h:dataTable e o comportamento foi o mesmo.
Ou seja, caso exista uma tabela com o domínio acima ordenada pela descrição e vc mandar pesquisar por COM, no dataTable aparecerá apenas uma linha (COM|Comercial). Se vc clicar no commandLink ele irá trazer o elemento CEL|Celular.
Consultei o HTML gerado e mesmo as linhas não filtradas estão sendo exibidas.
Se não for contra as regras, posso anexar o projeto eclipse (sem os jars é claro).
As tecnologias utilizadas são: JSF 1.2, Hibernate, RichFaces, Eclipse e no meu caso Oracle.
Olhei o seu código e acredito que o problema esteja relacionado ao modo com o qual o JSF processa as fases de seu ciclo.
Quando você faz chamadas ajax, o bean não tem estado, logo a variável lista está vazia qdo o bean é acionado pelo ajax.
A lista é preenchida pelo this.dao.list(); pq, no primeiro momento, o escolheTipoTelefone(ActionEvent e) não é acionado e this.tipTel está null. Num segundo momento, quando o evento é processado e tipTel é preenchido, lista está contendo o valor de 5 registros, não mais o que tinha sido originalmente pesquisado.
Se você faz uma pesquisa e retorna 2 resultados, qdo vc, por ex, escolhe o segundo resultado, o dataTable pede o índice 2 da coleção para atribuir seu valor ao objeto tipTel. O bean então remonta a lista e, no seu código, irá recriar a lista original inteira, pois tipTel ainda é null.
Qdo o bean recebe a informação de q precisa passar pro dataTable o valor do índice 2, ele passa o q estiver na lista, que será o segundo valor da lista original e não da pesquisada.
Não sei se ficou claro.
Para verificar se é isso mesmo, aconselho temporariamente usar o bean como session e só tentar repreencher a lista qdo ela estiver nula. ASsim, qqer resultado dentro dela será preservado.
Entendi o seu raciocínio. Eu considerei que o problema era nas fases do JSF, então, considerando o escopo de request, no meu entendimento o fluxo deveria ser assim:
Primeiro request: A variável deTipTel está vazia, logo é montada a lista inteira.
A visão é montada, o bean é construído e as suas propriedades são preenchidas com os valores de request correspondentes (vazios).
Na fase de Invocar Aplicação, como o texto de pesquisa não está preenchido, a propriedade lista é preenchida com todas as linhas da tabela.
Segundo request: Preencho a variável deTipTel e pressiono o botão PESQUISAR.
A visão é montada, o bean é construído (o bean anterior já morreu, pois é outro request) e as suas propriedades são preenchidas com os valores de request correspondentes (a propriedade de texto da pesquisa do bean agora está preenchida e a lista continua vazia).
Na fase de Invocar Aplicação, como o texto de pesquisa está preenchido, a propriedade lista é preenchida com as linhas da tabela que atendem ao critério (ilike).
Terceiro request (cliquei no commandLink).
A visão é montada, o bean é construído (o bean anterior já morreu, pois é outro request) e as suas propriedades são preenchidas com os valores de request correspondentes (a propriedade de texto da pesquisa do bean agora está preenchida e a lista continua vazia).
Na fase de Invocar Aplicação, como o texto de pesquisa está preenchido, a propriedade lista é preenchida com as linhas da tabela que atendem ao critério (ilike), logo o índice deveria apontar para o mesmo elemento do segundo request.
Alterei o método para ver o que estava acontecendo e observei que é quando ele executa a linha “lista = session.createCriteria(persistentClass).list();”
@SuppressWarnings("unchecked")
public List<T> list() {
logger.info("Listando todos");
List<T> lista;
lista = session.createCriteria(persistentClass).list();
System.out.println("DAO: lista qtde elementos:" + lista.size());
return lista;
}
Você consegue me ajudar a resolver o problema da exceção acima para que eu consiga completar o teste com escopo de sessão?
package handler;
import java.util.ArrayList;
import java.util.List;
import javax.faces.event.ActionEvent;
import modelo.TipoTelefone;
import org.hibernate.Session;
import dao.TipoTelefoneDao;
public class TipoTelefoneHandler {
private TipoTelefoneDao dao;
private TipoTelefone tipTel = new TipoTelefone();
private List<TipoTelefone> lista = new ArrayList<TipoTelefone>();
public TipoTelefoneHandler() {
super();
}
public TipoTelefoneDao getDao() {
return dao;
}
public void setDao(TipoTelefoneDao dao) {
this.dao = dao;
}
public List<TipoTelefone> getLista() {
System.out.println("**************************************************************************");
System.out.println("===> Localizando tipo de telefone por (" + this.tipTel.getDeTipTel() + ")");
if (this.tipTel.getDeTipTel() != null) {
this.lista = this.dao.list(this.tipTel.getDeTipTel());
} else {
this.lista = this.dao.list();
}
System.out.println("===> QTDE DE TIPOS DE TELEFONE: " + lista.size());
return this.lista;
}
public void setLista(List<TipoTelefone> lista) {
this.lista = lista;
}
public TipoTelefone getTipTel() {
return tipTel;
}
public void setTipTel(TipoTelefone tipTel) {
this.tipTel = tipTel;
}
public void setSessao(Session s) {
this.dao = new TipoTelefoneDao(s);
}
public String salva() {
System.out.println("Adicionando: " + tipTel.getDeTipTel());
this.dao.merge(this.tipTel); this.tipTel = new TipoTelefone();
return "";
}
public String pesquisa() {
System.out.println("Pesquisando: " + this.tipTel.getDeTipTel());
this.getLista();
return "tipoTelefone";
}
public String apaga() {
System.out.println("Eliminando: " + this.tipTel.getCdTipTel() + " " + this.tipTel.getDeTipTel());
if (this.tipTel.getCdTipTel().length() > 0) {
this.dao.delete(this.tipTel);
this.tipTel = new TipoTelefone();
}
return "sucesso";
}
public void escolheTipoTelefone(ActionEvent e) {
System.out.println("==============================================================================");
System.out.println("Localizando tipo de telefone:" + this.tipTel.getDeTipTel());
}
public String escolhe() {
System.out.println("------------------------------------------------------------------------------");
System.out.println("Localizando tipo de telefone:" + this.tipTel.getDeTipTel());
return "tipoTelefone";
}
}
Quando eu troco o escopo para session, recebo um java.lang.NullPointerException na hora que estou obtendo a lista no banco de dados, o que não acontece quando o escopo é de request.
Orlando, vou olhar para você o código, mas provavelmente só na noite de sexta e te respondo. Espero que não fique tarde demais para você, mas estou em semana de provas.