Pesquisar

sábado, 29 de maio de 2010

NoSuchFieldException no Hibernate (JPA)

No padrão JPA você pode anotar suas entidades pelos métodos (getters) ou pelos atributos, é um ou exclusivo ou vocÊ anota tudo pelos atributos ou pelos getters. O relato que segue é sobre um código que funcionou muito bem por muito tempo mas que na última sexta feira (28/05/2010) me deu muita dor de cabeça.

Devido a limitação do JSF (1.X) quanto a população de combos (o usuário do framework é obrigado a passar uma lista/matriz de SelectItem), eu criei um código para que dado uma lista de objetos, o nome do atributo à ser mostrado (descricao) e o nome do atributo com valor (id) retorna uma matriz de SelectItem.

API SelectItem[] converterListaParaCombo(final List objetos,String attMostrar,String attValor)

O código é simples; faz um loop nos objetos e vai recuperando os valores dos campos por reflexão e criando objetos do tipo SelectItem e os adicionando na lista/matriz.

Bem, voltando ao relato. Quase sempre eu usei anotar (JPA Annotations) as entidades nos campos, por boa prática comecei anotar pelos getters.

Quando fui testar percebi que o método converterListaParaCombo estava lançando a exceção NoSuchFieldException. Dessa vez o log não ajudou quase nada, tive que debugar... para minha surpressa a lista ia sendo populada normalmente até chegar num objeto (da lista) que não tinha o campo descrição :S. A primeira pergunta: Como isso é possível se eu mesmo declarei o campo na entidade?

Para responder essa pergunta criei mais um teste sobre a lista de objetos que eu passava para o método. Mandei (imperativamente) um sysout sobre getId e getDescrição... aqui outra surpresa não houve nenhum erro :S. Numa pesquisa mais profunda sobre o assunto descobri que o hibernate tem "seu modo de fazer cache" que pode causar alguma surpresa para os mais desavisados e na verdade ele nem sempre retorna a sua entidade e sim um proxy {eu pensava
que esse proxy era somente para List}. E um desses proxies "não tinha" o campo descricao...

Para resolver o problema, eu apenas mudei no método a forma de recuperar os valores. Ao invés
de pegá-los pelo atributos agora pelo pelos métodos getters. :D

Nenhum comentário: