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.
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.
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;
}
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)
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?
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.
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:
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;
}
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…