Problema ao obter valor a partir de um SelectOneMenu

17 respostas
S

Olá, pessoal.
Quero fazer algo que achei que fosse mais simples, porém não estou tendo sucesso.
Bem, o que preciso é que quano pudesse escolher um item qualquer à partir de um SelectOneMenu, este valor pudesse ser "submetido" e através de seu ID (de preferência, já que tentei criar algo assim no DAO, mas pode ser qualquer outro atributo, como NOME, por exemplo) e devolvesse um objeto igual correspondente, ou seja, selecionaria, passaria seu ID, consultando no banco e quando escolhesse, como um filtro, preenchesse inputs como inputText assim que clicasse:

vejam a minha página:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:a4j="http://richfaces.org/a4j"
	xmlns:rich="http://richfaces.org/rich">
<h:head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"></meta>
	<title>Teste</title>
</h:head>
<h:body>
	<f:view>
		<h:form id="formCadAtendimento">
			<h:messages layout="table" showSummary="true" showDetail="true"
				globalOnly="true">
			</h:messages>
			<h:panelGrid columns="2">
				<h:outputText Value="Nome do cliente"></h:outputText>
				<h:selectOneMenu id="pessoa"
					value="#{atendimentoBean.atendimentoEdicao.cliente}" label="Pessoa"
					required="true">
					<f:selectItems value="#{atendimentoBean.clientes}" />
				</h:selectOneMenu>
				<h:outputText Value="#{clienteBean.clienteEdicao.bairro}"></h:outputText>

				<h:outputText value="Cidade" />
				<h:inputText value="#{ClienteBean.clienteEdicao.cidade}" />

				<h:outputText value="Bairro" />
				<h:inputText value="#{clienteEdicao.bairro}" />

				<h:outputText value="Endereço" />
				<h:inputText value="#{clienteEdicao.endereco}" />

				<h:outputText value="Estado" />
				<h:inputText value="#{clienteBean.clienteEdicao.estado}" />

				<h:outputText value="Cpf" />
				<h:inputText value="#{clienteEdicao.cpf}" />

			</h:panelGrid>
		</h:form>
	</f:view>
</h:body>
</html>

Meu ManagedBean está assim:

package br.com.siscolorimetry.visao;

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.model.SelectItem;

import br.com.siscolorimetry.negocio.AtendimentoService;
import br.com.siscolorimetry.negocio.ClienteService;
import br.com.siscolorimetry.negocio.RegraNegocioException;
import br.com.siscolorimetry.dominio.Atendimento;
import br.com.siscolorimetry.dominio.Cliente;
import br.com.siscolorimetry.dominio.TipoAtendimento;

public class CadastroAtendimentoBean {

	private Atendimento AtendimentoEdicao;
	private List<SelectItem> tiposAtendimentos;
	private List<SelectItem> clientes;

	public String inicializar() {
		this.AtendimentoEdicao = new Atendimento();
		this.tiposAtendimentos = null;
		this.clientes = null;
		return "cadastroAtendimento";
	}

	public void salvar(ActionEvent event) {
		FacesContext context = FacesContext.getCurrentInstance();
		try {
			new AtendimentoService().salvar(this.AtendimentoEdicao);
			this.AtendimentoEdicao = new Atendimento();
			FacesMessage msg = new FacesMessage(
					"Atendimento Cadastrado com sucesso!");
			msg.setSeverity(FacesMessage.SEVERITY_INFO);
			context.addMessage(null, msg);
		} catch (RegraNegocioException e) {
			context.addMessage(
					null,
					new FacesMessage(FacesMessage.SEVERITY_ERROR, e
							.getMessage(), e.getMessage()));
		} catch (Exception e) {
			e.printStackTrace();
			FacesMessage msg = new FacesMessage(
					"Erro inesperado ao cadastrar atendimento! ");
			msg.setSeverity(FacesMessage.SEVERITY_ERROR);
			context.addMessage(null, msg);
		}
	}

	public List<SelectItem> getClientes() {
		if (this.clientes == null) {
			this.clientes = new ArrayList<SelectItem>();
			List<Cliente> clientes = new ClienteService().listarTodos();
			this.clientes.add(new SelectItem(null, "Selecione"));
			for (Cliente cliente : clientes) {
				this.clientes.add(new SelectItem(cliente, cliente.getNome()));
			}
		}
		return this.clientes;
	}

	public List<SelectItem> getTiposAtendimento() {
		if (this.tiposAtendimentos == null) {
			this.tiposAtendimentos = new ArrayList<SelectItem>();
			for (TipoAtendimento tipo : TipoAtendimento.values()) {
				this.tiposAtendimentos
						.add(new SelectItem(tipo, tipo.toString()));
			}
		}
		return tiposAtendimentos;
	}

	public Atendimento getAtendimentoEdicao() {
		return AtendimentoEdicao;
	}

	public void setAtendimentoEdicao(Atendimento atendimentoEdicao) {
		AtendimentoEdicao = atendimentoEdicao;
	}

	public List<SelectItem> getTiposAtendimentos() {
		return tiposAtendimentos;
	}

	public void setTiposAtendimentos(List<SelectItem> tiposAtendimentos) {
		this.tiposAtendimentos = tiposAtendimentos;
	}

	public void setClientes(List<SelectItem> clientes) {
		this.clientes = clientes;
	}

}

Esses são os métos da Service que obtenho os objetos do input, vejam que gostaria de usar o PESQUISA POR ID para obtê-lo na página para preenchê-lo, queria fazê-lo usando JSF “puro”.

public Cliente pesquisaPorId(Long id) {
		DAOFactory daoFactory = DAOFactory.getDAOFactory();
		ClienteDAO clienteDAO = daoFactory.getClienteDAO();
		Cliente cliente = clienteDAO.pesquisarPorId(id);
		return cliente;
	}

	public List<Cliente> listarTodos() {
		DAOFactory daoFactory = DAOFactory.getDAOFactory();
		ClienteDAO clienteDAO = daoFactory.getClienteDAO();
		List<Cliente> clientes = clienteDAO.listarTodosOrdenadosPorNome();
		daoFactory.encerrar();
		return clientes;
	}
}

É através de um DAO Genérico que são executadas as ações de listagem por ID e todas as outras listas são obtidas:

@SuppressWarnings("unchecked")
	public T pesquisarPorId(Serializable id) {
		return (T) this.session.get(this.persistentClass, id);
	}



public List<T> listarTodos() {
		return this.session.createCriteria(this.persistentClass).list();
	}

Não sei se é relevante, mas este é meu converter

package br.com.siscorimetry.conversores;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;

import br.com.siscolorimetry.dominio.Cliente;
import br.com.siscolorimetry.negocio.ClienteService;

public class ClienteConverter implements Converter {
	public Object getAsObject(FacesContext context, UIComponent component,
			String value) throws ConverterException {
		if (value == null) {
			return null;
		}
		return new ClienteService().pesquisaPorId(Long.parseLong(value));
	}

	public String getAsString(FacesContext context, UIComponent component,
			Object object) throws ConverterException {
		if (object == null) {
			return null;
		}
		Cliente cliente = (Cliente) object;
		return cliente.getId().toString();
	}
}

Espero ter passado informações suficientes, qualquer dúvida o meu e-mail também é [email removido], aguardo e já agradeço.

17 Respostas

S

Ninguém?

ErickRAR

Informação até demais, o que desanima para ler.
Qual erro está dando? Reescreveu os métodos equals e hashCode da sua classe Cliente?

S

Olá, tudo bem?
Postaria aqui o que tem, mas o erro é que o objeto CLIENTE está nulo, porém já está sobrescrito, embora só o ID, acha que tem de colocar mais?
Digo sobrescrever todos os atributos?

S
/incluirAtendimento.xhtml @26,22 value="#{atendimentoBean.atendimentoEdicao.cliente}": Target Unreachable, 'atendimentoEdicao' returned null
ErickRAR

No primeiro selectItem você está passando null como valor, tente passar um novo objeto cliente, em branco mesmo.

B

smnj, evite dar dois posts seguidos. Nem sempre tem gente online pra responder na hora, então tenha paciência.

Pelo que eu vi, o que voce quer fazer é, ao selecionar um f:selectItem no h:selectOneMenu, ele ja enviar o itemValue para o #{atendimentoBean.atendimentoEdicao.cliente}, certo ?
Se for isso, voce pode colocar no selectOneMenu a propriedade onchange="".

No caso de selectItems, eu não recomendo, por uso pessoal, o uso de List, e sim o uso de uma List, e fazer o selectItems assim:

<f:selectItems value="#{bean.listClasseQualquer}" var="classe" itemLabel="#{classe.descricao}" itemValue="#{classe.id}" />
S

Obrigado, Felipe, vou tentar implementar isso agora, e já mando a resposta.
Erick, me diga como posso fazer isso na prática?

ErickRAR
this.clientes.add(new SelectItem("", "Selecione"));  
 this.clientes.add(new SelectItem(new Cliente(), "Selecione"));  
 this.clientes.add(new SelectItem(0, "Selecione"));  
...

Não sei qual é a melhor prática. :lol:

S

Nenhuma das maneiras funcionou.

nenhumas das formas sugeridas por Erik,
quanto à Felipe, tentei assim:

&lt;f:selectItems value="#{atendimentoBean.clientes}" var="cliente" itemLabel="#{cliente.clientes}" itemValue="#{cliente.id}"&gt; &lt;/f:selectItems&gt;

Sem sucesso

G

tava com o mesmo problema
pesquise,pesquisei pro fim era o converter

meu topico com a resolução e o converter q usei

obs: sobrescrever os metos equals e hascode , e nao esquecer de dar new nos objetos

S

Muito obrigado, Geeh então crê que é o converter?
Vou modificar conforme sua sugestão, vou postar a resposta.

S

Talvez eu não estivesse sabendo como fazer, podem ajudar?

M

qual o erro que está aparecendo? erro de validação? nullpointer?

S

Olá, Marcos, tudo bem?
Na realidade, não é um erro exatamente, o problema é que não estou conseguindo fazê-lo.
Não exatamente um erro.

S
Marcos, nada acontece, tentei fazer deste modo: O que gostaria é fazer uma espécie de filtro dinâmico, ao mandar estas opções, abaixo, outros inputs pudessem ser alterados, assim que clicasse sobre qualquer valor deste select:
&lt;h:selectOneMenu id="cliente"
					value="#{atendimentoBean.atendimentoEdicao.id}" label="Pessoa"
					required="true"
					valueChangeListener="#{clienteBean.getClientePorNome}"&gt;
					&lt;f:selectItems value="#{atendimentoBean.clientes}" /&gt;
					&lt;f:ajax event="change" render="cliente"&gt;&lt;/f:ajax&gt;
				&lt;/h:selectOneMenu&gt;

Quando um valor acima pudesse ser selecionado, abaixo fosse preenchido por seus atributos:

&lt;h:outputLabel value="Nome" /&gt;
				&lt;h:inputText value="#{clienteBean.clienteEdicao.nome}"&gt;&lt;/h:inputText&gt;

				&lt;h:outputLabel value="Telefone"&gt;&lt;/h:outputLabel&gt;
				&lt;h:inputText value="#{clienteBean.clienteEdicao.telRes}"&gt;&lt;/h:inputText&gt;

				&lt;h:outputLabel value="Endereco"&gt;&lt;/h:outputLabel&gt;
				&lt;h:inputText value="#{clienteBean.clienteEdicao.endereco}"&gt;&lt;/h:inputText&gt;


				&lt;h:outputLabel value="Cidade"&gt;&lt;/h:outputLabel&gt;
				&lt;h:inputText value="#{clienteBean.clienteEdicao.cidade}"&gt;&lt;/h:inputText&gt;

				&lt;h:outputLabel value="Estado"&gt;&lt;/h:outputLabel&gt;
				&lt;h:inputText value="#{clienteBean.clienteEdicao.estado}"&gt;&lt;/h:inputText&gt;

				&lt;h:outputLabel value="Cep"&gt;&lt;/h:outputLabel&gt;
				&lt;h:inputText value="#{clienteBean.clienteEdicao.cep}"&gt;&lt;/h:inputText&gt;

				&lt;h:outputLabel value="Cpf"&gt;&lt;/h:outputLabel&gt;
				&lt;h:inputText value="#{clienteBean.clienteEdicao.cpf}"&gt;&lt;/h:inputText&gt;

Não acredito que esteja passando esse ID adequadamente;
A idéia que pudesse passar um ID ou até mesmo um objeto do tipo Cliente para um método que retornasse um cliente

public Cliente getClientePorNome(ValueChangeEvent evento, long id) {

		return new ClienteService().pesquisaPorId(id);

	}
M

O converter que você criou não está especificado no xhtml e nesse caso ele não é chamado. Ou anote o converter com forclass para ser ativado automaticamente, sem necessidade de inserir no xhtml.

Algo como:

@FacesConverter(forClass=Cliente.class)
public class ClienteConverter implements Converter{

....

}

O seu converter parece correto, mas no bean vc pode fazer referência direta ao objeto, quando usa converter. Não precisa usar o id para pegar novamente o objeto no banco de dados.

S

Você tem razão por um lado, Marcos, mas como uso algumas coisas do padrão JSF 1.1, então mapiei no FacesConfig, deste modo:

&lt;converter&gt; &lt;converter-for-class&gt;java.lang.Enum&lt;/converter-for-class&gt; &lt;converter-class&gt;br.com.siscorimetry.conversores.EnumConverter&lt;/converter-class&gt; &lt;/converter&gt; &lt;converter&gt; &lt;converter-for-class&gt;br.com.siscolorimetry.dominio.Cliente&lt;/converter-for-class&gt; &lt;converter-class&gt;br.com.siscorimetry.conversores.ClienteConverter&lt;/converter-class&gt; &lt;/converter&gt;

Criado 19 de outubro de 2012
Ultima resposta 22 de out. de 2012
Respostas 17
Participantes 5