[RESOLVIDO] EntityConverter, lista mas não seleciona corretamente
13 respostas
R
rodrigomarcelo
Boa tarde,
Tentei e pesquisei muito antes de estar aqui novamente trazendo mais problemas mas... não consegui mesmo.
Estou tentando popular um h:selectOneMenu com objetos do meu projeto. Para tal estou utilizando um conversor genérico que foi modificado e publicado por um membro aqui do GUJ, o Sr. Flavio Almeida.
Consigo popular normalmente, mas quando seleciono e submeto página, aparece o erro:
Erro de validação: o valor não é válido
Meus métodos equals e hashCode estão sobrescritos (gerado automaticamente pelo eclipse).
Bom, não deve fazer diferença, mas vc usando uma lista de SelectItem, vc não precisa definir o var, o itemValue e o itemLabel no seu componente no seu XHTML. Basta ter a referência para a lista.
Cola aqui o código do converter que o Flávio fez.
R
rodrigomarcelo
Arthur F. Ferreira:
Bom, não deve fazer diferença, mas vc usando uma lista de SelectItem, vc não precisa definir o var, o itemValue e o itemLabel no seu componente no seu XHTML. Basta ter a referência para a lista.
Cola aqui o código do converter que o Flávio fez.
Obrigado por responder Arthur.
Removi o que me passou, mas obtive o mesmo resultado.
Segue o converter:
packageutils;importjava.lang.reflect.Field;importjava.util.ArrayList;importjava.util.List;importjavax.faces.component.UIComponent;importjavax.faces.context.FacesContext;importjavax.faces.convert.Converter;importjavax.persistence.EmbeddedId;importjavax.persistence.Id;/** * Converter para entidades JPA. Baseia-se nas anotações @Id e @EmbeddedId para * identificar o atributo que representa a identidade da entidade. Capaz de * detectar as anotações nas classes superiores. * * @author Flávio Henrique * @version 1.0.3 * @since 05/10/2010 */publicclassEntityConverterimplementsConverter{publicObjectgetAsObject(FacesContextctx,UIComponentcomponent,Stringvalue){if(value!=null){returncomponent.getAttributes().get(value);}returnnull;}publicStringgetAsString(FacesContextctx,UIComponentcomponent,Objectobj){if(obj!=null&&!"".equals(obj)){Stringid;try{id=this.getId(getClazz(ctx,component),obj);if(id==null){id="";}id=id.trim();component.getAttributes().put(id,getClazz(ctx,component).cast(obj));returnid;}catch(SecurityExceptione){e.printStackTrace();// seu log aqui}catch(IllegalArgumentExceptione){e.printStackTrace();// seu log aqui}catch(NoSuchFieldExceptione){e.printStackTrace();// seu log aqui}catch(IllegalAccessExceptione){e.printStackTrace();// seu log aqui}}returnnull;}/** * Obtém, via expression language, a classe do objeto. * * @param FacesContext * facesContext * * @param UICompoment * compoment * * @return Class<?> */privateClass<?>getClazz(FacesContextfacesContext,UIComponentcomponent){returncomponent.getValueExpression("value").getType(facesContext.getELContext());}/** * Retorna a representação em String do retorno do método anotado com @Id ou @EmbeddedId * do objeto. * * @param Class * <?> clazz * * @return String */publicStringgetId(Class<?>clazz,Objectobj)throwsSecurityException,NoSuchFieldException,IllegalArgumentException,IllegalAccessException{List<Class<?>>hierarquiaDeClasses=this.getHierarquiaDeClasses(clazz);for(Class<?>classeDaHierarquia:hierarquiaDeClasses){for(Fieldfield:classeDaHierarquia.getDeclaredFields()){if((field.getAnnotation(Id.class))!=null||field.getAnnotation(EmbeddedId.class)!=null){FieldprivateField=classeDaHierarquia.getDeclaredField(field.getName());privateField.setAccessible(true);if(privateField.get(clazz.cast(obj))!=null){return(String)field.getType().cast(privateField.get(clazz.cast(obj))).toString();}}}}returnnull;}/** * Retorna uma lista com a hierarquia de classes, sem considerar a classe * Object.class * * @param Class * <?> clazz * * @return List<Class<?>> clazz */publicList<Class<?>>getHierarquiaDeClasses(Class<?>clazz){List<Class<?>>hierarquiaDeClasses=newArrayList<Class<?>>();Class<?>classeNaHierarquia=clazz;while(classeNaHierarquia!=Object.class){hierarquiaDeClasses.add(classeNaHierarquia);classeNaHierarquia=classeNaHierarquia.getSuperclass();}returnhierarquiaDeClasses;}}
Hebert_Coelho
Não olhei para ver o que esse código faz… mas… você olhou se o código do converter está sendo chamado?
R
rodrigomarcelo
Sim… já debuguei pra ver se estava sendo chamado… e está sim…
Hebert_Coelho
Sim… já debuguei pra ver se estava sendo chamado… e está sim…E ele está retornando um valor válido?
R
rodrigomarcelo
Sim… já debuguei pra ver se estava sendo chamado… e está sim…E ele está retornando um valor válido?
Sim… debugando o método getAsString funciona normalmente, e também quando seleciondo (método getAsObject), o value retorna o ID do objeto selecionado sim:
Mas o meu objeto Pessoa na Bean não recebe o objeto, e tenho esse retorno ai… =/
Arthur_F_Ferreira
Esse seu bean Pessoa é uma entidade com anotações JPA? Mais especificamente com @Id ou @EmbeddedId? Pq esse converter para funcionar tem que ser uma entidade com essas anotações JPA.
Arthur_F_Ferreira
Outra coisa: vc disse que ele retorna o ID corretamente, mas ele executa essa linha daqui sem erro?
returncomponent.getAttributes().get(value);
R
rodrigomarcelo
Arthur F. Ferreira:
Outra coisa: vc disse que ele retorna o ID corretamente, mas ele executa essa linha daqui sem erro?
returncomponent.getAttributes().get(value);
O erro dá justamente neste return...
A entidade em questão foi um teste que fiz bem simples, pra excluir a possibilidade de ser alguma outra coisa "externa", pra isto, criei essa entidade simples pra ver o que estava acontecendo:
...importjavax.persistence.Column;importjavax.persistence.Entity;importjavax.persistence.GeneratedValue;importjavax.persistence.Id;importorg.hibernate.annotations.GenericGenerator;importorg.hibernate.annotations.Index;@EntitypublicclassPessoa{@Id@GeneratedValue(generator="gen_pessoa")@GenericGenerator(name="gen_pessoa",strategy="increment")@Column(name="id",nullable=false)privateIntegerid;@Index(name="idx_nome_pessoa")@Column(name="nome",nullable=false,unique=true,length=100)privateStringnome;@OverridepublicinthashCode(){finalintprime=31;intresult=1;result=prime*result+((id==null)?0:id.hashCode());returnresult;}@Overridepublicbooleanequals(Objectobj){if(this==obj)returntrue;if(obj==null)returnfalse;if(getClass()!=obj.getClass())returnfalse;Pessoaother=(Pessoa)obj;if(id==null){if(other.id!=null)returnfalse;}elseif(!id.equals(other.id))returnfalse;returntrue;/// Getters e Setters...}
Arthur_F_Ferreira
Qual é o valor exato que vem no value?
E quando vc seleciona esse código (sem o return) e usa o CTRL+SHIFT+I, qual é a mensagem de erro detalhada que aparece para vc?
R
rodrigomarcelo
Arthur F. Ferreira:
Qual é o valor exato que vem no value?
E quando vc seleciona esse código (sem o return) e usa o CTRL+SHIFT+I, qual é a mensagem de erro detalhada que aparece para vc?
O Value vem o id da pessoa corretamente, já me certifiquei disso.
Não conhecia o CTRL+SHIFT+I… Já me ensinou mais uma =D
Resultado:
ID = NULL
NOME = NULL
Arthur_F_Ferreira
É…já dá para ver que tem algo de errado e provavelmente é a maneira com que o EntityConverter faz para recuperar um registro.
O converter que eu uso é diferente. Eu sigo o exemplo do Rafael Ponte:
Hoje mesmo no trabalho um colega estava tendo problemas com o converter que usava. Ele usou a implementação do SimpleIndexConverter que é a mais simples e, no seu caso, acho que será a melhor.
R
rodrigomarcelo
Arthur F. Ferreira:
É…já dá para ver que tem algo de errado e provavelmente é a maneira com que o EntityConverter faz para recuperar um registro.
O converter que eu uso é diferente. Eu sigo o exemplo do Rafael Ponte:
Hoje mesmo no trabalho um colega estava tendo problemas com o converter que usava. Ele usou a implementação do SimpleIndexConverter que é a mais simples e, no seu caso, acho que será a melhor.
Maravilha Arthur! Utilizei o SimpleIndexConverter da mesma maneira que estava usando o EntityConverter e funcionou de primeira!