[RESOLVIDO: @SessionScoped] componentes JSF <f:selectItems> e <f:ajax> não estão se entendendo

Boa Noite, estou a muito tempo tentando resolver esta besteira

possuo um <h:selectOneMenu> que está funcionando com <f:ajax>
e outro que não está funcionando

o que está funcionando possui os items do select inseridos a mão:

[code]<h:selectOneMenu value="#{semCookiesBean.estado}" id=“estados”>
<f:ajax event=“valueChange” execute="@this" listener="#{semCookiesBean.popularCidades}" render=“cidades” />

                    <f:selectItem itemLabel="UF" noSelectionOption="true"/>
                    <f:selectItem itemValue="AC" itemLabel="AC"/>
                    <f:selectItem itemValue="AL" itemLabel="AL"/>
                    <f:selectItem itemValue="AM" itemLabel="AM"/>
                    <f:selectItem itemValue="AP" itemLabel="AP"/>
                    <f:selectItem itemValue="BA" itemLabel="BA"/>
                    <f:selectItem itemValue="CE" itemLabel="CE"/>
                    <f:selectItem itemValue="DF" itemLabel="DF"/>
                    <f:selectItem itemValue="ES" itemLabel="ES"/>
                    <f:selectItem itemValue="GO" itemLabel="GO"/>
                    <f:selectItem itemValue="MA" itemLabel="MA"/>
                    <f:selectItem itemValue="MG" itemLabel="MG"/>
                    <f:selectItem itemValue="MS" itemLabel="MS"/>
                    <f:selectItem itemValue="MT" itemLabel="MT"/>
                    <f:selectItem itemValue="PA" itemLabel="PA"/>
                    <f:selectItem itemValue="PB" itemLabel="PB"/>
                    <f:selectItem itemValue="PE" itemLabel="PE"/>
                    <f:selectItem itemValue="PI" itemLabel="PI"/>
                    <f:selectItem itemValue="PR" itemLabel="PR"/>
                    <f:selectItem itemValue="RJ" itemLabel="RJ"/>
                    <f:selectItem itemValue="RN" itemLabel="RN"/>
                    <f:selectItem itemValue="RO" itemLabel="RO"/>
                    <f:selectItem itemValue="RR" itemLabel="RR"/>
                    <f:selectItem itemValue="RS" itemLabel="RS"/>
                    <f:selectItem itemValue="SC" itemLabel="SC"/>
                    <f:selectItem itemValue="SE" itemLabel="SE"/>
                    <f:selectItem itemValue="SP" itemLabel="SP"/>
                    <f:selectItem itemValue="TO" itemLabel="TO"/>
                 </h:selectOneMenu>[/code]

mas o outro select, que possui a lista inserida dinamicamente de acordo com o estado selecionado não funciona
o SETTER dele não esta sendo executado qnd eu seleciono um dos itens da lista, ele só funciona quando seleciono o item “cidade”:

<h:selectOneMenu id="cidades" value="#{semCookiesBean.cidade}" immediate="true"> <f:selectItem itemLabel="Cidade" noSelectionOption="true"/> <f:selectItems value="#{semCookiesBean.cidades}"/> <f:ajax event="change" execute="@this" listener="#{semCookiesBean.teste}"/> </h:selectOneMenu>

o listener esta sendo executado, mas como vou obter a cidade selecionada?

ouvi falar do valueChangeListener, mas não sei se faz diferença, oque vocês acham?

obrigado por qualquer resposta

Posta ai o código do seu semCookiesBean e do Converter que você está utilizando.

@ManagedBean
public class SemCookiesBean {

    private String cep;
    private String estado;
    private String cidade;
    private List<String> cidades;
    private String rua;
    private List<String> ruas;
    private String ruaBusca;

    @EJB
    BancoDeDados bd;

    public void popularApartirDeCep(){
        //popula as listas de estados, cidades e ruas e preencher a rua de
        //acordo com o cep
        //usado para preencher os <select>s e <input> de rua
        if(cep!=null){

            if(cep.length() == 8){
                //select * from cep where cep.cep_id = nosso atributo cep

                Cep endereco = bd.obterCep(Integer.parseInt(cep));
                
                estado = endereco.getEstado();
                popularCidades();

                cidade = endereco.getCidade();

                ruas.clear();
                rua = endereco.getRua();
                ruas.add(rua);
            }

        }

    }

    public void popularCidades(){
        //popula lista de cidades de acordo com o estado
        //usado para preencher o <select> de cidades
        if(estado!=null && !estado.isEmpty())
            cidades = bd.obterCidades(estado);
    }

    public void popularRuas(){
        //popula lista de ruas de acordo com a ruaBusca prenchida, cidade e estado
        //usado para preencher o <select> de ruas
            System.out.println("popularRuas       estado: "+estado+"   cidade: "+cidade+"   ruaBusca: "+ruaBusca);
        if(estado!=null && !estado.isEmpty() && cidade!=null && !cidade.isEmpty()
                && ruaBusca!=null && !ruaBusca.isEmpty()){
            ruas = bd.obterRuas(estado, cidade, ruaBusca);            
        }
    }

}

tirei uma parte do código por ser irrelevante, mas se preferir posso postar ele inteiro
OBS.: se eu popular a lista de cidades ao iniciar o bean ele funciona 100%, mas populando dinâmicamente não funciona mesmo

não estou usando um converter, oque você quis dizer com isso?

e quiser posso postar o facelet inteiro também

Cara, eu vou tentar te ajudar com o que você me passou até agora.

Primeiro eu vou presumir que o seu ManagedBean SemCookiesBean está em escopo de request posto que o seu código não diz nada.
Segundo, você não postou o seu getCidades(). Assim, de acordo com o código do primeiro post, eu vou presumir que esse método deve
estar pareciso com isso:

@ManagedBean
public class SemCookiesBean {
   // ... seu código
   public List<SelectItem> getCidades() {
      return new AbstractList<SelectItem>() {
         @Override public SelectItem get(int i) { return new SelectItem(cidades.get(i), cidades.get(i)); }
         @Override public int size() { return cidades.size(); }
      };
   }
}

E por fim que o seu método setCidade é como:

public void setCidade(String cidade) {
   this.cidade = cidade;
}

Bom, se eu acertei até agora e o seu código ainda não está funcionando, então é melhor você postar
mais desse código. Senão tente deixar o seu código desse jeito.

um converter eh apenas um componente (implements Converter) que transforma um objeto por exemplo Cidade (seguindo o que vc ja possue) em algo que vc possa exibir na tela, ex. nomeCidade, e quando vc sumbete esse valor ele pega o nome e faz a conversao novamente para o objeto Cidade que vc vai persistir digamos no seu pedido, ou seja la qual for a utilizacao do mesmo
pesquise por jsf converters e jsf custom converters para ver exemplos

cidades é uma lista de String, e o JSF resolveu muito bem isso, não precisei de um converter, já utilizei deste jeito em outros projetos,
mas com a tag f:ajax nunca fiz deste jeito, vc acha que este pode ser o problema?

public String getCep() {return cep;}
    public void setCep(String cep) {this.cep = cep;}

    public String getEstado() {return estado;}
    public void setEstado(String Estado) {
        this.estado = Estado;}

    public String getCidade() {return cidade;}
    public void setCidade(String cidade) {
        this.cidade = cidade;System.out.println("FUI EXECUTADO :)");}

    public List<String> getCidades() {return cidades;}
    public void setCidades(List<String> cidades) {this.cidades = cidades;}

    public String getRua() {return rua;}
    public void setRua(String rua) {this.rua = rua;}

    public List<String> getRuas() {return ruas;}
    public void setRuas(List<String> ruas) {this.ruas = ruas;}

    public String getRuaBusca() {return ruaBusca;}
    public void setRuaBusca(String ruaBusca) {this.ruaBusca = ruaBusca;}

alterei meu getCidades de acordo com oque você me orientou mas não fez diferença…

oque eu consigo fazer até agora:

ao selecionar um estado a lista de cidades é preenchida e o select das cidades é preenchido.

oque eu quero fazer:

ao escolher uma cidade do select, execute o método setCidade, para que eu possa fazer com que ao usuario for digitando o nome da rua uma lista de ruas com o nome parecido seja preenchida e ele possa escolher:

                  <h:inputText value="#{semCookiesBean.ruaBusca}" id="rua" size="20">                        
                        <f:ajax event="keyup" execute="@this cidades estados" listener="#{semCookiesBean.popularRuas}" render="ruas" />
                    </h:inputText>

                  <h:selectOneListbox value="#{semCookiesBean.rua}" id="ruas" rendered="#{!empty semCookiesBean.ruas}">
                        <f:ajax event="valueChange" execute="@this" listener="#{semCookiesBean.popularCep}" render="cep" />
                         
                        <f:selectItems value="#{semCookiesBean.ruas}"/>
                    </h:selectOneListbox>

e então poderei saber ql cep ele está com os dados q ele preencheu
obs.: tem o caminho de volta tmb, ele escolhe o cep e os campos são preenchidos, mas isso está funcionando

[b] SOLUÇÃO! ACHEI A SOLUÇÃO!

É NECESSÁRIO USAR A ANOTAÇÃO [/b] @SessionScoped
do pacote faces

import javax.faces.bean.SessionScoped;

@ManagedBean  
@SessionScoped
public class SemCookiesBean {  
//código da classe aqui
}

estou aliviado :slight_smile: