VRaptor 3 + JSON

Estou recebendo a seguinte exception de um controller que quero retornar uma lista da erro ja se eu retornar o objeto em si funciona blz

                TbTabelaA tbTabelaA = new TbTabelaA();
		this.result.use(json()).from(tbTabelaA).serialize(); //Isto funciona
                final Collection<TbTabelaA> lista =  new ArrayList<TbTabelaA>();
                this.result.use(json()).from(lista).serialize();  //isto nao funciona

Exception:

br.com.caelum.vraptor.InterceptionException: java.lang.IllegalArgumentException: It’s not possible to serialize colections yet. Create a class that wraps this collections by now.
at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:76)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:72)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:42)
at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Thread.java:637)
Caused by: java.lang.IllegalArgumentException: It’s not possible to serialize colections yet. Create a class that wraps this collections by now.
at br.com.caelum.vraptor.serialization.XStreamXMLSerializer.from(XStreamXMLSerializer.java:90)
at br.com.caelum.vraptor.serialization.XStreamJSONSerialization.from(XStreamJSONSerialization.java:49)
at com.jvds.telecon.controller.CadClassificacaoController.listaJson(CadClassificacaoController.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:50)
… 37 more

Basta ler.

Ainda não foi implementada a serialização de coleções.

Ainda não usei essa feature do VRaptor, mas você pode tentar usar um array.

Pela mensagem diz que você deve ter uma wrapper enquanto não é implementado coleções JSON.

Para isso faça algo como:

[code]public class MyCollectionWrapper {
final Collection lista;

[...]

}[/code]

E no seu controller:

final Collection<TbTabelaA> lista = ... MyCollectionWrapper w = new MyCollectionWrapper(lista); result.use(json()).from(w).serialize();

Não adicionamos ainda o suporte a collections em json ou xml porque precisávamos definir algumas coisas, como o nome do que vai guardar a coleção, etc

por enquanto crie a classe wrapper, e na próxima versão do VRaptor a parte de serialização de collections deve ficar pronta

[quote=garcia-jj]Pela mensagem diz que você deve ter uma wrapper enquanto não é implementado coleções JSON.

Para isso faça algo como:

[code]public class MyCollectionWrapper {
final Collection lista;

[...]

}[/code]

E no seu controller:

final Collection<TbTabelaA> lista = ... MyCollectionWrapper w = new MyCollectionWrapper(lista); result.use(json()).from(w).serialize();[/quote]

fiz desta forma e da certo para qualquer entidade que tenho no meu sistema.

public class MyCollectionWrapper<Entity> {
	private Collection<Object> lista = new ArrayList<Object>();
	
	public Collection<Object> getLista() {
		return lista;
	}
	
	public void setLista(Collection<Entity> lista) {
		this.lista = (Collection<Object>)lista;
	}
}

no caso quem usa jQuery criei uma funcao que ele percorre o objeto de retorno JSON ate chegar numa Array, isto faz com que vc nao precisa saber o nome de objeto de retorno no ajax(jQuery) segue o codigo da funcao ai.

//funcao JavaScript objectJSON recursiva para percorrer um objeto JSON ate sua lista Array
function objetoJSON(objeto) {
	for (var obj in objeto) {
		var value = objeto[obj];
		if (typeof value == 'object') {
			if (objeto instanceof Array) {
				break;
			}
			objeto = objetoJSON(value);
		}
	}
	return objeto;
}

já foi implementado o suporte a collections, sem precisar de wrappers…

não foi lançado ainda, então pra pegar essa versão vc precisa baixar do repositorio: http://github.com/caelum/vraptor e dar um ant na pasta vraptor-core…

inclusive, dá pra você configurar o XStream para não incluir o elemento externo, daí vc não precisa desse javascript. Crie a classe:

@Component
public class MeuJSONSerialization extends XStreamJSONSerialization {
   //delegate constructor
   @Override
   protected HierarchicalStreamDriver getHierarchicalStreamDriver() {
       return new JsonHierarchicalStreamDriver() {
            public HierarchicalStreamWriter createWriter(Writer writer) {
                  return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
            }
       });
   }
}

aí se vc serializa a lista de strings “aaa”, “bbb” por exemplo:

{"list": ["aaa", "bbb"] }

vira

["aaa", "bbb"]

[]'s

Lucas, fiz os testes aqui com essa versão e está funcionando 100%. :slight_smile:

Sobre não usar o root element, será que dá para incluir isso assim?

result.include("usuario", usuario); result.use(json()).exclude("usuario.roles").withDropRoot();

o certo seria:

result.use(json()).from(usuario)...

o complicado de fazer isso eh que essa configuração de droproot é feita na criação do XStream…
e o XStream eh criado antes do começo da serialização =(

mas vc pode criar um cara que estende XStreamJSONSerialization, configura o dropRoot nele, e usa essa classe quando vc quiser o json sem o root…

Lucas, foi erro meu no copy-and-past, hehehehe.

Hmm, beleza então, vou usar da forma que você falou. Abraços

Já foi disponibilizado o jar que auxilia com json, que não é necessário criar a classe wrapper?

Vi que o lucas disse:

Mais eu não faço idéia de como fazer isso.

[quote=davisnog]Já foi disponibilizado o jar que auxilia com json, que não é necessário criar a classe wrapper?

Vi que o lucas disse:

Mais eu não faço idéia de como fazer isso.[/quote]

Voce precisa instalar github neste link mostra como fazer isso:
http://help.github.com/

Depois de instalar vai ate console:
git clone git://github.com/caelum/vraptor.git

Depois e so rodar ant na pasta raiz vraptor no console:
ant
Sera gerado dentro da pasta vraptor-core/target
vraptor-3.0.3-SNAPSHOT.jar

Ok.

Se você tiver com problemas me passa uma MP com teu email que eu posso te mandar o jar compilado.

Abraços

[quote=garcia-jj]Se você tiver com problemas me passa uma MP com teu email que eu posso te mandar o jar compilado.

Abraços[/quote]

davisnog, jar enviado. Qualquer coisa responde aqui no tópico.

Abraços

obrigado garcia-jj, implementei a classe para retirar o elemento externo e deu tudo certo.

Valeu mesmo.

opa, quase tudo certo, estou tentando pegar o objeto json com o jquery, mais sempre aparece um arquivo pra download com os dados.

Minha tela é uma modal, para pesquisa de dados.

Meu metodo de pesquisa no controller:

[code]@Post
@Get
@Path("/cooperado.pesquisar")
public void pesquisar(Cooperado cooperado){
List cooperados = this.service.pesquisar(cooperado);

	this.json.from(cooperados).serialize();
}[/code]

E no jsp tem o codigo js:

[code]
$(function() {

		$.getJSON("<c:url value='/cooperado.pesquisar' />",  
			function(data){  
					alert('it worked!');  
			});  
		
	});
</script>[/code]

E da mesma forma esta me trazendo um arquivo pro download.

O que eu quero fazer, é pegar esses dados e preencher numa tabela.

esse this.json veio de onde? vc precisa fazer result.use(Results.json()) pra funcionar…

se vc acessar a essa lógica diretamente vai aparecer uma caixa pra download, pq por padrão o firefox/IE tratam o tipo application/json como download…

o jeito de usar no jquery é:

var json = $.getJSON("....");
//acessa o json e faz a sua lógica

this.json é essa é a implementação da classe que tira o root do json.

Lucas, eu fiz como você falou:

Mais ainda assim continua aparecendo o arquivo para download.

Fiz um teste usando esse arquivo, numa pagina em html puro e funcionou.

Só uma pergunta todas as actions tem que ter um result?

Somente com this.json, esta dando um erro:

[quote]SEVERE: Servlet.service() for servlet default threw exception
java.lang.IllegalStateException: Cannot forward after response has been committed
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:313)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:301)
at br.com.caelum.vraptor.view.DefaultPageResult.forward(DefaultPageResult.java:72)
at br.com.caelum.vraptor.extra.ForwardToDefaultViewInterceptor.intercept(ForwardToDefaultViewInterceptor.java:49)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.interceptor.OutjectResult.intercept(OutjectResult.java:56)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:67)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:77)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:42)
at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.util.hibernate.HibernateTransactionInterceptor.intercept(HibernateTransactionInterceptor.java:45)
at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:873)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Unknown Source)
[/quote]

vc fez o result.use(json())?

a tela pra download acontece na chamada Ajax?

davisnog, se você tentar acessar direto o URL do seu json certamente o browser irá pedir para fazer download. Não sei se há uma configuração no browser que evite isso, porém é o padrão ser assim.

Se você usa Linux você pode fazer um wget no URL, aí você pode ver o conteúdo, ou então baixar o arquivo e abrir em um editor de texto. Outra opção é o add-on Firebug para o Firefox, que permite fazer um debug nas requisições ajax.

Altere seu código do Javascript alterado o alert(‘it worked’) para alert(data), assim ele imprime a resposta no alert.

Abraços

davisnog, também achei estranho o this.json. O que é esse json? É de que tipo?

http://vraptor.caelum.com.br/documentacao/view-e-ajax/