[RESOLVIDO]Pegar objeto no selectOneMenu primefaces

12 respostas
Benjamin10

Boa noite pessoal, tenho um selectOneMenu que contem os estados cadastrados em um dialog que é para gravar uma nova cidade e indicar seu estado.
Mas quando mando gravar ele não pega o valor do estado no selectOneMenu. Abaixo os códigos que fiz.

Select One Menu

<p:dialog header="Informe o nome do estado" widgetVar="dlgInserir" width="500" height="300" showEffect="clip">
                     Nome: <p:inputText value="#{cidadeBean.cidade.nome}" required="true" requiredMessage="O campo nome esta vazio"/>  
                     Estado: <p:selectOneMenu id="selecionaEstado" value="#{cidadeBean.estadoSelecionado}" converter="CidadeConverter">
                         <f:selectItem itemLabel="Selecione o estado" />
                         <f:selectItems value="#{cidadeBean.estados}" var="estado" itemLabel="#{estado.nome}" itemValue="#{estado.idEstado}"/>
                         
                     </p:selectOneMenu>  
                    <p:commandButton value="Confirmar" icon="ui-icon-check" action="#{cidadeBean.gravar()}" ajax="false"/>
                    <p:commandButton value="Limpar" type="reset" ajax="false"/>
                    
                </p:dialog>

Método gravar no Bean

public void gravar() throws DaoException{
		this.estadoSelecionado = new Estado();
		this.cidade.setEstado(estadoSelecionado);
		dao.salvarOuAlterar(cidade);
        addMessageSucesso("Gravado Com Sucesso");
        cidade = null;
    }

E as Classes Estado e Cidade

@Entity
public class Estado implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Integer idEstado;
	@Column(length=50, nullable=false, name="nome_estado")
	private String nome;
	@OneToMany(fetch=FetchType.LAZY, mappedBy="estado")
	private Set<Cidade> cidades = new HashSet<Cidade>();
	
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	public Integer getIdEstado() {
		return idEstado;
	}
	public void setId(Integer id) {
		this.idEstado = id;
	}
	public Set<Cidade> getCidades() {
		return Collections.unmodifiableSet(this.cidades);
	}
	public void addCidade(Cidade cidade){
		if(cidade == null){
			throw new IllegalArgumentException("Cidade não pode ser null");
		}
		this.cidades.add(cidade);
		cidade.setEstado(this);
	}
	
	public boolean removeCidade(Cidade cidade){
		if(cidade == null){
			throw new IllegalArgumentException("Cidade não pode ser null");
		}
		if(this.cidades.remove(cidade)){
			cidade.setEstado(null);
			return true;
		}
		return false;
	}
	
}


@Entity
public class Cidade implements Serializable{

	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Integer idCidade;
	@Column(length=50, name="nome_cidade")
	private String nome;
	@ManyToOne(fetch=FetchType.LAZY, optional=false)
	@JoinColumn(name="estado",referencedColumnName="idestado")
	private Estado estado = new Estado();
	
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	public Integer getIdCidade() {
		return idCidade;
	}
	public Estado getEstado() {
		return estado;
	}
	public void setEstado(Estado estado) {
		this.estado = estado;
	}
	
	
}

e a classe converter

@FacesConverter(value="CidadeConverter", forClass=Cidade.class)  
public class CidadeConverter implements Converter {

	@Override  
    public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException {  
        if(value == null) {  
            try {
                return new CidadeDao().findById(Integer.parseInt(value));    
            } catch (DaoException ex) {
                Logger.getLogger(CidadeConverter.class.getName()).log(Level.SEVERE, null, ex);
            }
        }  
        return null;  
    }  
  
    @Override  
    public String getAsString(FacesContext context, UIComponent component, Object object) throws ConverterException {  
        if(object != null && object instanceof Cidade) {  
            return ((Cidade)object).getIdCidade().toString();  
        }  
        return null;  
    }  

}

12 Respostas

rogeriopaguilar

Na linha 6 do conversor a comparação não deveria ser if(value != null) ?

Benjamin10

Obrigado Rogério pela dica, mas agora ela esta dando outro erro.

Como se eu estivesse passando o nome do estado e não seu Id.

java.lang.NumberFormatException: For input string: "Parana"
	java.lang.NumberFormatException.forInputString(Unknown Source)
	java.lang.Integer.parseInt(Unknown Source)
	java.lang.Integer.parseInt(Unknown Source)
	br.unipar.rectfer.converter.CidadeConverter.getAsObject(CidadeConverter.java:24)
	com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getConvertedValue(HtmlBasicInputRenderer.java:171)
	com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectOneValue(MenuRenderer.java:202)
	com.sun.faces.renderkit.html_basic.MenuRenderer.getConvertedValue(MenuRenderer.java:319)
	org.primefaces.component.selectonemenu.SelectOneMenuRenderer.getConvertedValue(SelectOneMenuRenderer.java:55)
	javax.faces.component.UIInput.getConvertedValue(UIInput.java:1030)
	javax.faces.component.UIInput.validate(UIInput.java:960)
	javax.faces.component.UIInput.executeValidate(UIInput.java:1233)
	javax.faces.component.UIInput.processValidators(UIInput.java:698)
	javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214)
	org.primefaces.component.dialog.Dialog.processValidators(Dialog.java:359)
	javax.faces.component.UIForm.processValidators(UIForm.java:253)
	javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214)
	javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1172)
	com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
	com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	javax.faces.webapp.FacesServlet.service(FacesServlet.java:409)
A

Clássico problema de converter, olhe este post de um tempo atrás que você será feliz kkkkkkkkkk

Benjamin10

Pessoal troquei o converter para um genérico, porém agora ele dá erro de estado null, como a coluna estado da tabela cidade é uma fk, ele não deixa gravar como null.

Segue o erro.

org.postgresql.util.PSQLException: ERRO: valor nulo na coluna "estado" viola a restrição não-nula
	org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2101)
	org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1834)
	org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
	org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:510)
	org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:386)
	org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:332)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	java.lang.reflect.Method.invoke(Unknown Source)
	org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
	org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
	$Proxy20.executeUpdate(Unknown Source)
	org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
	org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2962)
	org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3403)
	org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
	org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
	org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
	org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:275)
	org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
	org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
	org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1214)
	org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:403)
	org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
	org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
	org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75)
	br.unipar.rectfer.dao.DaoGenerico.salvarOuAlterar(DaoGenerico.java:55)
	br.unipar.rectfer.controller.CidadeBean.gravar(CidadeBean.java:50)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	java.lang.reflect.Method.invoke(Unknown Source)
	org.apache.el.parser.AstValue.invoke(AstValue.java:264)
	org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
	com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
	javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
	com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
	javax.faces.component.UICommand.broadcast(UICommand.java:315)
	javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
	javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
	com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
	com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	javax.faces.webapp.FacesServlet.service(FacesServlet.java:409)

e o meu converter genérico que implementei seguindo o post
http://www.guj.com.br/java/220692-para-voce-entity…qualquer-entidade-e-tipo-de-id

public class EntityConverter implements Converter {  
  
    public Object getAsObject(FacesContext ctx, UIComponent component,  
            String value) {  
        if (value != null) {  
            return component.getAttributes().get(value);  
        }  
        return null;  
    }  
  
    public String getAsString(FacesContext ctx, UIComponent component,  
            Object obj) {  
        if (obj != null && !"".equals(obj)) {  
            String id;  
            try {  
                id = this.getId(getClazz(ctx, component), obj);  
                if (id == null) {  
                    id = "";  
                }  
                id = id.trim();  
                component.getAttributes().put(id,  
                        getClazz(ctx, component).cast(obj));  
                return id;  
            } catch (SecurityException e) {  
                e.printStackTrace(); // seu log aqui  
            } catch (IllegalArgumentException e) {  
                e.printStackTrace(); // seu log aqui  
            } catch (NoSuchFieldException e) {  
                e.printStackTrace(); // seu log aqui  
            } catch (IllegalAccessException e) {  
                e.printStackTrace(); // seu log aqui  
            }  
        }  
        return null;  
    }  
  
    /** 
     * Obtém, via expression language, a classe do objeto. 
     * 
     * @param FacesContext facesContext 
     *  
     * @param UICompoment compoment 
     *      
     * @return  Class<?> 
     */  
    private Class<?> getClazz(FacesContext facesContext, UIComponent component) {  
        return component.getValueExpression("value").getType(  
                facesContext.getELContext());  
    }  
  
  
    /** 
     * Retorna a representação em String do retorno do método anotado com @Id ou @EmbeddedId do objeto. 
     * 
     * @param Class<?> clazz 
     *             
     * @return  String 
     */  
    public String getId(Class<?> clazz, Object obj) throws SecurityException,  
            NoSuchFieldException, IllegalArgumentException,  
            IllegalAccessException {  
  
        List<Class<?>> hierarquiaDeClasses = this.getHierarquiaDeClasses(clazz);  
          
        for (Class<?> classeDaHierarquia : hierarquiaDeClasses) {  
            for (Field field : classeDaHierarquia.getDeclaredFields()) {  
                if ((field.getAnnotation(Id.class)) != null  
                        || field.getAnnotation(EmbeddedId.class) != null) {  
                    Field privateField = classeDaHierarquia  
                            .getDeclaredField(field.getName());  
                    privateField.setAccessible(true);  
                    if (privateField.get(clazz.cast(obj)) != null) {  
  
                        return (String) field.getType()  
                                .cast(privateField.get(clazz.cast(obj)))  
                                .toString();  
                    }  
                }  
            }  
        }  
        return null;  
    }  
  
    /** 
     * Retorna uma lista com a hierarquia de classes, sem considerar a classe Object.class 
     * 
     * @param Class<?> clazz 
     *             
     * @return  List<Class<?>> clazz 
     */  
    public List<Class<?>> getHierarquiaDeClasses(Class<?> clazz) {  
  
        List<Class<?>> hierarquiaDeClasses = new ArrayList<Class<?>>();  
        Class<?> classeNaHierarquia = clazz;  
        while(classeNaHierarquia != Object.class) {  
            hierarquiaDeClasses.add(classeNaHierarquia);  
            classeNaHierarquia = classeNaHierarquia.getSuperclass();  
              
        }  
        return hierarquiaDeClasses;  
    }   
}

Alguém mais poderia me ajudar,!!!

A

Como eu te passei no link Benjamin10, para selects, você não precisa de um converter, você precisa somente passar a lista de collection carregada:

este é o código no post que eu te passei como link, é específico para carregar um select:

public Collection&lt;SelectItem&gt; getCarregarSelect() {         
        Collection&lt;SelectItem&gt; lst = new ArrayList&lt;SelectItem&gt;();      
        lst.add(new SelectItem(null, "Selecione o estado"));      //Primeiro item do select 
        List&lt;Estado&gt; lista = **carregar lista com os estados**; //query que busca os valores do bd
        for (int i = 0; i &lt; lista.size(); i++) {        
            lst.add(new SelectItem(lista.get(i).getEstadoId(), lista.get(i).getNomeEstado()));
            //new SelectItem(valor, rótulo);
            //no exemplo acima, o estadoId() é o valor, e o nomeEstado() é o rótulo, é tudo carregado aqui
        }        
        return lst;        
    }

Para carregar o teu select:

Estado: &lt;p:selectOneMenu id="selecionaEstado" value="#{cidadeBean.estadoSelecionado}"&gt;  
    &lt;f:selectItems value="#{seuBean.carregarSelect }" /&gt; 
&lt;/p:selectOneMenu&gt;

não precisa do converter, o valor você converte/valida ao recuperá-lo

Benjamin10

Obrigado pela dica, listou os dados certinho aqui, ele continua dando pedindo pra converter o dado?/
O que eu quero é pegar o objeto selecionado no SelectOneMenu com se nome e id, e no bean setar esse objeto pego no setEstado da classe Cidade. Pois tenho um relacionamento entre as classes como coloquei acima.

Então quando eu coloco no bean

cidade.setEstado(estadoSelecionado);

O estado esta vindo null !!

tem alguma forma de resolver isso?/

A

Faça um teste, crie uma nova variável no teu mb, uma String mesmo, atrele o valor no seu select, e no momento que você executar a operação, debugue o sistema e veja se o valor está vindo ou se preferir, apenas de um print no valor dessa string, veja se o valor segue null.

Benjamin10

Fiz a variavél String que você falou, dai ele retorna o id do estado.

A

Beleza, estamos indo no caminho certo, aqui você já pode solucionar o teu problema.
O que aconteceria se você encontrasse o objeto agora?

Estado estado = new Estado(Integer.parseInt(StringQueEstaOID));
idade.setEstado(estado);

Julgando que dentro da entidade Estado você passe ID e ele te retorne o objeto, se você fizer isso não vai funcionar? Ou ainda melhor:

idade.setEstado(new Estado(Integer.parseInt(StringQueEstaOID)));

assim você vai ter o objeto encontrado já ali, não será necessário realizar uma conversão.

Benjamin10

Fiz do jeito que me falou, deu o seguinte erro.

org.hibernate.exception.ConstraintViolationException: ERRO: valor nulo na coluna "nome_estado" viola a restrição não-nula
	org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:128)
	org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
	org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
	org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
	org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
	org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
	$Proxy20.executeUpdate(Unknown Source)
	org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
	org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3119)
	org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3021)
	org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3350)
	org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:140)
	org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
	org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
	org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:276)
	org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
	org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
	org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1214)
	org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:403)
	org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
	org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
	org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75)
	br.unipar.rectfer.dao.DaoGenerico.salvarOuAlterar(DaoGenerico.java:55)
	br.unipar.rectfer.controller.CidadeBean.gravar(CidadeBean.java:53)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	java.lang.reflect.Method.invoke(Unknown Source)
	org.apache.el.parser.AstValue.invoke(AstValue.java:264)
	org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
	com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
	javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
	com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
	javax.faces.component.UICommand.broadcast(UICommand.java:315)
	javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
	javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
	com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
	com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)

é que meu nome_estado é notnull, e ele ta pedindo pra colocar o nome também.
É assim mesmo ou tem algo de errado com meus relacionamentos entre as entidades?/

Benjamin10

Caro andre.froes solucionei o problema, tirei o cascade da classe Cidade e funcionou belezinha rsrs
Obrigado pela grande ajuda,
abraços

A

Cara, um ID é atrelado a um nome somente correto? Não existem estados com o mesmo nome, somente cidades, então não tem porque ter o atributo nome_estado obrigatório pq já é tudo predefinido, esses valores não irão mutar em momento algum. Mas bem, todos os valores que você está trabalhando no sistema agora são conhecidos, você só tem que saber como jogar com eles, para localizar um estado, dependendo de como está a sua estrutura de tabela, basta somente que você tenha em mãos o ID dele correto? Pelo ID você fará o hook no objeto inteiro, o que nada mais seria um select “SELECT * FROM estado WHERE ID=#”, com isso você tem o seu objeto, agora, se você está com erro ao buscar este objeto, os quinhentos são outros, tu tem que revisar seu DB e tuas entidades.

Criado 1 de setembro de 2012
Ultima resposta 2 de set. de 2012
Respostas 12
Participantes 3