[Resolvido] Problema no onChange com selectOneMenu (JSF)

Pesssoal,

Estou utilizando jsf2 e estou com um problema:

Tenho uma lista de empresas no meu select. Gostaria que no evento change do select, ao selecionar outra empresa, alterasse o valor da variavel empresa no bean.

Olha como está :

No xhtml está assim

                                   <h:selectOneMenu value="#{meuBean.empresa}"    styleClass="xxlarge "  >

                                        <f:selectItems value="#{meuBean.empresas}" var="empresa" itemValue="#{empresa}" itemLabel="#{empresa.razaoSocial}"/>

                                        <f:ajax event="change"  immediate="true" listener="#{meuBean.alterarEmpresa(empresa)}"/>  

                                    </h:selectOneMenu>

E no ManagedBean do java está:

 public void alterarEmpresa(Empresa e) {

        if (e != null ) {

            System.out.println("Teste1");

        } else {

            System.out.println("Teste2");

        }

    }

Porém o valor da empresa sempre vem como null…

Eu ja li varios posts mas nenhum me ajudou, tentei alterar direto a variavel no bean sem precisar passar por parametro mas também nao deu certo… Alguém pode me ajudar?

Tentei de todas formas possiveis e impossíveis e descobri o seguinte:

Como eu estava passando uma lista de objetos do tipo empresa o JSF não setava o objeto no onchange, nao sei se é uma limitação do JSF, mas pelo que andei lendo , devo utilizar um Converter ou entao passar uma lista de Strings.

Ao passar uma lista de String funcionou da forma mais simples possível:

                                  <f:ajax event="change" immediate="true" listener="#{meuBean.selecionarEmpresa()}"  >  

                                        <h:selectOneMenu value="#{meuBean.empresaSelecionada}"  id="empresa" styleClass="xxlarge "   >  

                                            <f:selectItems value="#{meuBean.listaEmpresas}"   var="empresa" itemValue="#{empresa}"  />  

                                        </h:selectOneMenu>

                                    </f:ajax>

O Pior é que não recebima nenhum log ou msg de erro…

Algumas mensagens são suprimidas pelo JSF se o sistema estiver em produção, para mostrar mensagens a mais no desenvolvimento, é necessário adicionar um parâmetro no seu web.xml <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param>

Valeu pela dica Digao mas agora estou com outro problema:

Puxa vida…

Com Lista de String funcionou certinho, o problema é que eu preciso realmente da lista de objetos do tipo empresa.

Estou fazendo um converter e debugando,

Quando eu seleciono uma empresa ele chama o metodo getAsObject do converter e retorna a empresa que eu selecionei…

O problema é que eu nao sei pra onde ele retorna pq esse valor nao vai para nenhum lugar!

Eu gostaria que fosse para o objeto empresa dentro do meu bean, mas ele nao chama o set

o xhtml esta assim:


                                   <f:ajax event="change" immediate="true" listener="#{cadastrarColetorSamasBean.selecionarEmpresa()}"  >  

                                        <h:selectOneMenu value="#{cadastrarColetorSamasBean.empresa}"  id="empresa" styleClass="xxlarge "   >  

                                             <f:selectItems value="#{cadastrarColetorSamasBean.empresas}"   var="empresa" itemValue="#{empresa}"  itemLabel="#{empresa.razaoSocial}" />  

                                        </h:selectOneMenu>

                                    </f:ajax>

No managed bean:

//  CAMPOS EMPRESA

    public Empresa getEmpresa() {
        return empresa;
    }



    public void setEmpresa(Empresa empresa) {
        this.empresa = empresa;
    }



    // Método realizado ao alterar o select

    public String selecionarEmpresa() {
        Logger.getLogger(CadastrarColetorSamasBean.class.getName()).log(Level.INFO, "Empresa selecionada::: {0}", empresa.getIdEmpresa());
        return null;
    }



    //Popular Combo de Empresa
    public List<Empresa> getEmpresas() throws ClassNotFoundException, SQLException {

        List<Empresa> listaEmpresasSelect = new ArrayList();

        if (this.empresas == null) {

            List<Empresa> empresas = coletorSamasService.popularListaEmpresas();

            for (Empresa e : empresas) {
                listaEmpresasSelect.add(new Empresa(e.getIdEmpresa(), e.getRazaoSocial()));
            }
        }
        return listaEmpresasSelect;

    }

E o Converter:

@FacesConverter(forClass = Empresa.class)

public class EmpresaConverter implements Converter {


    private EmpresaDao daoEmpresa;


    public EmpresaConverter() throws NamingException {
        daoEmpresa = new EmpresaDao();
    }



    @Override

    public Object getAsObject(FacesContext context, UIComponent component, String value) {

        if (value != null && value.trim().length() > 0) {
            int id = Integer.valueOf(value);
            return daoEmpresa.getEmpresaById(id);
        }

        return null;
    }



    @Override

    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value != null) {
            Empresa empresa = (Empresa) value;
            return empresa.getIdEmpresa().toString();
        }
        return "";

    }

Alguém sabe para onde está sendo retornado a empresa retornada pelo getAsObject do Converter?

ele deveria ir para o atributo setado como value do seu <h:selectOneMenu>

Pois é!!! Pior que não vai :frowning:

Tente assim:<h:selectOneMenu value="#{cadastrarColetorSamasBean.empresa}" id="empresa" styleClass="xxlarge " > <f:selectItems value="#{cadastrarColetorSamasBean.empresas}" var="empresa" itemValue="#{empresa}" itemLabel="#{empresa.razaoSocial}" /> <f:ajax event="change" render="@this" execute="@this" listener="#{cadastrarColetorSamasBean.selecionarEmpresa()}" /> </h:selectOneMenu> O que faz esse seu listener?

Hoje o listener tem apenas um logger que eu coloquei um break point para ver se está sendo chamado no on change.

Ao debugar eu vejo que o método selecionarEmpresa() do bean está sendo chamado.

Depois dele ser chamado é chamado o getAsObject do Converter que retorna a empresa corretamente mas essa empresa nao é setada no setEmpresa() do Bean como o esperado.

Depois do getAsObject do Converter que retorna uma empresa que nao é setada em lugar nenhum é chamado o metodo getEmpresas do mesmo Bean para carregar a lista de empresas. E também nesse momento eu verifico o valor da propriedade empresa, e está null. :cry:

Acredito que se eu der um submit o valor deverá ir para o Bean, vou fazer o teste… O problema é q eu gostaria de alterar o valor no onChange …

Isso é perfeitamente possível, eu sempre fiz assim, só não sei se está havendo algum conflito com seu listener, você ja experimentou remover ele? Somente a tag ajax que eu coloquei no exemplo, sem o listener, sempre resolveu o problema pra mim.

Valeu Rodrigo pelas dicas!!

Nao sei porque cargas d’agua o converter nao setava o valor da empresa no bean entao resolvi fazer de uma maneira bem simples

Passo uma lista de empresas para o select.
Ao selecionar passo o id da Empresa para o Managed Bean, ao invés de passar o objeto empresa, e assim o proprio Managed bean faz o papel do converter, ou seja
ele mesmo busca a empresa referente aquele id.

Assim deu certo

No xhtml

   <h:selectOneMenu id="combo-empresa" value="#{solicitarColetorSamasBean.idEmpresaSelecionada}"  >  

                                        <f:ajax event="change" render="@form" listener="#{solicitarColetorSamasBean.atualizaEmpresa}" />  

                                        <f:selectItems value="#{solicitarColetorSamasBean.empresas}"     

                                                       var="empresa" 

                                                       itemValue="#{empresa.idEmpresa}" 

                                                       itemLabel="#{empresa.razaoSocial}" />   

                                    </h:selectOneMenu> 

No ManagedBean

 public void atualizaEmpresa() {

        if (idEmpresaSelecionada != null) {

            Empresa e = (Empresa) coletorSamasService.getEmpresaById(idEmpresaSelecionada);

            coletorSamas.setEmpresa(e);

        }

    }