Vraptor 3 + JSON

Boa tarde galera…

estou com o seguinte erro ao tentar serializar um objeto…

public void listarFuncConsolidado(){
		result.include("departamentoList", departamentoDAO.listar());
		List<PontuacaoFunc> pontuados = pontuacaoFuncDAO.listarConsolidado();		
		result.use(json()).withoutRoot().from(pontuados).include("colaborador").serialize(); //quando passa por aqui consta o erro abaixo
	}

Caused by: java.lang.IllegalArgumentException: Field path colaborador doesn’t exist
at br.com.caelum.vraptor.serialization.xstream.XStreamSerializer.include(XStreamSerializer.java:207)
at voxage.com.br.controllers.PontuacaoController.listarFuncConsolidado(PontuacaoController.java:85)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:61)
… 42 more

minha classe PontuacaoFunc para auxilio…

@Entity
@Table(name="pontuacao_func")
public class PontuacaoFunc implements Serializable{

	private static final long serialVersionUID = 3214100040938150076L;

	@Id
	@GeneratedValue
	@Column(name="id_pont_func")
	private Integer idPontuacaoFunc;
	
	@OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
	@JoinColumn(name="id_tipo_pontuacao", referencedColumnName="id_tipo_pontuacao")
	private TipoPontuacao tipoPontuacao;
	
	@Column(name="motivo")
	private String motivo;
	
	@Column(name="valor")
	private Integer valor;
	
	@Column(name="data_pont")
	private Date data;
	
	@OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
	@JoinColumn(name="id_func_pont", referencedColumnName="id_func")
	private Funcionario colaborador;
	
	@OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
	@JoinColumn(name="id_gestor_pont", referencedColumnName="id_func")
	private Funcionario gestor;

        // getters e setters

desde já agradeço a ajuda.

abs

só pra entender o erro, a lista que vai ser serializada está nula? vazia?

Boa Noite Vinicius,

conseguiu resolver o seu erro?

estou com o mesmo problema.

att,

E ai pessoal, eu cometi uma gafe :frowning: hehe… me desculpem! :oops:

mascjunior, no meu caso eu revi debugando que no meu DAO estava retornando atributos específicos e nao o objeto…

public void listarFuncConsolidado(){  
        result.include("departamentoList", departamentoDAO.listar());  
        List<PontuacaoFunc> pontuados = pontuacaoFuncDAO.listarConsolidado();  // esse metodo aqui    
        result.use(json()).withoutRoot().from(pontuados).include("colaborador").serialize();
    }

por isso q constava aquele erro hehe

vc conseguiu resolver?

abs

cara o meu aki funciona bem

[code]
Objeto ob = repository.getObjeto(id);

result
.use(json())
.withoutRoot()
.from(ob)
.exclude(“objRecursivo”, “prop.objR”)
.recursive()
.serialize();[/code]

agora o meu problema esta sendo o contrario
estou tentando enviar via:
AJAX
usando um POST
um dado em JSON
minha action eh executada mais não eh feito a deserialização

alguem tem alguma ideia?

eu vi uma thred aki no guj que fala algo assim
http://www.guj.com.br/java/197235-vraptor3-serializedeserialize-listas-com-xstream

mais não entendi onde eu coloco o codigo de deserializacao
eu tenho um

public class CustomJSONSerialization extends XStreamJSONSerialization

teria algo para deserializar json?

que erro dá?

então tentei realizar o PUT (ou POST, ja tentei os 2), e a execução ate chama a action mais o parametro chega null

[code] @Transactional
@Put("/templates")
public void update(EtiquetaTemplate etiquetaTemplate) {

	validator.validate(etiquetaTemplate);
	validator.onErrorUsePageOf(this).edit(etiquetaTemplate.getId());

	etiquetaTemplate.getId().setVersao(etiquetaTemplate.getId().getVersao()+1);
	repository.create(etiquetaTemplate);

	result.redirectTo(this).index();
}
[/code]

[code] @Transactional
@Put("/templates.json")
public void update(String etiquetaTemplate) {
System.out.print(etiquetaTemplate);

	result.redirectTo(this).index();
}

[/code]

ah tah, se vc quer que o VRaptor deserialize algo que veio por json (ou xml) vc precisa anotar o método do controller com @Consumes:

@Consumes("application/json") // ou sem o parâmetro
@Put("/templates")    
public void update(EtiquetaTemplate etiquetaTemplate) {       

...
}

senão o vraptor só tenta popular com os dados do formulário (parâmetros do request)

Ahh Legal Lucas,

mais e se eu estiver utilizando o Results.representation() ?
sendo assim a action deveria verificar o requestHeader antes de saber como tratar o parametro enviado

como isso funcionaria??

uma coisa é o content-type da requisição (que o VRaptor usa para deserializar) e outra é o header Accept (que o VRaptor usa no representation, para serializar).

se vc está usando um cliente http para se comunicar com o VRaptor, vc precisa setar tanto o header Content-type quanto o Accept.

de qqer forma vc não precisa mexer com esses headers na mão, o VRaptor já faz isso

acho q não entendi direito,

por exemplo na action Show se eu enviar um:
get normal (pelo browser) ele renderiza a view correspondente
get getJSON (usando jquery) ele renderiza um json

[code]@Transactional
@Get
@Path(value="/templates/{templatepk.nome}", priority=Path.LOWEST)
public void show(EtiquetaTemplatePK templatepk) {
EtiquetaTemplate ed = repository.getTemplateByNome(templatepk.getNome());

	result
		.use(Results.representation())			
		.from(ed)
		.exclude("usuarioCriacao", "regioes.template")			
		.recursive()
		.serialize();
}[/code]	

agora quero fazer algo assim no update, então caso eu envio o put via form request ele identifica
mais se eu envia usando um putJSON ele não deserializa pro objeto

[code] @Transactional
@Put("/templates")
@Consumes
public void update(EtiquetaTemplate etiquetaTemplate) {

	validator.validate(etiquetaTemplate);
	validator.onErrorUsePageOf(this).edit(etiquetaTemplate.getId());

	etiquetaTemplate.getId().setVersao(etiquetaTemplate.getId().getVersao()+1);
	repository.create(etiquetaTemplate);

	result.redirectTo(this).index();
}[/code]

ele da um erro:

[list]Unable to handle media type [application/x-www-form-urlencoded]: no deserializer found.[/list]

PS: eu sei q o metodo putJSON não existe no jquery mais eu o extendi

[code]function _ajax_request(url, data, callback, type, method) {

if (jQuery.isFunction(data)) {
	method = method || type;
	type = type || callback;
	callback = data;
	data = undefined;
}

return jQuery.ajax({
	type: method
	, url: url
	, data: data
	, success: callback
	, dataType: type
});

}

jQuery.extend({
put: function(url, data, callback, type) {
return ajax_request(url, data, callback, type, ‘PUT’);
}
, delete
: function(url, data, callback, type) {
return _ajax_request(url, data, callback, type, ‘DELETE’);
}
});

jQuery.extend({
postJSON: function(url, data, callback) {
return jQuery.post(url, data, callback, ‘json’);
}
, putJSON: function(url, data, callback) {
return jQuery.put(url, data, callback, ‘json’);
}
, deleteJSON: function(url, data, callback) {
return jQuery.delete_(url, data, callback, ‘json’);
}
});
[/code]

aki http://gabrielmancini.blogspot.com/2011/05/rest-jquery-ajax-json.html eu explico melhor como isso funciona

o dataType é o que vc espera receber, não é o que ele vai mandar… ou seja, é o Accept, não o Content-Type.

por padrão ele manda o data como www-formurlencoded, que o VRaptor trata como parametro da request mesmo…

faz um teste, olhe no firebug quais são os headers da requisição

desculpa lucas não entendi.

vc entendeu qual eh minha intenção?

entendi, o problema é o tipo e o formato de dados que o jquery tah mandando pro VRaptor…

vc tem o firebug instalado no seu firefox?

consegue ver qual é o corpo e os headers da sua requisição que usa o putJSON?

Cabeçalhos de Resposta Server Apache-Coyote/1.1 Content-Type text/html;charset=utf-8 Content-Length 1312 Date Thu, 19 May 2011 17:16:22 GMT Cabeçalhos de Solicitação Host localhost:8080 User-Agent Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Accept application/json, text/javascript, */*; q=0.01 Accept-Language pt-br Accept-Encoding gzip, deflate Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive 115 Connection keep-alive Content-Type application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With XMLHttpRequest Referer http://localhost:8080/etiquetas-interface/templates/Template%201/edit Content-Length 150 Cookie JSESSIONID=120F6F9B83158575A2C8099F72449FED

o cabeçalho da requisição:
Content-Type application/x-www-form-urlencoded; charset=UTF-8

ou seja, o VRaptor vai tentar tratar o que veio como form parameter (o funcionamento normal)…

dê uma olhada nisso:
http://api.jquery.com/jQuery.ajax/

específicamente as options contentType, data e proccessData

Legal corrigido.

so uma questão como eu seto as particularidades de deserialização
por ex: o erro exibe um problema de cast.

adicionei a dependencia do com.thoughtworks.xstream.mapper.CannotResolveClassException: etiquetaTemplate.id : etiquetaTemplate.id com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:68) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:71) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:86) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:96) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38) com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:52) com.thoughtworks.xstream.core.util.HierarchicalStreams.readClassType(HierarchicalStreams.java:29) com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:136) com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:33) com.thoughtworks.xstream.XStream.unmarshal(XStream.java:923) com.thoughtworks.xstream.XStream.unmarshal(XStream.java:909) com.thoughtworks.xstream.XStream.fromXML(XStream.java:861) br.com.caelum.vraptor.deserialization.JsonDeserializer.deserialize(JsonDeserializer.java:39) br.com.caelum.vraptor.interceptor.DeserializingInterceptor.intercept(DeserializingInterceptor.java:87) br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:59) br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:89) br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:59) br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) br.com.abril.etiquetasinterface.interceptor.AuthorizationInterceptor.intercept(AuthorizationInterceptor.java:52) 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.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.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:23) 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) com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129) com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)

qual é o json que o browser gerou mesmo? (no firebug tem um lugar que mostra o corpo da requisição)


não seria mais simples ter uma classe de deserialização tipo a de serialização

[code]

import java.io.Writer;
import java.util.Collection;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;


import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.collections.CollectionConverter;
import com.thoughtworks.xstream.converters.collections.MapConverter;
import com.thoughtworks.xstream.converters.enums.EnumConverter;
import com.thoughtworks.xstream.converters.javabean.JavaBeanConverter;
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;

import br.com.caelum.vraptor.interceptor.TypeNameExtractor;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.serialization.ProxyInitializer;
import br.com.caelum.vraptor.serialization.xstream.XStreamJSONSerialization;

@Component
public class CustomJSONSerialization extends XStreamJSONSerialization {
    //delegate constructor
    
    public CustomJSONSerialization(HttpServletResponse response,
			TypeNameExtractor extractor, ProxyInitializer initializer) {
		super(response, extractor, initializer);
		// 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);  
             }  
        };  
    }  
    
	@Override
    protected XStream getXStream() {
        XStream xStream = super.getXStream();
        xStream.registerConverter(new EnumConverter());
        xStream.registerConverter(new CollectionConverter(xStream.getMapper()) {
	        @Override
	        @SuppressWarnings("rawtypes")
	        public boolean canConvert(Class type) {
	            return Collection.class.isAssignableFrom(type);
	        }
	    });
        
        xStream.registerConverter(new MapConverter(xStream.getMapper()) {
            @Override
            @SuppressWarnings("rawtypes")
            public boolean canConvert(Class type) {
                return Map.class.isAssignableFrom(type);
            }
        });

        return xStream;
    }
}
[/code]

não seria mais simples ter uma classe de deserialização tipo a de serialização


import java.io.Writer;
import java.util.Collection;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;


import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.collections.CollectionConverter;
import com.thoughtworks.xstream.converters.collections.MapConverter;
import com.thoughtworks.xstream.converters.enums.EnumConverter;
import com.thoughtworks.xstream.converters.javabean.JavaBeanConverter;
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;

import br.com.caelum.vraptor.interceptor.TypeNameExtractor;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.serialization.ProxyInitializer;
import br.com.caelum.vraptor.serialization.xstream.XStreamJSONSerialization;

@Component
public class CustomJSONSerialization extends XStreamJSONSerialization {
    //delegate constructor
    
    public CustomJSONSerialization(HttpServletResponse response,
			TypeNameExtractor extractor, ProxyInitializer initializer) {
		super(response, extractor, initializer);
		// 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);  
             }  
        };  
    }  
    
	@Override
    protected XStream getXStream() {
        XStream xStream = super.getXStream();
        xStream.registerConverter(new EnumConverter());
        xStream.registerConverter(new CollectionConverter(xStream.getMapper()) {
	        @Override
	        @SuppressWarnings("rawtypes")
	        public boolean canConvert(Class type) {
	            return Collection.class.isAssignableFrom(type);
	        }
	    });
        
        xStream.registerConverter(new MapConverter(xStream.getMapper()) {
            @Override
            @SuppressWarnings("rawtypes")
            public boolean canConvert(Class type) {
                return Map.class.isAssignableFrom(type);
            }
        });

        return xStream;
    }
}

esse é o de resposta ou o de requisição?