Re:Problema com uso da Classe Converter

Você se confundiu aí porque o target que recebe no getAsString não é uma instância de Area. Por que?

Porque você não setou ele no seu SelectItem, você setou o que provavelmente é uma String dentro dele. Altere isso:for(Area p : areas){ itens.add(new SelectItem(p.getArea(), p.getDescricao())); } para isso:for(Area p : areas){ itens.add(new SelectItem(p, p.getDescricao())); } Se quiser uma explicação mais detalhada de como implementar um Converter, pode ler essa resposta aqui.

Por que você não coloca a lista de Area diretamente? ao invés de criar uma lista de SelectItem?

Acho que o problema é porque o nome do converter está errado:

e

AreaConverter != areaConverter.

Você leu o link que eu postei acima falando de converter? ele explica esse problema seu

O link explica que o objeto que você seleciona tem que ser um dos objetos disponíveis na lista. Ele irá usar internamente o seu método equals para saber se o objeto está de fato na lista, se ele não retornar true para nenhum dos elementos, essa exceção que você disse será lançada.

Portanto você tem que implementar corretamente os métodos equals e hashCode.

Você chegou a analisar a execução do equals com um depurador? Viu se ele retorna true alguma vez?

Oi Pessoal, to precisando muito de uma ajuda com uso da classe Converter…
Retorno os objetos de uma classe para apresentar num selectOneMenu, até ai tudo bem, mas quando implemento a classe Converter para tratar os dados, apresenta o seguinte erro:

java.lang.ClassCastException: java.lang.String cannot be cast to financeiro.area.Area
	at financeiro.web.converter.AreaConverter.getAsString(AreaConverter.java:23)
	at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getFormattedValue(HtmlBasicRenderer.java:519)
        ...

O converter está na forma abaixo, mas esse erro acusa na linha que instancio a classe Area (Area area = (Area) target;)

package financeiro.web.converter;

import financeiro.area.*;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.*;
import javax.faces.application.FacesMessage;

@FacesConverter(value="AreaConverter",forClass = Area.class)
public class AreaConverter implements Converter{

    @Override
      public Object getAsObject(FacesContext context,UIComponent componente, String value) throws ConverterException{
        String texto = String.valueOf(value);
        AreaRN tp=new AreaRN();
        Integer codigo = Integer.valueOf(texto);
        return tp.carregar(codigo);
    }  

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object target) throws ConverterException{
        if (target!=null){             
           Area area = (Area) target;
           return area.toString();
        }  
         return null;  
    } 
}

O código do método que lista, no meu Bean está assim:

    public List<SelectItem> getAreas(){
        AreaRN areaService = new AreaRN();

        List<Area> areas = areaService.listar();

        List<SelectItem> itens = new ArrayList<SelectItem>();

        for(Area p : areas){
            itens.add(new SelectItem(p.getArea(), p.getDescricao()));
        }
        
        return itens;
    }

Por favor, me ajudem…

Eu fiz a alteração que você informou mas continua o mesmo erro, o meu SelectedtItem está assim:

            <h:selectOneMenu id="area" value="#{experimentoBean.selecionado.area}" converter="areaConverter">
                <f:selectItem itemValue="" itemLabel="Selecione..." />
               <f:selectItems value="#{areaBean.areas}" var="t"  
                               itemValue="#{t}" itemLabel="#{t.description}" />   
            </h:selectOneMenu>

O Bean:

   public List<SelectItem> getAreas(){
        AreaRN areaService = new AreaRN();
        List<Area> areas = areaService.listar();
        List<SelectItem> itens = new ArrayList<SelectItem>();
        for(Area p : areas){
            itens.add(new SelectItem(p, p.getDescricao()));
        }
          return itens;
    }

O Converter alterado ficou assim:

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object target){
        if (target!=null){             
                  //Aqui eu preciso converter para String pois eu busco o ID da Area e não a descricao, como no exemplo da página que voce enviou
            return ((Area)target).getArea().toString();  
        }  
         return null;  
    } 

Erro:
java.lang.ClassCastException: java.lang.String cannot be cast to financeiro.area.Area
at financeiro.web.converter.AreaConverter.getAsString(AreaConverter.java:23)

Alguma outra sugestão???

Oi rodrigo eu fiz o que você disse. alterando meu Bean e o Converter, veja:

Bean:

    public List<Area> getAreas(){
        AreaRN areaService = new AreaRN();

        List<Area> areas = areaService.listar();

        return areas;
    }

E o Converter:

@Override
public String getAsString(FacesContext ctx, UIComponent component, Object value){
        if(value != null){
            Area area = (Area) value;
            return area.getArea().toString();
        }
        return "";
}

Mas continua o mesmo erro nessa linha que instancio a classe Area:

java.lang.ClassCastException: java.lang.String cannot be cast to financeiro.area.Area
at financeiro.web.converter.AreaConverter.getAsString(AreaConverter.java:29)

Já não sei mais o que fazer!!! Eu não entendo porque ele diz que não pode instanciar um objeto dentro de um método que retorna uma String…
Alguma outra sugestão?

Obrigado!

Foi só um lapso na hora de escrever, mas o problema persiste. Eu fiz algumas alterações com base em outros exemplos.

O erro mudou, mas pelo jeito agora o converter está atuando corretamente, porém ainda está com o erro na hora de retornar a classe, vejam a mensagem que me retorna (a primeira linha é somente o resultado do comando que pedi pra mostrar na tela, o erro é a segunda linha!):

Codigo da Area selecionado: 31

edicao:area: Erro de validação: o valor não é válido

Meu converter:

    @Override
      public Object getAsObject(FacesContext context,UIComponent componente, String value) throws ConverterException{
        String texto = String.valueOf(value);
        AreaRN tp=new AreaRN();
        Integer codigo = Integer.valueOf(texto);
                
        FacesContext.getCurrentInstance().addMessage("consulta:id",  
        new FacesMessage(" Codigo da Area selecionado: "+codigo));
                
        return tp.carregar(codigo);  // Aqui, ele tem que buscar o Objeto Area, mas não sei porque a a validação diz que o valor não é válido!
    } 
   
   @Override
    public String getAsString(FacesContext context, UIComponent component, Object target) {  
        if (target!=null){             
           return String.valueOf(target);  
        }  
         return null;  
    } 

Eu fiz um teste alterando o selectOneMenu, deixando apenas com campos Strings adicionados manualmente, deixei o itemValue com valores reais do id das minhas Áreas, aí ele funciona!!! Mas quando faço essa busca na classe utilizando o Bean para apresentar no selectOneMenu, dá essa confusão toda.

Alguma sugestão?

Eu tentei fazer exatamente como está lá mas não deu certo, são os mesmos problemas.

Oi Rodrigo, antes de tudo muito obrigado pela paciência…
Mas eu tentei com minha Classe Area com métodos equals e hashcode de duas formas:

  1. Igual à sua sugestão
 @Override
    public int hashCode() {
        int hash = 7;
        hash = 43 * hash + ((this.codArea == null ) ? 0 :this.codArea.hashCode());
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        
        if (this == obj)
            return true;
        
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof Area))
        return false;
        
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Area other = (Area) obj;
        if (this.codArea != other.codArea && (this.codArea == null || !this.codArea.equals(other.codArea))) {
            return false;
        }
        return true;
    }
  1. Conforme o netBeans criou
@Override
    public int hashCode() {
        int hash = 7;
        hash = 43 * hash + (this.codArea != null ? this.codArea.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        
        
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Area other = (Area) obj;
        if (this.codArea != other.codArea && (this.codArea == null || !this.codArea.equals(other.codArea))) {
            return false;
        }
        return true;
    }

Mas fica apresentando o erro:
Codigo da Area Selecionada: 77
edicao:area: Erro de validação: o valor não é válido

Eu sei que o conversor esta recebendo o código de área correto pois na primeira linha aparece a impressão que faço para confirmar, mas fica acusando esse tal de valor não é valido.

O que me deixa mais intrigado, é que quando troco o Select para os campos informados manualmente com os códigos cadastrados no bando de dados (exemplo abaixo), o CONVERTER aceita e busca o objeto normalmente, fazendo a inclusão dos dados…

  <f:selectItem itemValue="74" itemLabel="exp 1" />
  <f:selectItem itemValue="75" itemLabel="exp 1" />
  <f:selectItem itemValue="76" itemLabel="exp 1" />
  <f:selectItem itemValue="77" itemLabel="exp 1" />
  <f:selectItem itemValue="78" itemLabel="exp 1" />

To ficando maluco…

Oi Rodrigo, muito obrigado pela ajuda!

O problema estava na classe areaConverter:

Deveria estar assim para funcionar:

@FacesConverter("AreaConverter")
public class AreaConverter implements Converter{
    private AreaRN tp=new AreaRN();

@Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        Area area = null;
        try {
            area = tp.carregar(new Integer(value));
        } catch (Exception e) {
            System.out.println(e);
        }
        return area;
    }
  
    @Override
    public String getAsString(FacesContext context, UIComponent component, Object target) {  
        String resultado = "";
        if (target != null && target instanceof Area) {
            if (((Area) target).getCodArea() != null) {
                resultado = ((Area) target).getCodArea().toString();
            }
        }
        return resultado;
    }

Muito obrigado mesmo e abraços!