Olá a todos,
estou com um problema ao serializar meus objetos através do VRaptor.
this.result.use(xml()).from(gerenciador.lista(usuario.getEmpresa()), "funcionarios").include("setor").serialize();
Se no JPA o relacionamento entre funcionario e setor for LAZY
o VRaptor serializa o objeto setor mas como um proxy do hibernate
Alguém sabe como resolver isso sem que seja definir o relacionamento como EAGER?
Desde já obrigado
vc vai ter que forçar o load da coleção…
ou chamando funcionario.getSetor();, ou se vc estiver usando HQL, vc pode forçar:
"from Funcionarios f join fetch f.setor where ...."
não testei essa query, mas é algo do tipo… talvez vc não precise da palavra fetch
Olá Lucas,
Está OK. Obrigado.
Nem precisei forçar o hibernate buscar no banco.
Fazendo os testes de serialização de objetos pelo XStream e Vraptor percebi um problema:
o XSTream usa getters e setters, correto!?
no entanto, fiz um teste assim:
private String local = "atributo";
public String getLocal() {
return "get";
}
e ele sempre retorna “atributo”. Ele não deveria usar o método getLocal?
desde já obrigado
por padrão o XStream usa fields… se vc quiser que ele use getters e setters vc precisa registrar o converter JavaBeanConverter:
xstream.registerConverter(new JavaBeanConverter());
a proxima versão do vrpator deve solucionar esse problema do lazy ^^
na verdade a que esta no snapshot já resolve…
só falta alguns detalhes pra ficar 100% =x
Lucas,
consegui fazer isso LOCAL, sem usar o Vraptor… quando uso o Vraptor nada é serializado…
eu já criei uma classe chamada CustomXMLSerialization para retornar o XStream com o registro do converter
xstream.registerConverter(new JavaBeanConverter(xstream.getMapper());
sabe oq pode estar acontecendo?
essa CustomXMLSerialization estende XStreamXMLSerialization? ela sobrescreve o método getXStream? ela está anotada com @Component?
Sim.
está tudo ok.
segue abaixo o código:
package br.com.originalsoftware.concrebase.controller;
import javax.servlet.http.HttpServletResponse;
import br.com.caelum.vraptor.interceptor.TypeNameExtractor;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.serialization.xstream.XStreamXMLSerialization;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.javabean.JavaBeanConverter;
@Component
public class CustomXMLSerialization extends XStreamXMLSerialization {
public CustomXMLSerialization(HttpServletResponse response, TypeNameExtractor extractor) {
super(response, extractor);
}
// delegate constructor
@Override
protected XStream getXStream() {
XStream xstream = super.getXStream();
xstream.registerConverter(new ConverterDate());
xstream.registerConverter(new JavaBeanConverter(xstream.getMapper()));
return xstream;
}
}
Esse component está sendo usado pelo Vraptor… o único problema é o JavaBeanConverter… quando eu registro ele… nada é serializado…
quando executo ele local funciona normalmente
pesquisei no google mas não encontrei uma solução…
cheguei a implementar o método canConverter e canHandle mas não mudou nada.
Lucas,
consegui.
xstream.registerConverter(new JavaBeanConverter(xstream.getMapper()) {
public boolean canConvert(Class clazz) {
return clazz.equals(Entrega.class);
}
});
Estava fazendo o canConvert retornar true quando o tipo era o tipo do retorno do atributo e não da classe.
Erro meu.
Obrigado pela ajuda.
O VRaptor serializa a proxy justo porque o XStream usa os atributos. Como ele acessa um atributo diretamente, se seu objeto é uma proxy (o session.load devolve proxy, apenas o .get faz uma requisicao direta sempre) ele vai serializar um monte de nulls e atributos especiias.
O Vitor e o Lavieri perceberam muito bem isso.
Vitor, pra ser sincero, eu havia tentado sua solução há algum tempo atrás, e tive o mesmo problema, tanto em testes com vraptor ou diretamente com o XStream. Em outras palavras, acho que o JavaBeanConverter nao esta mais funcionando como deveria.
Olá a todos,
havia esquecido de colocar a solução aqui.
A conclusão que eu cheguei é que o XStream não funciona corretamente quando você não especifica as classes que vão ser utilizadas pelo JavaBeanConverter mas, quando você especifica ele funciona direito.
Não fui atrás para saber o porque mas segue a solução abaixo:
@Component
public class CustomXMLSerialization extends XStreamXMLSerialization {
public CustomXMLSerialization(HttpServletResponse response, TypeNameExtractor extractor) {
super(response, extractor);
}
@Override
protected XStream getXStream() {
XStream xstream = super.getXStream();
xstream.registerConverter(new ConverterDate());
xstream.registerConverter(new JavaBeanConverter(xstream.getMapper()) {
@SuppressWarnings("unchecked")
public boolean canConvert(Class classe) {
List<Class> classes = new ArrayList<Class>();
classes.add(Betoneira.class);
classes.add(Descarregamento.class);
classes.add(Entrega.class);
classes.add(Obra.class);
classes.add(Posicionamento.class);
classes.add(Rastreador.class);
return classes.contains(classe);
}
});
return xstream;
}
}
Assim ele funciona corretamente e, não lendo a partir do field, ele não pode retornar o proxy do Hibernate.
Obrigado a todos
oi vitor
a versao 3.1.2, que deve sair na semana que vem, ja vem com uma correcao para o problema.
paulo
O que foi feito para corrigir o problema?
basicamente foi inicializar os proxies antes de serializar… o lavieri que fez =)
Aos poucos a galera está conhecendo o projeto e logo começarão a vir muitas contribuições
Alguem tentou o mesmo pra JSON?
Criei um CustomJSONSerialization semelhante ao do vitor.valerio, mas não consegui recuperar um objeto relacionado como EAGER
vlw!
Eu estava fazendo errado. Nem precisou da classe.
Apenas adicionei o include no código abaixo e funcionou:
List<Ad> ads = this.adService.search(q);
this.result.use(Results.json()).from(ads).include("publisher").serialize();
Abs!