Redirecionamento entre páginas com datatable(primefaces) sem perder os filtros

Olá galera!

Alguém pode me ajudar, por favor?

Deixe-me explicar o que preciso fazer …

Eu tenho 3 páginas e elas são responsáveis ​​por buscar objetos em meus bancos de dados baseados no filtro de seleção da primeira página.

Meu site é sobre anúncios de carros e tem a seguinte estrutura:

1ª página: É responsável pelo filtro de seleção do usuário.

2ª página: É a página da datatable com os resultados do filtro da primeira página.

3ª página: É relacionado com os detalhes do carro

Eu usei @SessionScoped no meu projeto para ser capaz de fazer o que eu quero e “consegui” dessa forma, mas o problema é que quando eu estou na terceira, quarta, quinta página do datatable, ao clicar em uma linha de detalhes do anúncio e retornar para a página do datatable, em vez de ele retorna para a página que eu estava, ele retorna para a primeira não importa onde ela está. Ela sempre retorna para a primeira página…

Por causa disso, eu tentei mudar meu bean para usar @ViewScoped. Eu pensei que iria resolver o meu problema, mas quando eu volto a partir da terceira página do site para a segunda, a datatable perde os dados do filtro(por ser @ViewScoped).

Eu tenho usado o contexto Lazyload, mas acho que não importa para o caso.

Minha necessidade é que o usuário possa clicar em um anúncio e se ele quer voltar exatamente para a página que ele estava, ele consiga.

Agradeço antecipadamente.

@Andrepicoli fez bem tirar o SessionScoped e mudar p/ ViewScoped, temos o ConversationScoped tbm, quiser dar uma olhada no mesmo depois. Seguinte pelo que vc fala os scoped’s estão funcionando corretamente, acho que seu problema está em algum UPDATE do primefaces nos seus componentes. Se poder colocar alguns trechos de códigos p/ analisar.

Opa, valeu o retorno @RaulCrash

Legal, vi algumas coisas sobre o ConversationScoped, mas como me disseram que dava pra resolver na minha atual estrutura, eu to tentando nela ainda.

Sobre o fato de estar funcionando corretamente as scoped’s, a @ViewScoped não esta funcionando a paginação do LazyLoad ainda, mas pretendo resolver isso assim que resolver essa questão do update do componente. Atualmente ele está listando todas os objetos sem a paginação.

Vou postar a estrutura aqui:

Eu estou usando o mesmo Bean pra trabalhar com a sessão usando o put e o get do Flash()

Eu carrego as propriedades do meu objeto e salvo na sessão
FacesContext fc = FacesContext.getCurrentInstance();
FacesContext.getCurrentInstance().getExternalContext().getFlash().put(“busca”, anuncio);

Nota: No término dessa função eu redireciono a página para a página destino pelo próprio Bean
fc.getExternalContext().redirect(“buscapadrao.xhtml”);

Ao chamar minha função de busca, eu uso o método @PostConstruct para verificar se existe o objeto na session e assim buscar uma ArrayList dos objetos que condizem com minha pesquisa.

@PostConstruct
public void init(){

    try{
        
        anuncio = (Anuncio) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("busca");
        
        if(!anuncio.equals(null)){

            // PREÇO
            final BigDecimal[] precos = new BigDecimal[2];

            precos[0] = new BigDecimal(0);
            precos[1] = new BigDecimal(0);

            if((!(anuncio.getPreco() == null)) && (!(anuncio.getPreco().toString().equals(0))) && (!(anuncio.getPreco().toString().equals("")))){
                precos[0] = new BigDecimal(anuncio.getPreco().toString().replaceAll("\\.","").replace(",","."));
                precos[1] = new BigDecimal(anuncio.getPreco().toString().replaceAll("\\.","").replace(",","."));
            }
            
            model = new LazyDataModel<Anuncio>() {

                private static final long serialVersionUID = 1L;

                @Override
                public List<Anuncio> load(int first, int pageSize, String sortField, SortOrder sortOrder,
                        Map<String, Object> filters) {
                    filtro.setPrimeiroRegistro(first);
                    filtro.setQuantidadeRegistros(pageSize);
                    filtro.setAscendente(SortOrder.ASCENDING.equals(sortOrder));
                    filtro.setPropriedadeOrdenacao(sortField);

                    setRowCount(new DAO<Anuncio>(Anuncio.class).quantidadeFiltrados(anuncio, precos, filtro));

                    busca = new DAO<Anuncio>(Anuncio.class).buscaAnuncio(anuncio, precos, filtro);

                    return busca;

                }

            };

    }catch(Exception ex){
    
    }

}

Até então os objetos abrem na datatable(lazyload não funciona, mas quando jogo direto pra lista de objetos sem passar pela função load, dá certo).

Ao clicar em um dos itens da datatable, faço outro redirecionamento para outro managedbean que traz os detalhes do item selecionado no datatable.

fc.getExternalContext().redirect(“anunciodetalhado.xhtml?codigo=”+anuncio.getId()+"");

Até aqui tudo bem, ele constrói certinho os dados, o problema é quando volto pra tela do datatable “buscapadrao.xhtml” que ele perde os dados da consulta que eu fiz anteriormente e me traz a datatable vazia.

Pode me sugerir algo?

Obrigado por enquanto.

Veja só, se você tem um scope de View é que você quer manter no contexto aquele Bean p/ View (óbvio), se tú seta o filtro e tem que ficar recuperando o mesmo no postconstruct sendo no mesmo Bean sempre, você matou o ViewScoped e tá usando mais uma tecnica de ResquestScoped.
Eu sugiro voce separar, até pra você entender melhor, sem muito impacto tenta criar um outro Bean.

@ManagedBean(name="filtroUsuarioBean")
@RequestScoped
public class FiltroUsuarioBean{
     private BigDecimal valorInicial;
     private BigDecimal valorFinal;
//.....
}

E então vc usa no Bean que busca e faz a magica toda das paginas 2 e 3, injetando o FiltroUsuarioBean no scope do JSF. Assim:

@ManagedBean(name="meuBeanOuControllerResponsavelPorMostrarOsVeiculos")
@ViewScoped
public class MeuBeanOuControllerResponsavelPorMostrarOsVeiculos{
//...
    @ManagedProperty(value="#{filtroUsuarioBean}")
    private FiltroUsuarioBean filtroUsuarioBean;

//e assim usaria o filtro como quisesse
sysout(filtroUsuarioBean.getValorInicial());


}

@RaulCrash, já me deu esperanças de resolver esse problema que achei que era irresolúvel. Valeu demais!!!

Eu queria só uma ajuda pra me dizer o que estou errando, por favor.

Eu percebi que usando o @RequestScoped, o servidor faz várias requisições no meu Bean de filtro, mas quando eu chamo a função buscar, função esta responsável por alimentar os dados do filtro, ele não recupera a informação que selecionei no meu combo. Veja se pode me dizer o que estou fazendo de errado.

Essa é a Bean do meu filtro

@ManagedBean(name=“compraBean”)
@RequestScoped

public class CompraBean implements Serializable{
…/
public void buscarAnuncio() throws IOException{

    try{
            //final Anuncio anuncio = new Anuncio();

            if(!(idID == null) && !(idID.equals(""))){
                anuncio.setId(Integer.parseInt(idID));
            }
            
            if(!(idMarca == null) && !(idMarca.equals(""))){
                marca = new DAO<Marca>(Marca.class).buscaPorId(Integer.parseInt(idMarca));
                anuncio.setMarca(marca);
            }

            if(!(idModelo == null) && !(idModelo.equals(""))){
                modelo = new DAO<Modelo>(Modelo.class).buscaPorId(Integer.parseInt(idModelo));
                modelo.setMarca(marca);
                anuncio.setModelo(modelo);    
            }

            if(!(idVersao == null) && !(idVersao.equals(""))) {
                versao = new DAO<Versao>(Versao.class).buscaPorId(Integer.parseInt(idVersao));
                versao.setModelo(modelo);
                anuncio.setVersao(versao);
            }

            if(!(idAnoMod2 == null) && !(idAnoMod2.equals("Selecione"))){
                anomodelo2 = new DAO<Ano>(Ano.class).buscaPorId(Integer.parseInt(idAnoMod2));
                anuncio.setAnofabricacao(anomodelo2.getAno());
            }

            if(!(idAnoMod == null) && !(idAnoMod.equals("Selecione"))){
                anomodelo = new DAO<Ano>(Ano.class).buscaPorId(Integer.parseInt(idAnoMod));
                anuncio.setAnomodelo(anomodelo.getAno());
            }

            if(!(idEstado == null) && !(idEstado.equals(""))){
                estado = new DAO<Estado>(Estado.class).buscaPorId(Integer.parseInt(idEstado));
                anuncio.setEstado(estado);
            }

            if(!(idCidade == null) && !(idCidade.equals(""))){
                cidade = new DAO<Cidade>(Cidade.class).buscaPorId(Integer.parseInt(idCidade));
                anuncio.setCidade(cidade);
            }

            }

            FacesContext fc = FacesContext.getCurrentInstance();
            fc.getExternalContext().redirect("buscapadrao.xhtml");  

        
    }catch(Exception ex){
        System.out.println("Erro ao buscar anúncio");
        ex.getMessage();
    }

}

}

Este é a função chamada pelo .xhtml

       <p:commandButton value="Buscar" id="busca" styleClass="btBuscar"> 
              <p:ajax event="click" listener="#{compraBean.buscarAnuncio}" process="@this"/>
           </p:commandButton> 

Já este é o Bean responsável pela transição das páginas, por recuperar os dados do filtro e apresentar na página com o ViewScoped.

@ManagedBean
@ViewScoped
public class BuscaBean implements Serializable{

/**
 * 
 */
private static final long serialVersionUID = -3259475072329382298L;

@ManagedProperty(value="#{compraBean}")
private CompraBean filtroUsuarioBean;

@PostConstruct
public void init(){

    try{
        
        anuncio = filtroUsuarioBean.getAnuncio();

if(!anuncio.equals(null)){

            model = new LazyDataModel<Anuncio>() {

                private static final long serialVersionUID = 1L;

                @Override
                public List<Anuncio> load(int first, int pageSize, String sortField, SortOrder sortOrder,
                        Map<String, Object> filters) {
                    filtro.setPrimeiroRegistro(first);
                    filtro.setQuantidadeRegistros(pageSize);
                    filtro.setAscendente(SortOrder.ASCENDING.equals(sortOrder));
                    filtro.setPropriedadeOrdenacao(sortField);

                    setRowCount(new DAO<Anuncio>(Anuncio.class).quantidadeFiltrados(anuncio, precos, filtro));

                    busca = new DAO<Anuncio>(Anuncio.class).buscaAnuncio(anuncio, precos, filtro);

                    return busca;

                }

            };

        }

}catch(Exception ex){

    }
}

Acreditava que ao redirecionar a página pelo Bean do filtro, o Bean das transições seria chamado, mas não aconteceu e também o filtro com o escopo de requisição não guardou os dados no meu objeto de filtro.
Na página buscapadrao.xhtml, página de destino(seria a página da datatable) eu chamo os objetos da #{buscaBean.anuncio}, achei que isso também faria startar a managedbean da viewScoped, mas não :confused:

Percebeu que sou bem novato nisso :confused: , se puder me ajudar, agradeço muito.

Obrigado por enquanto

@Andrepicoli tá meio confuso pra mim, mas uma coisa é que o bean Filtro determina somente a responsabilidade de armazenar os dados, nada de redirecionar pagina ou chamar banco. E outra no JSF vc pode fazer redirect via facescontext ou simplesmente retornar pelo metodo(isto mesmo um return e o tipo de retorno do metodo fica String) return "buscapadrao.jsf";

@RaulCrash eu não sabia que poderia dar um return no método com a página de destino (valeu), vou tentar fazer isso.
O que eu não consegui fazer logo de início é carregar os dados do bean filtro e mantê-los com o @RequestScoped, pois em uma única chamada do método buscar(), eu tive várias requisições no bean do filtro e acredito que mesmo que tenha sido alimentado em algum momento, parece que ao entrar novamente pra fazer uma destas várias requisições, ele perde o filtro :confused:. No caso eu devo ter uma função buscar no Bean do filtro como fiz ou seria de outra forma?
Pensando nessa lógica, e se eu usar um @SessionScoped apenas para o filtro, o que acha? Visando o fato que pretendo trabalhar com apenas um objeto e toda vez que setar ele novamente, ele acaba substituindo o objeto do filtro atual.

Eu acreditava que ao chamar a página com outra expression language (no caso a do bean de transição) eu conseguiria receber os dados do filtro e trabalhar com eles, que seria essa a intenção como me passou.

Pelo que vi da sua aplicação ela é simples e pequena, e pode sim usar um SessionScoped pro filtro como é uma particularidade do usuario e vc irá ter ela durante a sessao do usuário, por que não neh?
Mas cara, tira o metodo buscar do seu Bean Filtro, tem que ficar nas da View, se a estrategia é buscar e paginar por view etc…

@RaulCrash, deu certo como você me orientou… consegui me livrar do @SessionScoped na minha busca, agora uso ele apenas para o filtro. Valeu demais!!!

Eu fiz isso pra tentar resolver uma questão de datatable do primefaces que ao usar a tecla backspace do anunciodetalhado(página 3) para o resultado da busca(página 2), ele voltar na ultima página que cliquei do datatable, mas o danado volta pra primeira. Achei que de início o LazyLoad resolveria meu problema, mas não resolveu… aí tentei jogar como viewscoped a busca justamente para o sistema não deixar carregado em sessão o resultado da busca, mas mesmo assim ele ainda volta pra primeira.

Para redirecionar do datatable para a página de anúncio detalhado eu estava usando h:commandLink e redirecionando direto do Bean. Substitui o componente pelo h:link (por causa do redirecionamento do outcome) que quando estou na segunda página (usando o firefox) e vou para terceira e volto para a segunda (no meu localhost), ele funcionou :slight_smile: :slight_smile: :slight_smile: … porém nos outros navegadores não funcionam e atualizando no servidor real, nem o Firefox funfa :frowning: :frowning: :frowning:

Tem alguma sugestão?

Se não tiver, valeu demais… já ajudou bastante!