VRaptor 3 + JSON

77 respostas
J

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: Its 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: Its 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

77 Respostas

Mikhas

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.

G

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

Para isso faça algo como:

public class MyCollectionWrapper {
    final Collection<TbTabelaA> lista;

    [...]
}

E no seu controller:

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

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

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

Para isso faça algo como:

public class MyCollectionWrapper {
    final Collection<TbTabelaA> lista;

    [...]
}

E no seu controller:

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

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;
}
Lucas_Cavalcanti

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

G

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();

Lucas_Cavalcanti

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…

G

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

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

D

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.

J

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.

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.

G

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

Abraços

G

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

Abraços

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

Abraços

D

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

Valeu mesmo.

D

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:

@Post
	@Get
	@Path("/cooperado.pesquisar")
	public void pesquisar(Cooperado cooperado){
		List<Cooperado> cooperados = this.service.pesquisar(cooperado);
		
		this.json.from(cooperados).serialize();
	}

E no jsp tem o codigo js:

<script type="text/javascript">
		$(function() {
	
			$.getJSON("<c:url value='/cooperado.pesquisar' />",  
				function(data){  
						alert('it worked!');  
				});  
			
		});
	</script>
E da mesma forma esta me trazendo um arquivo pro download.

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

Lucas_Cavalcanti

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
D

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:

<blockquote>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)

</blockquote>
Lucas_Cavalcanti

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

a tela pra download acontece na chamada Ajax?

G

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

G

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

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

Lucas_Cavalcanti

a classe de json sua estende XStreamJSONSerialization?

se sim, basta anotá-la… e usar result.use(Results.json()).from(objeto)…serialize();

G

Se você usou a implementação que o lucas te indicou no inicio do topico, você não precisa injetar ela dentro de sua classe. Pelo que entendi foi isso que você fez, não?

O correto seria apenas colocar seu componente em algum lugar que o vraptor possa fazer scan, e no seu controller escrever normalmente conforme o padrão do vraptor que é ± assim:

public class MeuController { public void metodo() { result.use(Results.json()).from(objeto).serialize(); } }

Abraços

D

Lucas eu usei result.use(json()), mais dessa forma ele esta mandando “list” também, e como vc colocou no inicio do tópico eu criei a classe que tira o “list” do objeto json. E minha classe não extende XStreamJSONSerialization.

Garcia, isso mesmo o this.json é minha classe injetada no meu controller. Agora onde iria colocar minha classe para fazer o que vc colocou, “o vraptor fazer o scan”.

Essa página, ela é de pesquisa. Com os campos para filtros e uma tabela, no meu metodo do controller pesquisar, ele esta anotado como @Get e @Post, dessa forma eu utilizo o mesmo método para trazer a lista completa no primeiro acesso, daí caso o usuário queira refinar os dados ele informa os filtros necessários.

Então Lucas, logo no carregamento da página me aparece o arquivo para donwload, eu necessariamente nem preciso chamar o método do meu controller via requisição ajax.
No meu controller o método esta assim:

@Post
	@Get
	@Path("/cooperado.pesquisar")
	public void pesquisar(Cooperado cooperado){
		List<Cooperado> cooperados = this.service.pesquisar(cooperado);
		
		this.json.from(cooperados).serialize(); //dessa forma acontece o erro  informado - Cannot forward after response has been committed 
                //result.use(Results.json()).from(cooperados).serialize();  // assim o objeto json vem com root "list"
           //nas duas formas aparecem o arquivo para download.

	}
Lucas_Cavalcanti

faça essa classe de JSON que vc fez implementar JSONSerialization:

@Component
public class MinhaClasseQueFazJSON implements JSONSerialization {

....
}

assim ela vai ser usada no result.use(json())

[]'s

D

Minha classe esta assim:

import java.io.Writer;

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.XStreamJSONSerialization;

import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
import com.thoughtworks.xstream.io.json.JsonWriter;

@Component
public class CustomJSONSerialization extends XStreamJSONSerialization {

	public CustomJSONSerialization(HttpServletResponse response,
			TypeNameExtractor extractor) {
		super(response, extractor);
		// TODO Auto-generated constructor stub
	}

	@Override
	   protected HierarchicalStreamDriver getHierarchicalStreamDriver() {
	       return new JsonHierarchicalStreamDriver() {
	            public HierarchicalStreamWriter createWriter(Writer writer) {
	                  return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
	            }
	       };
	   }
}
No caso de implementar a interface JSONSerialization, como ficaria as implementações dos metodos abaixo?
@Override
	public boolean accepts(String arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public <T> Serializer from(T arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public <T> Serializer from(T arg0, String arg1) {
		// TODO Auto-generated method stub
		return null;
	}

A classe CustomJSONSerialization seria o que eu estou utilizando em this.json.

Lucas_Cavalcanti

davisnog:
Minha classe esta assim:

import java.io.Writer;

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.XStreamJSONSerialization;

import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
import com.thoughtworks.xstream.io.json.JsonWriter;

@Component
public class CustomJSONSerialization extends XStreamJSONSerialization {

	public CustomJSONSerialization(HttpServletResponse response,
			TypeNameExtractor extractor) {
		super(response, extractor);
		// TODO Auto-generated constructor stub
	}

	@Override
	   protected HierarchicalStreamDriver getHierarchicalStreamDriver() {
	       return new JsonHierarchicalStreamDriver() {
	            public HierarchicalStreamWriter createWriter(Writer writer) {
	                  return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
	            }
	       };
	   }
}


se sua classe já está assim, vc não precisa implementar aquela interface… result.use(json()) deveria usar a sua implementação…

faz o seguinte, em algum ponto de sua lógica:

System.out.println(this.json == result.use(json()));
System.out.println(this.json.getClass() == result.use(json()).getClass());

tem que imprimir true nos dois casos, ou pelo menos no segundo.

se imprimir true, vc pode tirar o this.json da sua classe e usar o result.use(json()) no lugar. Vai funcionar direito

D

Lucas, imprimiu no console, true, true.

Agora como eu faço para consumir esse objeto?

Tenho no meu jsp esse codigo, mais não chega a dar um alert no json. Continua aparecendo o arquivo pra download.
<script type="text/javascript">
		$(function() {
		      var json = $.getJSON("<c:url value='/cooperado.pesquisar' />");

			alert(json); 
		});
	</script>
Lucas_Cavalcanti
troca o

this.json.from(object).serialize()

para

result.use(json()).from(object).serialize()
D

isso eu ja fiz.

Lucas_Cavalcanti

em que arquivo está esse código?

<script type="text/javascript">
		$(function() {
		      var json = $.getJSON("<c:url value='/cooperado.pesquisar' />");

			alert(json); 
		});
	</script>
D

no pesquisar.jsp, o engraçado é o seguinte.

Esse jsp é uma tela de pesquisa em determinada situação e uma modal em outra situação, então eu tenho o mesmo jsp usando em dois lugar com a mesma finalidade.

Na tela onde eu utilizo esse jsp como modal o alert(json) aparece XMLHttpRequest, sendo assim eu consigo utilizar o objeto.
Já na situação em que esse jsp é uma tela normal de pesquisa, me aparece o arquivo pra download.

Lucas_Cavalcanti

então o problema é o seguinte: se vc quer produzir json, vc não deve ter o jsp… ele nem chega a chamar o jsp…

a solução fácil pra isso é criar duas lógicas, uma que gera html (com jsp) e uma que gera o json

D

hum, entendi, vou testar aqui.

G

lucascs:
então o problema é o seguinte: se vc quer produzir json, vc não deve ter o jsp… ele nem chega a chamar o jsp…

a solução fácil pra isso é criar duas lógicas, uma que gera html (com jsp) e uma que gera o json

Nesse caso ele não pode usar o representation? Assim dependendo do accept ele faz jsp ou json.

D

representation? o que seria?

Lucas_Cavalcanti

o representation não foi lançado ainda… vai estar no 3.0.3…

o representation funciona assim: vc faz

result.use(Results.representation()).from(objeto).serialize();

se vier o parâmetro _format=json na requisição, a resposta vai ser um json do objeto.
se vier o _format=xml, vai gerar um xml do objeto
se não vier nada ele vai pra jsp padrão (com o objeto adicionado, eu acho)

assim vc não precisa de duas lógicas… basta passar o parametro _format=json no $.getJSON(…)

se quiser o SNAPSHOT-3.0.3 pra usar isso:
http://www.linux.ime.usp.br/~lucascs/vraptor-3.0.3-SNAPSHOT.jar

[]'s

D

opa, tudo certo, até agora.

Valeu mesmo.

Essa versão do vraptor eu já estava usando, o Garcia tinha me mandado por email, mais de qualquer forma obrigado.

G

Representation leva em questão apenas o _format ou também os headers? No caso se meu accept for json ele considera?

lucascs:
o representation não foi lançado ainda… vai estar no 3.0.3…

o representation funciona assim: vc faz

result.use(Results.representation()).from(objeto).serialize();

se vier o parâmetro _format=json na requisição, a resposta vai ser um json do objeto.
se vier o _format=xml, vai gerar um xml do objeto
se não vier nada ele vai pra jsp padrão (com o objeto adicionado, eu acho)

assim vc não precisa de duas lógicas… basta passar o parametro _format=json no $.getJSON(…)

se quiser o SNAPSHOT-3.0.3 pra usar isso:
http://www.linux.ime.usp.br/~lucascs/vraptor-3.0.3-SNAPSHOT.jar

[]'s

Lucas_Cavalcanti

leva em questão os headers tb… (o Accept)

mas via javascript é um pouco mais difícil setar headers, então usar o _format é mais prático

D

Como eu estou usando o jquery ui Dialog para fazer a modal, no submit da modal para fazer a pesquisa, esta sendo redirecionado para a página pesquisar.jsp.

Tem alguma forma de fazer o submit sem que saia da modal?
Ou vocês tem alguma outra sugestão de plugin para modal.

Lucas_Cavalcanti

pra fazer isso funcionar, vc pode usar o plugin do ajax Form http://jquery.malsup.com/form/
que envia a requisição via ajax… com o resultado, vc pode atualizar alguma div ou coisa do tipo dentro do modal

D

eu tentei utilizar esse plugin, mais como a modal é carregada dinamicamente, não consigo pegar o form. O codigo javascript esta abaixo:

$(function() {

		var options = { 
		        target:        '#resultado',   
		        beforeSubmit:  showRequest   
		};

		$("#btnCooperado").click(function(){
				$("#modalCooperados").dialog('open');
				$("#modalCooperados").load("<c:url value='/cooperado.pesquisar' />");				
			}
		);

		$("#btnFechar").click(function(){
			$('#modalCooperados').dialog('close');
		});
				
		$("#modalCooperados").dialog({
			bgiframe: true,
			autoOpen: false,
			height: 500,
			width: 600,
			modal: true
		});

	    $('#pesquisarForm').submit(function() { 
	        $(this).ajaxSubmit(options); 
	        return false; 
	    }); 
		
	});

	function showRequest(formData, jqForm, options) { 
	    var queryString = $.param(formData); 
	    return true; 
	}

Ainda assim, é feito o post para a pagina de pesquisa.

Lucas_Cavalcanti

dá uma olhada nas options desse plugin…

acho que dá pra vc criar um modal sem botão, colocar no html do texto o form de pesquisar, com o id certo
e transformar ele em um ajax form

D

pelo que eu percebi o jquery não esta conseguindo achar os elementos DOM dessa página que é carregada via metodo load.

Nessa pagina carregada, não consigo manipular nada via jquery, se eu colocar um evento direto no botão de pesquisar dai eu consigo fazer alguma coisa.

Lucas_Cavalcanti

dá uma olhada no html que o modal gera… às vezes ele muda o id das coisas, e dá pau

D

Agora se eu colocar um include desse arquivo dentro da div modal, o jquery acha os elementos da pagina, mais dai por algum motivo que eu não sei o qual, debugando eu vi que ele passa duas vezes no metodo do controller que traz os dados da tabela, mais quando a modal abre não aparece os dados na tabela.

Lucas_Cavalcanti

vc precisa pegar o div do modal, e colocar os dados lah dentro

D

pelo firebug olhei o html gerado os ids continuam o mesmo, dei um alert no $("#form").name e esta indefined, se der um alert em $("#form"), aparece Object, tem como saber que objeto é esse?

Lucas_Cavalcanti

não existe $("#form").name mesmo…

com o jquery o jeito de acessar atributos é diferente:
$("#form").attr(“name”)…

o que vc quer fazer?

D

como eu utilizei o load para carregar os dados na modal, queria saber o que tem dentro da div modal.

D

sobre colocar os dados dentro da div, o load faz isso né?

Lucas_Cavalcanti

acho que é só passar o id da div: “#idDaDiv

D
$("#btnCooperado").click(function(){
				$("#modalCooperados").dialog('open');
				$("#modalCooperados").load("<c:url value='/cooperado.modal' />");
									
				$("#modalCooperados").each(function(i, val){

					alert(val);
				});				
			}
		);

Com esse codigo apartir de um button eu abro a modal, na onde tem o alert me aparece [object HTMLDivElement], mais só isso.

Mais ainda não consegui pegar nenhum elemento da pagina adicionada.

Lucas_Cavalcanti

dá uma olhada no plugin de dialog, se não tem nenhum jeito melhor de fazer isso…

depois que o div foi carregado, suponha que existe um elemento qqer com id=“abc”…

vc consegue acessar ele via $(’#abc’)

D

fiz um teste num html puro usando o exemplo do que esta no site do jquery [url]http://jqueryui.com/demos/dialog/#modal-form[/url], e deu certo.

Na pagina carregada, eu coloquei o codigo abaixo, e nada, parece que nem foi carregada, será porque ela é carregada dinamicamente?

$(function(){

			alert("CARREGOU...");

		});
D

se eu acesso a pagina de pesquisa diretamente na url do browser o alert(“CARREGOU…”); executa, já na modal não.

Lucas_Cavalcanti

qdo vc carrega via load ele não executa os javascripts da página carregada

D

tem alguma sugestão para carregar essa pagina?

Lucas_Cavalcanti

tenta inverter:

$("#modalCooperados").load("<c:url value='/cooperado.modal' />");  
$("#modalCooperados").dialog('open');

deveria aparecer algo… senão tenta algo diferente de modal

D

mesmo invertendo a ordem não deu certo, o estranho é que somente o javascript do jquery que não funciona:

<script type="text/javascript">

		$(function(){

			alert("CARREGOU..."); // isso não funciona

		});

		alert("SEM JQUERY CARREGOU..."); // isso funciona
	
</script>
G

Se $(function() não funcionou é porque o jquery não está sendo carregado. Tente colocar um alert($). Se retornar null ou undefined é porque realmente o jquery não está sendo carregado. Verifique se você tem o arquivo no local que você está importando.

D

uma forma que eu resolvi, foi usando o metodo de callback open do dialog ui.

Dessa forma eu tenho um include na div container do dialog, e no metodo open eu chamo a function que carrega os dados da tabela.

Tudo certo até aqui, estou usando tambem o plugin Jquery Form, pra fazer chamadas ajax a partir de um formulário já que essa modal é de pesquisa. Se eu chamar a página de pesquisa através da url funciona tudo certo, mais na modal esta dando o erro abaixo:


Erro Status 405
14/12/2009 10:57:05 br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor intercept
INFO: Method POST is not allowed for requested URI. Allowed Methods are [GET]

Lucas_Cavalcanti

o javascript:

$(function() {
   // o que está aqui executa no onLoad do body
   // qdo vc faz requisições ajax, esse evento não é disparado, logo o código
   // que está aqui dentro não roda.
});

o que vc pode fazer, é colocar uma função init() e executá-la na mão.

[]'s

D

mais ai fica a pergunta, porque quando eu chamo a pagina de pesquisa pela url funciona normal, agora quando a modal chama essa pagina não funciona?

Lucas_Cavalcanti

sim, é isso mesmo…

não funciona com requisições ajax, pq ele não dispara o evento onLoad…

qdo vc acessa diretamente dispara o onload e funciona normal

D

hum, entendi…

D

Tem um exemplo de como eu poderia estar fazendo funçaõ init, já tentei assim e não deu certo:

function init(){

  $(function(){
    //meu codigo aqui
  });

}
D

Resolvido.

Um colega meu vendo o codigo fonte do jquery viu que a function que retornava o prototype do jquery tinha um var que limitava o escopo das variaveis (no arquivo min, eh a primeira function), ele retirou o var das variaveis e tudo funcionou.

Agora não sei se isso é um bug, mais sei que esta funcionando agora.

Lucas_Cavalcanti

O código $(function() {…}) não deve estar dentro da função init, e sim direto dentro de uma tag ou dentro de um arquivo .js importado

D

Pois é, eu tinha dito que estava resolvido, mais não esta não.

Tem alguma forma de forçar o onload ou algum evento que tenha o mesmo efeito dentro de uma div?

Lucas_Cavalcanti

tenta fazer o seguinte: ao inves de usar o load, usa o get, que está nessa página de doc:

http://docs.jquery.com/Ajax/jQuery.get#urldatacallbacktype

seria algo do tipo:

$.get('caminho/da/pagina', {}, function(data) {
  $("#idDaDiv").html(data);
}, "html");

o último parâmetro é o tipo, tente variar ele para todos os que estão na documentação… um dos tipos, se eu não me engano, executa os eventos do cara carregado

[]'s

D

como esses dados estão sendo carregados dinamicamente, a página que o jquery adiciona ao meu jsp modal, tanto usando o metodo load quanto o get, nenhuma das duas opções dão certo. Pois a pagina adicionada na modal, dentro de $(function(){…}), nem um alert functiona.

não funciona com requisições ajax, pq ele não dispara o evento onLoad…

qdo vc acessa diretamente dispara o onload e funciona normal

Lucas vc já tinha dito que isso era porque o quando adicionado na modal não é executado o evento onload.

Tem alguma forma de fazer forçar o onload ou mesmo fazer algo semelhante?

Lucas_Cavalcanti

depende do plugin do JQuery que vc tah usando… se o plugin tem essa opção, vc usa… senão vc tem que chamar os javascripts na mão…
tenta fazer o seguinte:

function init() { //onde estava $(function(){
    //inicialização
}

init();

dentro da página carregada… aí vc testa as opções e vê se alguma executa o init

D

resolvi criando um iframe e esse iframe tem a uri que vai ser chamado no controller.

wolmirGarbin

Me diz uma coisa, vc importou a biblioteca do jQuery na pagina que esta chamando via load?
Veja o exe:

pagina.html

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>ExtJS Layout Examples</title>


    <script type="text/javascript" src="jquery-1.3.1.min.js"></script>

	<script type="text/javascript">
		$(document).ready(function(){
			$('#start').load('ler.html');
		})
	</script>
</head>
<body>
    <div id="header"><h1>Load</h1></div>
	
        <div id="start" style="border:1px solid #000000; height:200px; width:200px;">
           	
        </div>

</body>
</html>

ler.html

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>ExtJS Layout Examples</title>

	<script type="text/javascript">
	
	$(document).ready(function(){
		alert('Teste');
	});
	
	</script>
</head>
<body>
	123
</body>
</html>

veja que não foi importado o jQuery na outra pagina…

Wolmir Garbin

tefo

eai galera!

estou tentando fazer uma requisição ajax mas não estou conseguindo..

abaixo o que estou usando para a requisição:

libs:
- jackson-core-asl-1.5.5.jar
- jackson-jaxrs-1.5.5.jar
- jackson-mapper-asl-1.55.jar
- jackson-xc-1.5.5.jar
- asm-3.1.jar
- jersey-core-1.4.jar
- jersey-json-1.4.jar
- jersey-server-1.4.jar
- jsr311-api-1.1.1.jar

web.xml:
...
&lt;servlet&gt;
&lt;servlet-name&gt;Jersey REST Service&lt;/servlet-name&gt;
&lt;servlet-class&gt;com.sun.jersey.spi.container.servlet.ServletContainer&lt;/servlet-class&gt;
&lt;init-param&gt;
&lt;param-name&gt;com.sun.jersey.config.property.packages&lt;/param-name&gt;
&lt;param-value&gt;br.com.website.resources&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;Jersey REST Service&lt;/servlet-name&gt;
&lt;url-pattern&gt;/rest/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
...
bean:
package br.com.website.beans;

@Entity
@XmlRootElement
public class Estado implements Serializable {
...
}
resource:
package br.com.website.resources;

@Path("/estado")
public class EstadoResource {

@Get @Path("/list/{idPais}")
@Produces(MediaType.APPLICATION_JSON)
public String getListaEstados(@PathParam("idPais") Integer idPais) throws Exception {

ObjectMapper mapper = new ObjectMapper();
String response = "";

/* valores de teste */
Long paisId = Long.parseLong(idPais.toString());

Pais pais = new Pais();
pais.setId(paisId);
pais.setNome("Brasil");
pais.setSigla("BR");

Estado estado = new Estado();
estado.setId(1L);
estado.setNome("Alagoas");
estado.setSigla("AL");
estado.setPais(pais);

List&lt;Estado&gt; lsEstado = new ArrayList&lt;Estado&gt;();
lsEstado.add(estado);

response = mapper.writeValueAsString(lsEstado);

return response;
}
}
retorno do método getListaEstados:
[{"id":1,"nome":"Alagoas","sigla":"AL","pais":{"id":1,"nome":"Brasil","sigla":"BR"}}]
requisição ajax:
getJSON = function(url, data, dt, bs, s, e){
$.ajax({
type:"get",
url:url,
data:data,
dataType:dt,
beforeSend:bs,
success:s,
error:e
});
});

getJSON(
'/website/rest/estado/list/1',
null,
"json",
function(xhr, settings){},
function(data, textStatus, xhr){},
function(xhr, textStatus, errorThrown){}
);

O que acontece é o seguinte:
- em outro projeto meu tudo isto funciona perfeitamente (neste projeto não uso vRaptor).
- neste projeto 'website' tudo funciona até o momento de retornar os dados para o browser (neste projeto estou usando vRaptor).
- a requisição ajax é executada e, no EstadoResource, o método getListaEstados(idPais) recebe o parametro idPais, os dados são setados para uma lista de Estado, a lista é convertida em String e essa String deveria ser retornada ao browser... ...mas não é!
- ao receber o retorno no browser temos o seguinte: "HTTP Status 405 - Method Not Allowed" "description - The specified HTTP method is not allowed for the requested resource (Method Not Allowed)."

Alguém já teve este problema?

tefo

Em minha última tentativa desesperada de fazer funcionar minha aplicação antes tentar de dormir, encontrei a solução para este problema que já estava me dando insônia:

no resourse EstadoResource.java apenas troquei o import da anotação @Get de br.com.caelum.vraptor.Get para javax.ws.rs.GET e funcionou!

agora posso dormir feliz… hauhauhauahah

Lucas_Cavalcanti

colocar o @GET do jax-rs é a mesma coisa que deixar sem anotação :wink:

alguem estava mandando POST nesse método, ou qqer outro diferente de GET, por isso o erro.

Criado 23 de novembro de 2009
Ultima resposta 23 de jul. de 2012
Respostas 77
Participantes 7