VRaptor3 + Converter = Comportamento estranho

16 respostas
S

Oi pessoal, tenho um converter pra List<Jsonable> que me retorna uma lista na primeira posição de outra lista, pegando a posição 0 da primeira lista e fazendo um cast para o List<Jsonable> funciona, mas eu queria deixar funcionando certinho sem esta “gambiarra”…

Segue códigos:

JsonableConverter
Este Converter retorna sempre uma lista de Jsonable independente se ele esta recebendo um json ou um array de json…

@Convert(Jsonable.class)  
public class JsonableConverter implements Converter&lt;List&gt;&lt;Jsonable&gt;&gt; {
	public List&lt;Jsonable&gt; convert(String value, Class&lt;? extends List&lt;Jsonable&gt;&gt; type, ResourceBundle arg2) {
		ArrayList&lt;Jsonable&gt; list = new ArrayList&lt;Jsonable&gt;();
		   
		   if (value.substring(0, 2).equals("[{")){
			   JSONArray arrayJson;
			   try {
				   arrayJson = new JSONArray(value);
				   for (int i = 0; i &lt; arrayJson.length(); i++) {
					   String json = "{\"data\":"+ arrayJson.getJSONObject(i).toString() +"}";
					   addJsonable(list, json, type);
				   }
			   } catch (JSONException e) {
				   // TODO Auto-generated catch block
				   e.printStackTrace();
			   }
			   
		   }else{
			   String json = "{\"data\":"+ value +"}";
			   addJsonable(list, json, type);
		   }
		   return list;
	}
	
	@SuppressWarnings("rawtypes") 
	private void addJsonable(List&lt;Jsonable&gt; list, String json, Class type){
		XStream xstream = new XStream(new JettisonMappedXmlDriver());
		xstream.alias("data", type);
		list.add((Jsonable) xstream.fromXML(json));
	}
}

LoginConverter
Obs: o objeto usuarios deveria conter um lista de usuario, porém, ele vem apenas com um item, na posição 0, que este sim é uma lista de usuario, do jeito que esta aqui funciona…

@Path("/login/autenticar")
	public void autenticar(List&lt;Usuario&gt; usuario, boolean forcar){
		try {
			List&lt;Usuario&gt; al = (List&lt;Usuario&gt;) usuario.get(0);
			this.loginService.autenticar(al.get(0), forcar);
			result.use(ExtJSJson.class).from("ok").success(true).serialize();
		} catch (ExceptionLogin e) {
			String retorno = "{controleInterno:true, msg:'"+e.getMessage()+"', status:"+String.valueOf(e.getEstado())+"}";
			result.use(ExtJSJson.class).from(retorno).success(false).serialize();
		}
	}

Valeu pessoal Obrigado.

16 Respostas

Lucas_Cavalcanti

o vraptor tem um @Consumes(“application/json”) pra vc fazer isso…

daí vc teria que passar como corpo da requisição um json, e não form parameters.

se quiser fazer fazer o seu exemplo funcionar, teria que ter um parâmetro da requisição chamado usuarios, com o json:

usuarios={"nome": "jao", "email": "jao@sadf"}

e o @Convert de veria ser de List.class, não de Jsonable.

S

Da forma que esta descrito acima esta funcionando, o problema é que o list que eu quero vem na primeira posição do list que recebo no controler…

Tentei testar apenas mudando o @Converter para List.Class mas esta dando um erro:

HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

br.com.caelum.vraptor.VRaptorException: Unable to find converter for br.com.aberta.tzion.entity.Usuario
	br.com.caelum.vraptor.core.DefaultConverters.to(DefaultConverters.java:59)
	br.com.caelum.vraptor.http.ognl.VRaptorConvertersAdapter.convert(VRaptorConvertersAdapter.java:59)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.convert(OgnlParametersProvider.java:178)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createList(OgnlParametersProvider.java:185)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createSimpleParameter(OgnlParametersProvider.java:172)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createRoot(OgnlParametersProvider.java:144)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createParameter(OgnlParametersProvider.java:122)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.getParametersFor(OgnlParametersProvider.java:85)
	br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.getParametersFor(ParametersInstantiatorInterceptor.java:105)
	br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:77)
	br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:59)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:48)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:83)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:71)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.core.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:44)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:58)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)
HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

br.com.caelum.vraptor.VRaptorException: Unable to find converter for br.com.aberta.tzion.entity.Usuario
	br.com.caelum.vraptor.core.DefaultConverters.to(DefaultConverters.java:59)
	br.com.caelum.vraptor.http.ognl.VRaptorConvertersAdapter.convert(VRaptorConvertersAdapter.java:59)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.convert(OgnlParametersProvider.java:178)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createList(OgnlParametersProvider.java:185)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createSimpleParameter(OgnlParametersProvider.java:172)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createRoot(OgnlParametersProvider.java:144)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.createParameter(OgnlParametersProvider.java:122)
	br.com.caelum.vraptor.http.ognl.OgnlParametersProvider.getParametersFor(OgnlParametersProvider.java:85)
	br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.getParametersFor(ParametersInstantiatorInterceptor.java:105)
	br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:77)
	br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:59)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:48)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:83)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:71)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.core.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:44)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:58)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)

note The full stack trace of the root cause is available in the Apache Tomcat/7.0.20 logs.
Apache Tomcat/7.0.20

Tentei mudar tudo pra List tbm mas deu um outro erro, e eu acho que por este caminho fica dificil uma vez que não terei o type(Class) correto pra converter no xstream.alias("data", type);

Lucas_Cavalcanti

o problema é que o VRaptor trata listas de um jeito diferente…

qdo vc colocou Jsonable no @Convert ele chegou a executar o converter?

S

sim, com o converter citado na primeira msg funciona, o “problema” que recebo uma lista dentro de lista, da uma olha no controler que vc vai entender certinho…

S

Notar que eu alterei o Controler na primeira msg…

Lucas_Cavalcanti

sim, pq qdo vc passa usuarios=[…] na requisição, ele popula um usuario, e não a lista inteira…

isso pq vc pode passar varias vezes:

usuarios=blah
usuarios=bleh
usuarios=blih

e cada um seria um dos elementos da lista.

vc não consegue usar o @Consumes?

S

???
Pra mim tanto faz ele passar um único usuario ou um array de usuario eu trato isto no converter pra sempre me retornar um List…

Não entendi muito bem a sua msg…

Lucas Cavalcanti:
sim, pq qdo vc passa usuarios=[…] na requisição, ele popula um usuario, e não a lista inteira…

isso pq vc pode passar varias vezes:

usuarios=blah
usuarios=bleh
usuarios=blih

e cada um seria um dos elementos da lista.

vc não consegue usar o @Consumes?

Lucas_Cavalcanti

o que eu falei é justificando o fato de ele fazer uma lista com uma lista dentro…

vc ainda não respondeu do @Consumes :wink:

como vc tá fazendo a requisição?

S

Não sabia que tinha o @Costumes procurei no pdf do Vraptor e não falava sobre, procurando sobre ele na net vi tbm um @Deserializes, vc sabe me passar algum lugar que ache documentação deles?

Quanto a requisição vão assim:

Request URL:http://localhost:8080/tzion/login/autenticar
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Content-Length:72
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Cookie:JSESSIONID=E5E0FADB1AE5B75ECD3E6A507CEAE0E1
Host:localhost:8080
Origin:http://localhost:8080
Referer:http://localhost:8080/tzion/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11
X-Requested-With:XMLHttpRequest
Form Dataview URL encoded
usuario:{"email":"f","senha":"f"}
forcar:false
Response Headersview source
Date:Thu, 05 Jul 2012 13:28:37 GMT
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
Request URL:http://localhost:8080/tzion/usuario/incluir?_dc=1341494432413
Request Method:POST
Status Code:500 Internal Server Error
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Content-Length:131
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Cookie:JSESSIONID=E5E0FADB1AE5B75ECD3E6A507CEAE0E1
Host:localhost:8080
Origin:http://localhost:8080
Referer:http://localhost:8080/tzion/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11
X-Requested-With:XMLHttpRequest
Query String Parametersview URL encoded
_dc:1341494432413
Form Dataview URL encoded
usuario:{"codigo":0,"usuario":"l","email":"l","senha":"l","permissao":""}
Response Headersview source
Connection:close
Content-Length:7128
Content-Type:text/html;charset=utf-8
Date:Thu, 05 Jul 2012 13:20:32 GMT
Server:Apache-Coyote/1.1
Request URL:http://localhost:8080/tzion/usuario/procurar?_dc=1341494761693
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Content-Length:158
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Cookie:JSESSIONID=E5E0FADB1AE5B75ECD3E6A507CEAE0E1
Host:localhost:8080
Origin:http://localhost:8080
Referer:http://localhost:8080/tzion/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11
X-Requested-With:XMLHttpRequest
Query String Parametersview URL encoded
_dc:1341494761693
Form Dataview URL encoded
listaFiltrosProcura:[{"campo":"codigo","tipo":"integer","operador":"&gt;","valor":0}]
page:1
start:0
limit:25
Response Headersview source
Date:Thu, 05 Jul 2012 13:26:01 GMT
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked

Valeu obrigado.

Lucas_Cavalcanti

dúvida: pq vc não está enviando os dados como form parameters mesmo?

algum motivo específico pra vc transformar os dados em json e enviar?

o consumes só funciona se o corpo da request for um json, não vai funcionar se for um form parameter com um json.

Infelizmente as docs sobre isso são apenas o javadoc http://vraptor.caelum.com.br/javadoc/ e os testes dos deserializers…

S

Na verdade tenho um objeto no ExtJS(proxy) que faz isto pra mim, esta camada fica transparente…

Lucas_Cavalcanti

A sua solução do JsonableConverter funciona pra tudo, menos pra List<> certo?

nesse caso, vc pode fazer um ajuste :wink:

  • sobrescreva o parametersProvider:
@Component
public class JsonableParametersProvider implements ParametersProvider {
   public JsonableParametersProvider(ParametersProvider delegate) {
           this.delegate = delegate;
   }

   public Object[] getParametersFor(ResourceMethod method, List<Message> errors, ResourceBundle bundle) {
          Object[] parameters = delegate.getParametersFor(method, errors, bundle);
           for(int i = 0; i < parameters.length; i++) {
                if(parameters[i] instanceof List<? extends Jsonable> 
                   && !parameters[i].isEmpty()
                   && parameters[i].get(0) instanceof List<? extends Jsonable>) {
                     parameters[i] = ((List)parameters[i]).get(0);
                 }
           }
           return parameters;
    }
}

ou algo do tipo =)

S

O converter aceita List<> tbm, na verdade ele sempre retorna um List<? extends Jsonable>, mesmo que o View tenha mandado um json, trato antes pra ver se é um json, um array de json, ou um array vazio e transformo para um List...

fiz umas alterações porque o java não aceitava o
if(parameters[i] instanceof List&lt;? extends Jsonable&gt;)
, ficou perfeito... Não sabia que existia esta interface ParametersProvider, cada dia me surpreendo mais com o VRaptor parabéns... Deveria ter uma documentação sobre estas "características do VRaptor", são super importantes e valiosas
@Component  
public class JsonableParametersProvider implements ParametersProvider {  
   private ParametersProvider delegate;

   public JsonableParametersProvider(ParametersProvider delegate) {  
           this.delegate = delegate;  
   }  
  
   @SuppressWarnings(&quot;unchecked&quot;)
   public Object[] getParametersFor(ResourceMethod method, List&lt;Message&gt; errors, ResourceBundle bundle) {  
          Object[] parameters = delegate.getParametersFor(method, errors, bundle);  
           for(int i = 0; i &lt; parameters.length; i++) {  
                if(
                		(parameters[i] instanceof List&lt;?&gt;)&&
                		(!((List&lt;?&gt;)parameters[i]).isEmpty()) &&
                		(((List&lt;?&gt;)parameters[i]).get(0) instanceof List&lt;?&gt;) &&
                		( 
                			(  !((List&lt;?&gt;)((List&lt;?&gt;)parameters[i]).get(0)).isEmpty() &&
                				((List&lt;?&gt;)((List&lt;?&gt;)parameters[i]).get(0)).get(0) instanceof Jsonable		
                			)||
                			( ((List&lt;?&gt;)((List&lt;?&gt;)parameters[i]).get(0)).isEmpty()  )
                		)
                )
                {
                	parameters[i] = ((List&lt;Jsonable&gt;)parameters[i]).get(0);
                 }  
           }  
           return parameters;  
    }  
}

Obrigado pela força.

Lucas_Cavalcanti

Esse é um problema bem específico. Na documentação está escrito que as listas são tratadas de um jeito diferente, e os converters são aplicados nos elementos da lista.

Em todo caso, pull requests com documentação são sempre bem-vindos =)

S

Desculpe a minha ignorância :slight_smile: mas, o que é pull request? e como faze-lo?

Lucas_Cavalcanti

aqui:

tem um botão chamado “Fork”.

vc pode fazer um fork que é tipo uma cópia do código do vraptor que vc pode editar do jeito que vc quiser. Daí vc pode juntar algumas alterações e mandar um pull request (outro botão da interface do github), daí eu posso pegar as suas modificações e colocar no código do VRaptor.

vc pode editar os arquivos pelo próprio github, ou baixar o código todo pra sua máquina usando o git.

Criado 3 de julho de 2012
Ultima resposta 9 de jul. de 2012
Respostas 16
Participantes 2