JSF - Validation Error: Value is not valid

Olá pessoal, eu sei que já existe vários tópicos sobre esse assunto, já visitei todos e não consegui resolver o erro.

o problema ocorre no SelectOneMenu, onde tenho um combo de estados que carrega o combo de cidades, ao selecionar um estado é disparado um método para carregar as cidades referente esse estado. esse combo já funciona [color=red]sem CONVERSOR[/color] com (ESTADO, CIDADE e o BEAN REGIAO)… porém quando eu passo para o[color=blue] Bean de Cadastro de cliente[/color] onde eu tenho um atributo do tipo estado na classe [color=green]CLIENTE[/color], o SelectOneMenu não converte. Já criei um conversor, fiz os métodos equals e hashCode, e nada resolve.

se alguém puder analisar o código, eu agradeço.

[code]CLASSE: ESTADO

@Entity
@Table(name = “estados”)
public class Estado implements Serializable {

private static final long serialVersionUID = -5582648910303813488L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ESTADO_ID")
private Integer id;

@Column(name = "sigla")
private String sigla;

@Column(name = "nome")
private String nome;

@OneToMany(mappedBy = "estado", fetch = FetchType.LAZY)
@Cascade(org.hibernate.annotations.CascadeType.ALL)
private List<Cidade> cidades = new ArrayList<Cidade>();

public Integer getId() {
	return id;
}

public void setId(Integer id) {
	this.id = id;
}

public String getNome() {
	return nome;
}

public void setNome(String nome) {
	this.nome = nome;
}

public String getSigla() {
	return sigla;
}

public void setSigla(String sigla) {
	this.sigla = sigla;
}

public List<Cidade> getCidades() {
	return cidades;
}

public void setCidades(List<Cidade> cidades) {
	this.cidades = cidades;
}

public String toString() {
	return this.nome;
}

@Override
public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result + ((id == null) ? 0 : id.hashCode());
	return result;
}

@Override
public boolean equals(Object obj) {
	if (this == obj)
		return true;
	if (obj == null)
		return false;
	if (getClass() != obj.getClass())
		return false;
	Estado other = (Estado) obj;
	if (id == null) {
		if (other.id != null)
			return false;
	} else if (!id.equals(other.id))
		return false;
	return true;
}

}[/code]

CLASSE CLIENTE:

[code]package com.algaworks.dwjsf.financeiro.dominio;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;

import javax.persistence.Table;

@Entity
@Table(name=“cliente”)
public class Cliente implements Serializable{

/**
 * 
 */
private static final long serialVersionUID = 1L;
@Id @GeneratedValue
private Integer idCliente;
@Column(name="nome")
private String nome;
@Enumerated(EnumType.STRING)
@Column(name="tipoPessoa")
private TipoPessoa tipoPessoa;
@Column
private String cpf;
@Column
private String rg;
@Column
private String endereco;
@Column
private String bairro;
@Column
private String cep;

@JoinColumn(name="ID_CIDADE")
private Cidade cidade;

@OneToMany
@JoinColumn(name="ID_ESTADO")
private Estado estado;

@Column
private String telefone;
@Column
private String celular;
@Column
private String email;
@Column
private String nomeEmpresa;
@Column
private String cnpj;

public Integer getIdCliente() {
	return idCliente;
}
public void setIdCliente(Integer idCliente) {
	this.idCliente = idCliente;
}
public String getNome() {
	return nome;
}
public void setNome(String nome) {
	this.nome = nome;
}

@Enumerated(EnumType.STRING)
@Column(name="tipoPessoa")	
public TipoPessoa getTipoPessoa() {
	return tipoPessoa;
}
public void setTipoPessoa(TipoPessoa tipoPessoa) {
	this.tipoPessoa = tipoPessoa;
}
public String getCpf() {
	return cpf;
}
public void setCpf(String cpf) {
	this.cpf = cpf;
}
public String getRg() {
	return rg;
}
public void setRg(String rg) {
	this.rg = rg;
}
public String getEndereco() {
	return endereco;
}
public void setEndereco(String endereco) {
	this.endereco = endereco;
}
public String getBairro() {
	return bairro;
}
public void setBairro(String bairro) {
	this.bairro = bairro;
}
public String getCep() {
	return cep;
}
public void setCep(String cep) {
	this.cep = cep;
}

public Cidade getCidade() {
	return cidade;
}
public void setCidade(Cidade cidade) {
	this.cidade = cidade;
}

public Estado getEstado() {
	return estado;
}
public void setEstado(Estado estado) {
	this.estado = estado;
}
public String getTelefone() {
	return telefone;
}
public void setTelefone(String telefone) {
	this.telefone = telefone;
}
public String getCelular() {
	return celular;
}
public void setCelular(String celular) {
	this.celular = celular;
}
public String getEmail() {
	return email;
}
public void setEmail(String email) {
	this.email = email;
}
public String getNomeEmpresa() {
	return nomeEmpresa;
}
public void setNomeEmpresa(String nomeEmpresa) {
	this.nomeEmpresa = nomeEmpresa;
}
public String getCnpj() {
	return cnpj;
}
public void setCnpj(String cnpj) {
	this.cnpj = cnpj;
}

@Override
public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result
			+ ((idCliente == null) ? 0 : idCliente.hashCode());
	return result;
}
@Override
public boolean equals(Object obj) {
	if (this == obj)
		return true;
	if (obj == null)
		return false;
	if (getClass() != obj.getClass())
		return false;
	Cliente other = (Cliente) obj;
	if (idCliente == null) {
		if (other.idCliente != null)
			return false;
	} else if (!idCliente.equals(other.idCliente))
		return false;
	return true;
}

}
[/code]

BEAN CADASTRO CLIENTE

[code]package com.algaworks.dwjsf.financeiro.visao;

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.ValueChangeEvent;
import javax.faces.model.SelectItem;
import org.hibernate.Session;
import com.algaworks.dwjsf.financeiro.dao.CidadeDAO;
import com.algaworks.dwjsf.financeiro.dao.EstadoDAO;
import com.algaworks.dwjsf.financeiro.dominio.Cidade;
import com.algaworks.dwjsf.financeiro.dominio.Cliente;
import com.algaworks.dwjsf.financeiro.dominio.Estado;
import com.algaworks.dwjsf.financeiro.dominio.TipoPessoa;
import com.algaworks.dwjsf.financeiro.negocio.CidadeService;
import com.algaworks.dwjsf.financeiro.negocio.ClienteService;
import com.algaworks.dwjsf.financeiro.negocio.EstadoService;
import com.algaworks.dwjsf.financeiro.negocio.RegraNegocioException;
import com.algaworks.dwjsf.financeiro.util.HibernateUtil;

public class CadastroClienteBean implements Serializable {
private static final long serialVersionUID = -4281390476508498320L;
private String tipo;
private Cliente clienteEdicao = new Cliente();
private List tipoPessoa;
private List cidades = new ArrayList();
private List estados;

public String inicializar() {
	this.clienteEdicao = new Cliente();
	this.tipoPessoa = null;

	return "cadastroCliente";

}


public void validaTipo(ValueChangeEvent event) {
	if (event.getNewValue().equals(getTipoPessoa().equals("FISICA"))) {
		tipo = "PF";
	} else if (event.getNewValue().equals("JURICA")) {
		tipo = "PJ";
	} else {
		tipo = "";
	}

}

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

	

public void salvar(ActionEvent event) {
	FacesContext context = FacesContext.getCurrentInstance();
	try {
		new ClienteService().salvar(this.clienteEdicao);
		this.clienteEdicao = new Cliente();
		FacesMessage msg = new FacesMessage(
				"Cliente 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 salvar cliente!");
		msg.setSeverity(FacesMessage.SEVERITY_ERROR);
		context.addMessage(null, msg);
	}
}

public List<SelectItem> getEstados() {

	this.estados = new ArrayList<SelectItem>();
	List<Estado> estados = new EstadoService().listarTodas();

	//List<SelectItem> itens = new ArrayList<SelectItem>(lista.size());
	this.estados.add(new SelectItem(null, "Selecione"));
	for (Estado s : estados) {
		this.estados.add(new SelectItem(s.getId(), s.getNome()));
	}

	return this.estados;
}

public void actionCarregaCidades() {
	System.out.println("id do estado selecionado >>> "
			+ clienteEdicao.getEstado().getId());

	this.cidades = this.getCidadesByEstado();
}

public List<SelectItem> getCidadesByEstado() {
	Session session = HibernateUtil.getSession();

List<Cidade> lista = new CidadeService().listarCidades(clienteEdicao.getEstado().getId());

	
	List<SelectItem> items = new ArrayList<SelectItem>(cidades.size());

	for (Cidade c : lista) {
		items.add(new SelectItem(c.getId(), c.getNome()));
	}
	session.close();
	return items;
}


public String getTipo() {
	return tipo;
}


public void setTipo(String tipo) {
	this.tipo = tipo;
}


public Cliente getClienteEdicao() {
	return clienteEdicao;
}


public void setClienteEdicao(Cliente clienteEdicao) {
	this.clienteEdicao = clienteEdicao;
}


public List<SelectItem> getCidades() {
	return cidades;
}


public void setCidades(List<SelectItem> cidades) {
	this.cidades = cidades;
}


public void setTipoPessoa(List<SelectItem> tipoPessoa) {
	this.tipoPessoa = tipoPessoa;
}

}
[/code]

CONVERSOR DE ESTADO:

[code]package com.algaworks.dwjsf.financeiro.conversores;

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

import com.algaworks.dwjsf.financeiro.dominio.Estado;
import com.algaworks.dwjsf.financeiro.negocio.EstadoService;

public class EstadoConverter implements Converter {

public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException{
	if(value == null){
		return null;
	}
	return new EstadoService().pesquisarPorId(Integer.parseInt(value));
	
}

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

}
[/code]

FACES CONFIG

[code]
com.algaworks.dwjsf.financeiro.dominio.Estado
com.algaworks.dwjsf.financeiro.conversores.EstadoConverter

</converter>

[/code]

Olá,

Qual o escopo do seu managed bean? Normalmente ele pode estar em escopo de request e as listas de entidades dos componentes precisam estar em um escopo maior que request, como view ou mesmo session.

Dica, passe seu managed bean para escopo de session e veja se funciona. Se funcionar então seu problema está relacionado ao escopo de conversação.

Um abraço.

faltou a pagina…

Pagina Cadastro:

<h:selectOneMenu value="#{cadastroClienteBean.clienteEdicao.estado}">
	<f:selectItem itemValue="" itemLabel="Selecione..." />
		<f:selectItems value="#{cadastroClienteBean.estados }" />
	<a4j:support event="onchange" ajaxSingle="true"
           action="#{cadastroClienteBean.actionCarregaCidades}"   reRender="estado,cidade" />
</h:selectOneMenu>

o escopo do bean é session.

o erro acontece no retorno ao componente acredito que na fase de validação do JSF

21/07/2012 21:33:17 com.sun.faces.lifecycle.RenderResponsePhase execute
INFO: WARNING: FacesMessage(s) have been enqueued, but may not have been displayed.
sourceId=frm:j_id_jsp_1448383668_46[severity=(ERROR 2), summary=(frm:j_id_jsp_1448383668_46: Validation Error: Value is not valid), detail=(frm:j_id_jsp_1448383668_46: Validation Error: Value is not valid)]

Bem, seu converter parece estar correto, os métodos equals&hashCode também parecem estar ok e mesmo com escopo session o problema ocorre.

Acredito que o problema está em como você está construindo a sua lista de SelectItem’s. Você está fazendo assim:

Mas o correto deveria ser: