[RESOLVIDO] Erro de validação: o valor não é válido (RadioButton)

Opa turma, tudo bom?
É o seguinte tem 2 dias que estou com esse erro e não consigo solucionar, já vasculhei por inúmeros tópicos aqui do fórum, mas nenhum conseguiu me ajudar de fato.

Estou desenvolvendo um sistema de perguntas e respostas simples, porém quando selecione um item do radio button da o erro:

formDesafio:respostas: Erro de validação: o valor não é válido

Minha página JSF:

<!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:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:p="http://primefaces.org/ui">

<h:head>
	<title>Desafio</title>
</h:head>
<h:body>
	<h:form id="formDesafio">
		<p:messages autoUpdate="true" />
		<h:outputText value="#{desafioMB.pergunta.texto}" />
		<br />
		<p:selectOneRadio id="respostas" value="#{desafioMB.respostaSelecionada}" required="true" requiredMessage="#{msg.respostaPerguntaRequired}">
			<f:selectItems value="#{desafioMB.pergunta.respostas}" var="r" itemValue="#{r}" itemLabel="#{r.resposta}" />
		</p:selectOneRadio>
		
		<p:commandButton value="#{msg.responder}" action="#{desafioMB.responder}" />
		<p:commandButton value="#{msg.desistir}" onclick="desistirDlg.show()" />
		<br />
	</h:form>
	
	<p:confirmDialog widgetVar="desistirDlg" id="desistirDialog"
		header="#{msg.desafio_desistir_titulo}"
		message="#{msg.desafio_desistir_pergunta}">

		<h:form>
			<p:commandButton value="#{msg.sim}"
				oncomplete="desistirDlg.hide()" action="#{desafioMB.desistir}" />
			<p:commandButton value="#{msg.nao}"
				onclick="desistirDlg.hide()" type="button" />
		</h:form>
	</p:confirmDialog>
</h:body>
</html>

Meu BackBean:


@ManagedBean
@ViewScoped
public class DesafioMB extends AbstractMB{
	
	@EJB private PerguntaFacade perguntaFacade;
	@EJB private RespostaFacade respostaFacade;
	
	private Pergunta pergunta = new Pergunta();
	private Resposta respostaSelecionada = new Resposta();
	private List<Pergunta> perguntas;
	
	public void responder(){
		//se a resposta selecionada for igual a 1 ela é a correta
		if(respostaSelecionada.getCorreta() == 1)
		{
			//faz ações se o usuário acertar
		}
		else
		{
//faz ações se o usuário errar
		}
	}
//getters e setters

Já tentei criar um custom converter, mas não deu certo
Já passar apenas o id para o backbean e depois recupear o objeto através do id, mas da o mesmo erro

Não falta um converter não para poder converter o seu objeto de Resposta para o combobox ?

[quote=lele_vader]Não falta um converter não para poder converter o seu objeto de Resposta para o combobox ?
[/quote]
Não entendi, eu tentei criar um converter… Vi vários exemplos, fiz mas não deu certo!

Poderia me ajudar?

Aqui tem um exemplo

Só lembrar que tem que implementar equals e hashcode no classe que você quer converter, no caso Resposta.

[quote=lele_vader]Aqui tem um exemplo

Só lembrar que tem que implementar equals e hashcode no classe que você quer converter, no caso Resposta.

[/quote]

Eu tinha feito o seguinte, mapeava para passar apenas o id para o mb, ai fiz esse converter aqui mas não adiantou nada:

[code]public class LongConverter implements Converter {

public Object getAsObject(FacesContext arg0, UIComponent arg1, String valor) throws ConverterException {  
	Long resultado = null;
	
    try {  
       resultado = new Long(Long.parseLong(valor));  
    } catch (NumberFormatException nfe) {  
       throw new ConverterException(valor + " não é um número válido!", nfe);  
    }  
    return resultado;  
}


public String getAsString(FacesContext arg0, UIComponent arg1, Object obj) throws ConverterException {  
	String resultado ="";  
    
	if (obj != null) {  
       resultado = obj.toString();  
	}
	return resultado;  
}

}[/code]

O getAsObject tinha que retornar o seu objeto resposta não ?

você implementou o método toString da classe Resposta, pois você chama toString em getAsString.

Acredito que o toString você pode retornar o id do objeto para no getAsObject pegar esse id e consultar pelo objeto completo.

[quote=lele_vader]O getAsObject tinha que retornar o seu objeto resposta não ?

você implementou o método toString da classe Resposta, pois você chama toString em getAsString.

Acredito que o toString você pode retornar o id do objeto para no getAsObject pegar esse id e consultar pelo objeto completo.

[/quote]
Então como estou utilizando EJB, li que converteres ainda não dão suporte para injeção de dependência. Teria outra forma de buscar esse objeto, ou só por lookup?

Nesse exemplo foi criado um managedBean para colocar o converter, e nele foi colocado um EJB com injeção de dependência.

[quote=lele_vader]Nesse exemplo foi criado um managedBean para colocar o converter, e nele foi colocado um EJB com injeção de dependência.

http://stackoverflow.com/questions/2019495/inject-a-ejb-into-a-jsf-converter-with-jee6[/quote]Essa é a solução mais simples.

Uma outra forma, seria pegar o MB de dentro do contexto e utilizá-lo para fazer a pesquisa. [=

[quote=lele_vader]Nesse exemplo foi criado um managedBean para colocar o converter, e nele foi colocado um EJB com injeção de dependência.

Então deixa eu ver se entendi, no meu xhtml ficaria assim:

		<p:selectOneRadio id="respostas" value="#{desafioMB.respostaSelecionada}" required="true" requiredMessage="#{msg.respostaPerguntaRequired}">
			<f:selectItems value="#{desafioMB.pergunta.respostas}" var="r" itemValue="#{r.id}" itemLabel="#{r.resposta}" />
			<f:converter converterId="LongConverter"/>
		</p:selectOneRadio>

em value eu passaria:

value="#{desafioMB.respostaSelecionada}"

ou

value="#{desafioMB.respostaId}"

Sendo que respostaSelecionada é o objeto Resposta e respostaId é um Long.

E no converter eu receberia o id e retornaria o objeto?

Não funcionou :frowning:

Fiz meu converter assim:

[code]public class LongConverter implements Converter {

public Object getAsObject(FacesContext arg0, UIComponent arg1, String valor)
		throws ConverterException {
	InitialContext ini = null;
	Resposta resposta = null;
	try {
		RespostaFacade respostaFacade = (RespostaFacade) ini.lookup("java:module/RespostaFacade");
		resposta = respostaFacade.buscaPorId(Long.valueOf(valor));
	} catch (NamingException e) {
		e.printStackTrace();
	} catch (NumberFormatException nfe) {
		throw new ConverterException(valor + " não é um número válido!",
				nfe);
	}
	return resposta;
}

public String getAsString(FacesContext arg0, UIComponent arg1, Object obj)
		throws ConverterException {
	String resultado = "";

	if (obj != null) {
		resultado = obj.toString();
	}
	return resultado;
}

}[/code]

E minha página ficou assim:

[code]

<h:form id="formDesafio">
	<p:messages autoUpdate="true" />
	<h:outputText value="#{desafioMB.pergunta.texto}" />
	<br />
	<p:selectOneRadio id="respostas" value="#{desafioMB.respostaSelecionada}" required="true" requiredMessage="#{msg.respostaPerguntaRequired}">
		<f:selectItems value="#{desafioMB.pergunta.respostas}" var="r" itemValue="#{r}" itemLabel="#{r.resposta}" />
		<f:converter converterId="LongConverter"/>
	</p:selectOneRadio>
	
	<p:commandButton value="#{msg.responder}" action="#{desafioMB.responder}" />
	<p:commandButton value="#{msg.desistir}" onclick="desistirDlg.show()" />
	<br />
</h:form>[/code]

Quando eu clico em responder, não acontece nada… tentei debugar, mas nada também… alguma sugestão?

No value acho que ficaria respostaSelecionada, o qual é um objeto Resposta.

O que o converter vai fazer é pegar o seu objeto e colocar o select como long e quando der o submit pegar o long e transformar em objeto de novo, acredito eu.

Dá uma olhada no exemplo que te passei.

[quote=lele_vader]No value acho que ficaria respostaSelecionada, o qual é um objeto Resposta.

O que o converter vai fazer é pegar o seu objeto e colocar o select como long e quando der o submit pegar o long e transformar em objeto de novo, acredito eu.

Dá uma olhada no exemplo que te passei.[/quote]

Bom consegui resolver o problema, o que eu fiz foi:

Troquei o contexto de ViewScoped para RequestScoped

e deixei assim:

<p:selectOneRadio id="respostas" value="#{desafioMB.respostaId}" required="true"> <f:selectItems value="#{desafioMB.listRespostas}"/> </p:selectOneRadio>

no bean:

	public Collection<SelectItem> getListRespostas() {    
	    Collection<SelectItem> lst = new ArrayList<SelectItem>();    
	    List<Resposta> lista = pergunta.getRespostas();
	    //lst.add(new SelectItem("", "Selecione"));
	    for (int i = 0; i < lista.size(); i++) {    
	        lst.add(new SelectItem(lista.get(i).getId(), lista.get(i).getResposta()));    
	    }    
	    return lst;    
	}

Só não entendi o por que do contexto estar influenciando. Alguém sabe explicar? rsrs