Bom dia, eu sei que nas versões anteriores haviam alguns bugs em relacao a serializacao de herança e com os .includes(), ai baixei o VRaptor 3.4.1 e parei de ter uma excecao mas em compensacao o resultado ainda nao e como o esperado. Vejam so:
CONTROLLER:
@Get("/contato/{contato.id}.json")
public void obterContatoPorIdRetornandoJson(Contato contato){
this.resultado.use(Results.json())
.withoutRoot()
.from(this.contatoDao.procurar(contato))
.include("telefones")
.serialize();
}
RESULTADO:
{
"id": 1,
"excluido": false,
"dataDeCriacao": {
"time": 1335536220000,
"timezone": "America/Sao_Paulo"
},
"tipo": "juridica",
"telefones": [
false,
-1,
"br.ind.prv.dominio.Contato.telefones",
false
],
"nome": "Pedreira Rio Verde LTDA",
"dataDeNascimento": {
"time": 1335536220000,
"timezone": "America/Sao_Paulo"
},
"registroNacional": "00132781000178",
"inscricaoMunicipal": "103010068"
}
O problema esta no campo “telefones” que nao traz os telefones e sim dados do objeto ArrayList… Alguem tem alguma ideia???
Eu estava suspeitando que na hora da serializacao o hibernate ainda nao tinha buscado a colecao de telefones no banco e que dessa forma o vraptor estava serializando um objeto de proxy do hibernate, mas ai eu fiz um contato.getTelefones(); antes da serializacao e nao mudou nada…
Engraçado é que serializando direto usando o XStream + Jettison eu consigo perceber que de fato tem um objeto do Hibernate ai no meio e que em uma de sua propriedades tem sim a lista…
CODIGO
XStream xstream = new XStream(new JettisonMappedXmlDriver());
System.out.println(xstream.toXML(this.contatoDao.procurar(contato)));
RESULTADO
...
"telefones":[{"@class":"org.hibernate.collection.PersistentBag","initialized":true,"owner":{"@class":"br.ind.prv.dominio.PessoaJuridica","@reference":"..\/.."},"cachedSize":-1,"role":"br.ind.prv.dominio.Contato.telefones","key":{"@class":"long","$":"1"},"dirty":false,"storedSnapshot":{"@class":"list","br.ind.prv.dominio.Telefone":{"id":1,"excluido":false,"dataDeCriacao":{"time":1335538203000,"timezone":"America\/Sao_Paulo"},"numero":6132084002,"tipo":"Comercial"}},"bag":[{"br.ind.prv.dominio.Telefone":{"@reference":"..\/..\/storedSnapshot\/br.ind.prv.dominio.Telefone"}}]}],
...
tem certeza que é um ArrayList, e não um List qualquer?
se isso veio do hibernate, não é um ArrayList, é um persistentBag.
vc precisa colocar esse converter:
http://www.wbotelhos.com.br/2010/08/26/vraptor-3-evitando-circularreferenceexception-do-xstream/
na parte do collectionconverter…
vc pode fazer isso no xstreamBuilder ao invés do JSONSerialization
Muito obrigado Lucas, agora funcionou!!!
Lucas, antes deu mudar para 3.4.1 eu nao tinha problemas com esse metodo:
@Get("/contatos/busca-resumida.json")
public void buscaResumida(String nome){
this.resultado.use(Results.json())
.withoutRoot()
.from(this.contatoDao.buscaPorNome(nome))
.exclude("registroEstadual")
.exclude("excluido")
.exclude("tipo")
.exclude("dataDeCriacao")
.exclude("dataDeNascimento")
.exclude("observacoes")
//.exclude("inscricaoMunicipal")
.serialize();
}
Agora, ele da uma excecao na linha comentada porque “inscricaoMunicipal” so tem em um dos filhos, nao na classe pai. Existe uma maneira de contornar isto? A intencao desta busca e retornar apenas o id do objeto, e desta maneira, quando for PessoaJuridica vai retornar tambem a inscricao municipal, que e desnecessaria neste contexto. O que acha???
vc quer retornar só os ids?
o mais fácil pra garantir isso, é serializar uma lista só com os ids:
List<Pessoa> pessoas = this.contatoDao.buscaPorNome(nome);
List<Long> ids = Lists.transform(pessoas, new Function<Pessoa,Long>() {
public Long apply(Pessoa pessoa) {
return pessoa.getId();
}
}
result.use(json()).withoutRoot().from(ids).serialize();
isso ou o forzinho equivalente 
Obrigado Lucas, como sou novo no java ainda nao conhecia esse macete!!! Cara, se nao for abusar, e puder fazer mais uma pergunta… existe uma maneira de sobrescrever a seralizacao de um tipo especifico no VRaptor??? Por exemplo… quando eu serializo um calendar ele fica assim:
"dataDeNascimento": {
"time": 1335644466000,
"timezone": "America/Sao_Paulo"
}
porém eu gostaria de ter a data por extenso mesmo:
"dataDeNascimento": "21/04/1987 00:00:00"
Algo como:
@Component
@CustomSerializer
public class CalendarCustomSerialization extends CustomSerialization<Calendar>{
public String serialize(Calendar calendar){
return "data do jeito que eu quero";
}
}
Obrigado novamente Lucas! Estamos reimplementando o sistema da empresa em java e escolhi o VRaptor para isso, ate agora so estou me impressionando com todas as funcionalidades e rapidez no desenvolvimento!!! abracao
só criar um converter do XStream pra data, e anotá-la com @Component:
@Component
public class SeuDateConverter implements SingleValueConverter {
//....
}
se for um tipo mais complicado, vc pode usar o Converter do XStream.