Vraptor muda o comportamento do Xstream?

24 respostas
renanreismartins

Prezados, tenho o seguinte codigo em um metodo main qualquer:

List<Amount> amounts = // populo a lista

XStream xs = new XStream(new JettisonMappedXmlDriver());
xs.aliasSystemAttribute(null, "class");
xs.aliasSystemAttribute(null, "resolves-to");
xs.setMode(XStream.NO_REFERENCES);
xs.autodetectAnnotations(true);

String get = xs.toXML(amounts);

meu json retornado:

{
    "list": [
        {
            "amount": [
                {
                    "amount": 100,
                    "type": {
                        "id": 1,
                        "title": "dano moral"
                    }
                },
                {
                    "amount": 200,
                    "type": {
                        "id": 1,
                        "title": "dano moral"
                    }
                }
            ]
        }
    ]
}

tudo perfeito até então...

Porém quando populo a lista da mesma maneira num controller:

@Get("/urlAki")
public void getAmounts(Task task, ObligationToPay obligationToPay) {
	
	List<Amount> amounts = // populo do mesmo jeito
	result.use(Results.json()).from(amounts).include("type").serialize();
}

o meu json retornado é:

[code]
{
    "list": [
        {
            "br.com.fourdata.model.cco.Amount": [
                {
                    "amount": 100,
                    "type": {
                        "id": 1,
                        "title": "dano moral"
                    }
                },
                {
                    "amount": 200,
                    "type": {
                        "id": 1,
                        "title": "dano moral"
                    }
                }
            ]
        }
    ]
}

Notem que ele colocou o nome qualificado. Alterando o comportamento padrao, como chamado no metodo main. Cabe salientar que ja criei classe que customiza a criação do Xstream

@PrototypeScoped
@Component
public class CustomXStreamBuilder extends XStreamBuilderImpl {

	public CustomXStreamBuilder(XStreamConverters converters, TypeNameExtractor extractor) {
		super(converters, extractor);
	}

	public XStream configure(XStream xstream) {
		xstream = new XStream(new JettisonMappedXmlDriver());
		xstream.aliasSystemAttribute(null, "class");
		xstream.aliasSystemAttribute(null, "resolves-to");
		xstream.setMode(XStream.NO_REFERENCES);
		xstream.autodetectAnnotations(true);

		super.configure(xstream);

		return xstream;
	}
}

existe uma maneira de nao sobreescrever o comportamento?

abrasssss

24 Respostas

Lucas_Cavalcanti

troque o new XStream por new VRaptorXStream(extractor, driver)

ele faz os alias pras classes automaticamente

renanreismartins

tks lucas,

mas trocar no método configure do CustomXStreamBuilder?

Ele me pede um TypeNameExtractor…

edit: nao sei passei a mensagem certa, gostaria que ele deserializasse da forma padrao do Xstream

abrasss

renanreismartins

fiz dessa maneira:

@PrototypeScoped
@Component
public class CustomXStreamBuilder extends XStreamBuilderImpl {

	private TypeNameExtractor extractor;
	
	public CustomXStreamBuilder(XStreamConverters converters, TypeNameExtractor extractor) {
		super(converters, extractor);
	}

	public XStream configure(XStream xstream) {
		xstream = new VRaptorXStream(extractor, new JettisonMappedXmlDriver());
		//xstream = new XStream(new JettisonMappedXmlDriver());
		xstream.aliasSystemAttribute(null, "class");
		xstream.aliasSystemAttribute(null, "resolves-to");
		xstream.setMode(XStream.NO_REFERENCES);
		xstream.autodetectAnnotations(true);

		super.configure(xstream);
		return xstream;
	}
}

mas dai recebo uma ex

br.com.caelum.vraptor.InterceptionException: exception raised, check root cause for details: java.lang.NullPointerException
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:96)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:61)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:93)
	at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:59)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:48)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	at br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:71)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:83)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	at br.com.caelum.vraptor.core.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:44)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:58)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:964)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:304)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.NullPointerException
	at br.com.caelum.vraptor.serialization.xstream.VRaptorClassMapper.serializedClass(VRaptorClassMapper.java:83)
	at com.thoughtworks.xstream.mapper.MapperWrapper.serializedClass(MapperWrapper.java:34)
	at com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter.writeItem(AbstractCollectionConverter.java:62)
	at com.thoughtworks.xstream.converters.collections.CollectionConverter.marshal(CollectionConverter.java:55)
	at com.thoughtworks.xstream.core.TreeMarshaller.convert(TreeMarshaller.java:86)
	at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:78)
	at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:63)
	at com.thoughtworks.xstream.core.TreeMarshaller.start(TreeMarshaller.java:98)
	at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.marshal(AbstractTreeMarshallingStrategy.java:38)
	at com.thoughtworks.xstream.XStream.marshal(XStream.java:837)
	at com.thoughtworks.xstream.XStream.marshal(XStream.java:826)
	at com.thoughtworks.xstream.XStream.toXML(XStream.java:801)
	at br.com.caelum.vraptor.serialization.xstream.XStreamSerializer.serialize(XStreamSerializer.java:142)
	at br.com.fourdata.controller.ObligationToPayController.getAmounts(ObligationToPayController.java:136)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:61)
	... 45 more
Lucas_Cavalcanti

faltou um this.extractor = extractor; no construtor.

renanreismartins

perdao!

vou blogar sobre isso como retribuição cara!

vc n acha legal esse comportamento como padrao?

muito obrigado mesmo!

absss

Lucas_Cavalcanti

o problema de deixar isso como padrão é que vai quebrar todo mundo que usa json no VRaptor…

mas manda aí o link do post pra gente colocar no site!

renanreismartins

Estou tentando deixar rendondo, dps te envio o codigo pra deixarmos o mais elegante possivel.

Uma coisa que notei, não tem haver com o vraptor mas sim Xstream, é que quando pedimos para ele serializar uma lista vazia como

List<Amount> amounts = new ArrayList<>();
String get = xs.toXML(amounts);

eu recebo

{"list":[""]}

ideal seria que viesse um array vazio, sem o “objeto” string la dentro, assim os clients nao precisam fazer verificação adicional do obj, apenas verificar se o array esta vazio ou nao como

{"list":[]}

tem ideia de como mudar esse comportamento? em libs como gson é assim

abrassss

Lucas_Cavalcanti

talvez sobrescrevendo o converter de listas… vc tá com a última versão do XStream, se eu não me engano isso era um bug que foi corrigido.

renanreismartins

Xstream 1.4.2

jettison 1.3.1

tentei sobrescrever a CollectionConverter. Deixei os métodos unmarshal e marshal vazios, mesmo assim me retornou o mesmo json. Não consegui entender

abrasss

Lucas_Cavalcanti

qual código vc usou?

renanreismartins
xstream.registerConverter(new CollectionConverter(xstream.getMapper()) {
			@Override
			@SuppressWarnings("rawtypes")
			public boolean canConvert(Class type) {
				return Collection.class.isAssignableFrom(type);
			}
			
			
			public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
		    }

		    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
		       return null;
		    }
			
		});

algo como isso…

mesmo assim ele retorna akele json…

{"list":[""]}

abrasss

Lucas_Cavalcanti

só um teste rápido: esse mesmo código no XStream 1.3.1 funciona?

renanreismartins

n… tem o mesmo comportamento em ambas as versoes

Lucas_Cavalcanti

bom, vc pode usar uma gambiarra no controller por enquanto…

if (lista.isEmpty())
    result.use(http()).body("{\"list\": []}");
else
    result.use(json()).from(lista).serialize();
renanreismartins

confesso que pensei em fazer isso dentro do converter rsrs. mas como mostrei ele nao deu certo sobreescrever. Tem ideia de pq?

Será que esse comportamento do list é um bug deles que será corrigido?

to tentando corrigir esses dois problemas pra fazer o post do blog, mas o duro é que o “problema” é do xstream nao do vraptor, entao ta dificil rs.

abrassss

Lucas_Cavalcanti

parece ser do xstream mesmo, principalmente se vc fez esse teste num main com um new XStream(driverdoJson)

renanreismartins

é dele sim, com o JsonHierarchicalStreamDriver
ele serializa certo, porém esse driver não deserializa.

apenas o JettisonMappedXmlDriver deserializa.

isso em ambas as versões… =/ #fail

abrasss

Lucas_Cavalcanti

não dá pra usar um driver pra serializar e outro pra deserializar, neh?

renanreismartins

tentei isso também, mas como um driver se comporta diferente do outro, oque deserializa (JettisonMappedXmlDriver) espera as tais aspas.

stack

{"list": [
]}
Exception in thread "main" com.thoughtworks.xstream.io.StreamException:  : org.codehaus.jettison.json.JSONException: JSONArray[0] not found.
	at com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver.createReader(JettisonMappedXmlDriver.java:58)
	at com.thoughtworks.xstream.XStream.fromXML(XStream.java:853)
	at com.thoughtworks.xstream.XStream.fromXML(XStream.java:845)
	at br.com.fourdata.controller.Amounts.main(Amounts.java:64)
Caused by: javax.xml.stream.XMLStreamException: org.codehaus.jettison.json.JSONException: JSONArray[0] not found.
	at org.codehaus.jettison.mapped.MappedXMLInputFactory.createXMLStreamReader(MappedXMLInputFactory.java:46)
	at org.codehaus.jettison.AbstractXMLInputFactory.createXMLStreamReader(AbstractXMLInputFactory.java:151)
	at com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver.createReader(JettisonMappedXmlDriver.java:56)
	... 3 more
Caused by: org.codehaus.jettison.json.JSONException: JSONArray[0] not found.
	at org.codehaus.jettison.json.JSONArray.get(JSONArray.java:162)
	at org.codehaus.jettison.json.JSONArray.getJSONObject(JSONArray.java:254)
	at org.codehaus.jettison.mapped.MappedXMLStreamReader.<init>(MappedXMLStreamReader.java:51)
	at org.codehaus.jettison.mapped.MappedXMLInputFactory.createXMLStreamReader(MappedXMLInputFactory.java:44)
	... 5 more

abrasss

Lucas_Cavalcanti

GSON? :wink:

renanreismartins

vc quer dizer, fazer o vraptor usar o gson ao invés do xstream?

abs

Lucas_Cavalcanti

É um dos jeitos… talvez fique mais consistente…

tenta usar um desses:


renanreismartins

lucas mto obrigado pela paciencia e contribuição.

Pelo pouco que vi a solução criada pelos caras foi bem melhor que a minha.

Vai ser muito util até para aprender como eles estenderam o framework, vou estudar e se tentar contribuir com um dos plugins.

abrassss

Lucas_Cavalcanti

contribuições são sempre bem-vindas =)

Criado 8 de março de 2012
Ultima resposta 15 de mar. de 2012
Respostas 24
Participantes 2