JSF e os Objetos no <h:selectOneMenu <RESOLVIDO>

15 respostas
aeciovc

Boa Tarde,

o que acontece é que tenho um Select assim:

&lt;h:selectOneMenu value="#{projetoManaged.projeto.cliente.codCliente}"  valueChangeListener="# {projetoManaged.valueChangeListener}" immediate="true" &gt;
                        
                        &lt;f:selectItems value="#{projetoManaged.clientes}" var="cliente" itemLabel="#{cliente.codCliente}" itemValue="#{cliente.codCliente}"/&gt;
                    &lt;/h:selectOneMenu&gt;

porém ele sempre tá retornando null isso: itemValue="#{cliente.codCliente}

não consigui fazer funcionar dessa forma com selectItems... sabendo que a lista não está vazia pois meu Bean coloca a lista correta como:

for (Cliente cliente : c) {
            clientes.add(new SelectItem(cliente, cliente.getNome()));

        }

quando faço assim:

&lt;f:selectItem itemLabel="a" itemValue="a"/&gt;
&lt;f:selectItem itemLabel="b" itemValue="b"/&gt;
&lt;f:selectItem itemLabel="c" itemValue="c"/&gt;

funciona perfeitamente!

alguém sabe onde possso estar errando? ou um esclarecimento mehor do JSF!

15 Respostas

dev.rafael

Não sei se eu te entendi direito, tente return uma lista de objetos do tipo Cliente, da maneira que você está construindo
o seu SelectOne você não precisa converter os dados para SelectItem. Confirma ai se você está usando JSF 2 ou 1.2.

Se não funcionar posta um pouco mais de código, porque esse ai não esclareceu muito.

aeciovc

estou usando JSF 2.

esse é meu Bean Gerenciado:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.kmf.controller;

import br.kmf.bean.Cliente;
import br.kmf.bean.Projeto;
import br.kmf.dao.GenericDAOImpl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;

/**
 *
 * @author Bruno
 */
public class ProjetoManaged implements Serializable {

    private Projeto projeto;

    public List&lt;SelectItem&gt; clientes = new ArrayList&lt;SelectItem&gt;();
    private Cliente cliente = new Cliente();
    private String cliente1;


    /** Creates a new instance of ProjetoManaged */
    public ProjetoManaged() {
        projeto = new Projeto();
        projeto.setCliente(cliente);
    }

    /**
     * @return the projeto
     */
    public Projeto getProjeto() {
        return projeto;
    }

    /**
     * @param projeto the projeto to set
     */
    public void setProjeto(Projeto projeto) {
        this.projeto = projeto;
    }

    public void cadastrar(ActionEvent event) {

        System.out.println("Aquiiii: "+ cliente.getCodCliente());
          System.out.println("Aquiiii: "+ cliente1);
        GenericDAOImpl&lt;Projeto, Integer&gt; dao = new GenericDAOImpl();
        this.projeto = dao.save(projeto);
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Informacao:", "Projeto " + projeto.getDescricao() + ",  cadastrado com Sucesso!"));

    }

    public List&lt;SelectItem&gt; getClientes() {

        List&lt;Cliente&gt; c = new ArrayList&lt;Cliente&gt;();

        GenericDAOImpl&lt;Cliente, Integer&gt; dao = new GenericDAOImpl();
        c = dao.getAll(new Cliente());

        for (Cliente cliente : c) {
            clientes.add(new SelectItem(cliente, cliente.getNome()));

        }

        return clientes;
    }

    public void valueChangeListener(ValueChangeEvent event) {
        System.out.println(&quot;Cliente: &quot; + event.getNewValue());
 
        PhaseId phaseId = event.getPhaseId();
        //pega o novo valor
        Integer newValue = (Integer) event.getNewValue();
        if (phaseId.equals(PhaseId.ANY_PHASE)) {
            //agenda o evento para a fase que nos interessa
            event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
            event.queue();
        } else if (phaseId.equals(PhaseId.UPDATE_MODEL_VALUES)) {
            //aqui vai o método de antes (um pouco mudado)
            
            this.cliente.setCodCliente(newValue);
            cliente1 = String.valueOf(newValue);
        }
    }

    /**
     * @return the cliente
     */
    public Cliente getCliente() {
        return cliente;
    }

    /**
     * @param cliente the cliente to set
     */
    public void setCliente(Cliente cliente) {
        this.cliente = cliente;
    }

    /**
     * @return the cliente1
     */
    public String getCliente1() {
        return cliente1;
    }

    /**
     * @param cliente1 the cliente1 to set
     */
    public void setCliente1(String cliente1) {
        this.cliente1 = cliente1;
    }

}

tem algumas coisas como esse cliente1 que tava colocando pra testar!

e minha pagina:

&lt;?xml version='1.0' encoding='UTF-8' ?&gt;
&lt;!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:p="http://primefaces.prime.com.tr/ui"
                template="/template/template.xhtml"
                xmlns:f="http://java.sun.com/jsf/core"&gt;
    
    &lt;ui:define name="top"&gt;&lt;/ui:define&gt;

    &lt;ui:define name="content"&gt;

        &lt;h:form&gt;
            &lt;p:messages id="messages" showDetail="true"/&gt;

            &lt;p:panel header="Projetos"&gt;

                &lt;h:panelGrid columns="2" &gt;
                    &lt;h:outputText value="Descricao: "/&gt;
                    &lt;h:inputText value="#{projetoManaged.projeto.descricao}"/&gt;

                    &lt;h:outputText value="URL: "/&gt;
                    &lt;h:inputText value="#{projetoManaged.projeto.url}"/&gt;

                    &lt;h:outputText value="Cliente: "/&gt;

                    &lt;h:selectOneMenu value="#{projetoManaged.cliente.codCliente}"  valueChangeListener="#{projetoManaged.valueChangeListener}" immediate="true" &gt;
                        &lt;f:selectItems value="#{projetoManaged.clientes}" var="cliente" itemLabel="#{cliente.nome}" itemValue="#{cliente.codCliente}"/&gt;
                    &lt;/h:selectOneMenu&gt;
                &lt;/h:panelGrid&gt;

                &lt;p:commandButton value="Cadastrar" actionListener="#{projetoManaged.cadastrar}" update="messages"/&gt;
            &lt;/p:panel&gt;

        &lt;/h:form&gt;

    &lt;/ui:define&gt;



&lt;/ui:composition&gt;

a questão é que essa linha <f:selectItems value="#{projetoManaged.clientes}" var="cliente" itemLabel="#{cliente.nome}" itemValue="#{cliente.codCliente}"/> ele não pega o itemValue. e quando vai Validar o Bean não passa, o que não acontece se eu usar estaticamente o selectItem

dev.rafael

Me parece que o seu problema é que o seu método getClientes() está retornando um List mas a sua viu
está tentando acessar os atributos dos items como se esses fossem do tipo Cliente.

Modifique o seu método getClientes() disso:

public List<SelectItem> getClientes() {  
  
        List<Cliente> c = new ArrayList<Cliente>();  
  
        GenericDAOImpl<Cliente, Integer> dao = new GenericDAOImpl();  
        c = dao.getAll(new Cliente());  
  
        for (Cliente cliente : c) {  
            clientes.add(new SelectItem(cliente, cliente.getNome()));  
  
        }  
  
        return clientes;  
    }

… para isso:

public List<Cliente> getClientes() {  
  
        return new GenericDAOImpl().getAll(new Cliente());
  
    }

… e me avise se funcionou.

aeciovc

funcionou sim. mas algumas questões agora me deixaram na dúvida.

primeiro: da forma que está eu não estou trabalhando com Objetos no selectOne certo??

existe como fazer isso, ou seja no lugar do vaor dele ser o codCliente inteiro ser o objeto Cliente??

outra coisa estranha é que achei que tinha que retornar o SelectItens assim como vi em muitos tutorias do JSF 2. isso mudou do JSF 1.2 e 2??

mas tá funcionando direitinho… so isso que fiquei em duvida agora!

dev.rafael

PRIMEIRO:
Sim é possível fazer isso e inclusive é aconselhável que você o faça pois dessa forma o componente vai armazenar os objetos
Cliente ficando mais fácil para escrever um converter que entregue o objeto para o seu ManagedBean e não o código dele. Ai
segue as modificações que você precisa fazer no seu código, apenas o valor do atributo itemValue.

<h:selectOneMenu value="#{projetoManaged.projeto.cliente.codCliente}"  valueChangeListener="# {projetoManaged.valueChangeListener}" immediate="true" >  
    <f:selectItems value="#{projetoManaged.clientes}" var="cliente" itemLabel="#{cliente.codCliente}" itemValue="#{cliente}"/>  
</h:selectOneMenu>

SEGUNDO:
Antes do JSF 2 a tag f:selectItems não possuía os atributos var, itemLabel e itemValue, essas informações eram obtidas através
dos atributos dos objetos SelectItem retornados. O problema, como você pode perceber, é que dessa forma você sempre precisava
converter os objetos das suas listas para SelectItem, o que é massante e trabalhoso. Com esses três atributos é possível que seus
ManagedBeans retornem a lista de dados sem nenhum tipo de processamento prévio, ou seja, assim como ela veio do banco.

aeciovc

blz, dev.rafael, como ficaria pra armazenar os Objetos??

pq quando tento fazer isso ele dá um erro de Null Converter.

dev.rafael

Acho que não entendi, o que você quer dizer com “armazenar os Objetos”? Você quer armazena-los onde?
Com relação ao seu erro, poste o stackTrace da sua exceção.

juniorsatanas

aeciovc Isso é um sistema ? caralho fiquei bolado… muito legal jsf 2

Tu tem mais codigo para postar aqui ? gostaria de dar um Contro C + Control V, para fazer um CRUD.

abraço.

juniorsatanas
public void cadastrar(ActionEvent event) {  
  
        System.out.println("Aquiiii: "+ cliente.getCodCliente());  
          System.out.println("Aquiiii: "+ cliente1);  
        GenericDAOImpl&lt;Projeto, Integer&gt; dao = new GenericDAOImpl();  
        this.projeto = dao.save(projeto);  
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Informacao:", "Projeto " + projeto.getDescricao() + ",  cadastrado com Sucesso!"));  
  
    }

da ate pra ver que ta usando Facade !

dev.rafael

Cara, vou ver se arranjo um tempo para escrever um artigo e posto ae. Beleza?

aeciovc

blz dev.rafael…

minha questão de armazenar os Objetos é no selectOneMenu mesmo… pq da forma que fiz no meu selectItems eu to usando o ItemValue como cliente.codCliente e não como o Objeto = cliente

entende??

juniorsatanas

otimo vou ficar aqui no agurado, e estudando sobre o spring

tonyam

aeciovc:
blz dev.rafael…

minha questão de armazenar os Objetos é no selectOneMenu mesmo… pq da forma que fiz no meu selectItems eu to usando o ItemValue como cliente.codCliente e não como o Objeto = cliente

entende??

Caro aeciovc

veja:

  • primeiro crie os metodos hashCode e equals da sua classe cliente
  • Na seu managed bean a classe que retorna a lista pode ser assim:
public List&lt;Cliente&gt; getClientes() {     
  
    return new GenericDAOImpl().getAll(new Cliente());   
  
}
  • crie uma classe para converter
@FacesConverter(value="converteCliente", forClass=Cliente.class) 
public class ConverteCliente implements Converter {

	@Override
	public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
		return GenericDAOImpl().getCliente(Integer.valueOf(arg2));
	}

	@Override
	public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
		return String.valueOf(((Cliente) arg2).getCodigoCliente());
	}

}
  • e sua pagina
&lt;h:selectOneMenu value="#{projetoManaged.projeto.cliente}"   &gt;     
    &lt;f:selectItems value="#{projetoManaged.clientes}" var="cliente" itemLabel="#{cliente.descricao}" itemValue="#{cliente}"/&gt;     
    &lt;f:converter converterId="converteCliente"/&gt;
&lt;/h:selectOneMenu&gt;

e pronto.

não sei se fui claro

Flw

D

tonyam, tentei fazer desta forma como você postou mas não funcionou. Você teria um exemplo com o Dao para eu poder comparar.

obrigado.

cbs_sp

Pra quem se interessar, tenho um exemplo sem converter aqui:
codepianist.com/2012/06/exemplo-jsf2-selectcombo-sem-coverter/

Um grande abraço e sucesso! 8)

Criado 13 de julho de 2010
Ultima resposta 9 de jun. de 2012
Respostas 15
Participantes 6