Ajuda com VRaptor

32 respostas
neguinho.etav

Boa noite,

estou com um probleminha pra retornar o json de uma estrutura do meu sistema. Lá vai:

public class Uf { private long codigo; private String sigla; private String nome; private List<Cidade> cidades; ...

public class Cidade { private long codigo; private Uf uf; private String nome; ...
Eu gostaria de retornar o JSon com os dados da cidade + apenas o código da UF. como posso fazer isso no result???
Tentei dessa forma, porém não me traz corretamente

List<Cidade> list = daoCidade.listar(Cidade.class); result.use(ExtJSJson.class) .from(list) .include("uf", "uf.codigo") .exclude("uf.nome","uf.cidades","uf.sigla") .serialize();
Resultado:

{"data": [{"codigo": 1,"uf": {"codigo": 1},"nome": "Acrelândia"},{"codigo": 2,"uf": {"@reference": "../../info.pm.bellicus.bean.util.Cidade/uf"},"nome": "Assis Brasil"},{"codigo": 3,"uf": {"@reference": "../../info.pm.bellicus.bean.util.Cidade/uf"},"nome": "Brasiléia"},{"codigo": 4,"uf": {"@reference": "../../info.pm.bellicus.bean.util.Cidade/uf"},"nome": "Bujari"},{"codigo": 5,"uf": {"@reference": "../../info.pm.bellicus.bean.util.Cidade/uf"},"nome": "Capixaba"},{"codigo": 6,"uf": {"@reference": "../../info.pm.bellicus.bean.util.Cidade/uf"},"nome": "Cruzeiro do Sul"},{"codigo": 7,"uf": {"@reference": "../../info.pm.bellicus.bean.util.Cidade/uf"},"nome": "Epitaciolândia"},{"codigo": 8,"uf": {"@reference": "../../info.pm.bellicus.bean.util.Cidade/uf"},"nome": "Feijó"}........

Alguém poderia me ajudar??

32 Respostas

Lucas_Cavalcanti

vc precisa pra extJS mesmo?

neguinho.etav

Sim… estou fazendo a parte de interface com ExtJS4.

Consegui resolver fazendo 1 DTO… mas tenho certeza q vraptor automatiza isso sem necessidade de criação de classes DTO.

Testei criar o PersistentBagConverter, CustomJSONSerialization (desse link: http://www.wbotelhos.com.br/category/vraptor/page/3/), CustomXStreamBuilder, e nenhum funcionou corretamente…

Vc teria alguma outra idéia???

neguinho.etav

Alguma luz quanto ao problema??

Lucas_Cavalcanti

tenta fazer uma coisa.

crie uma cópia dessa classe no seu projeto:

mantenha a anotação @Component.

receba um XStreamBuilder no construtor

troque a expressão do new XStream por xstreamBuilder.jsonInstance();

continue usando o result.use(ExtJSJson.class)

me dá um toque se funcionar.

neguinho.etav

Lucas Cavalcanti:
tenta fazer uma coisa.

crie uma cópia dessa classe no seu projeto:

mantenha a anotação @Component.

receba um XStreamBuilder no construtor

troque a expressão do new XStream por xstreamBuilder.jsonInstance();

continue usando o result.use(ExtJSJson.class)

me dá um toque se funcionar.

A classe ExtJSWrapper está dando erro… meu projeto não consegue encontrá-la no jar do vraptor… estou usando o maven segue dependencia:

<dependency>
		<groupId>br.com.caelum</groupId>
		<artifactId>vraptor</artifactId>
		<version>3.4.0</version>
	</dependency>	

	<dependency>
		<groupId>com.thoughtworks.xstream</groupId>
		<artifactId>xstream</artifactId>
		<version>1.4.2</version>
	</dependency>

Nesse caso o que fazer?

Lucas_Cavalcanti

é pq ele é package protected, então vc não consegue usar fora… vc precisa copiar essa classe tb:

Lucas_Cavalcanti

só uma coisa:

antes de fazer isso, tenta voltar o xstream pra versão 1.3.1, tinha um bug com a versão 1.4.2

neguinho.etav
Lucas Cavalcanti:
só uma coisa:

antes de fazer isso, tenta voltar o xstream pra versão 1.3.1, tinha um bug com a versão 1.4.2
https://github.com/caelum/vraptor/issues/416

Cara... fiz o q vc falou, mas não rolou... quando eu adiciono estas classes o meu código para de funcionar... não converte a lista em Json... É necessário configurar alguma coisa para que o código assuma que a minha classe como prioridade?

segue o codigo:

@Component
public class DefaultExtJson implements ExtJSJson {

    private XStreamSerializer serializer;
    private XStream xstream;
    private ExtJSWrapper wrapper;

    public DefaultExtJson(HttpServletResponse response, TypeNameExtractor extractor, ProxyInitializer initializer, XStreamBuilder xStreamBuilder)
        throws IOException {
        xstream = xStreamBuilder.jsonInstance();
        xstream.aliasField("data", ExtJSWrapper.class, "list");
        serializer = new XStreamSerializer(xstream, response.getWriter(), extractor, initializer);
    }

    public ExtJSJson from(Object object) {
        wrapper = new ExtJSWrapper(object);
        serializer.from(object);
        return this;
    }

    public ExtJSJson exclude(String... names) {
        serializer.exclude(names);
        return this;
    }

    public ExtJSJson include(String... fields) {
        serializer.include(fields);
        return this;
    }

    public ExtJSJson selected(Object value) {
        wrapper.setSelected(value);
        return this;
    }

    public ExtJSJson serialize() {
        serializer.from(wrapper).recursive().serialize();
        return this;
    }

    public ExtJSJson success() {
        wrapper.setSuccess(true);
        return this;
    }

    public ExtJSJson success(boolean success) {
        wrapper.setSuccess(success);
        return this;
    }

    public ExtJSJson total(Integer total) {
        wrapper.setTotal(total);
        return this;
    }
}
result.use(ExtJSJson.class).from(list).total(list.size()).serialize();
Lucas_Cavalcanti

qual erro deu?

neguinho.etav

Rapaz… esse é o problema… não dá erro… simplesmente deixa de renderizar os campos ExtJson…

Agora se eu removo as classes, funciona legal…

Lucas_Cavalcanti

ele chega a passar pelas suas classes?

neguinho.etav

Lucas, Refiz todos os passos que vc me pediu… agora deu certo… acho que eu estava fazendo algo errado…

só uma outra dúvida:
Após eu fazer essas modificações, o JSon resolvido ficou da seguinte forma:

{"extJSWrapper": { "data": [ {"codigo": 2,"uf": {"codigo": 1,"sigla": "AC","nome": "Acre"},"nome": "Assis Brasil"}, {"codigo": 3,"uf": {"codigo": 1,"sigla": "AC","nome": "Acre"},"nome": "Brasiléia"}, {"codigo": 4,"uf": {"codigo": 1,"sigla": "AC","nome": "Acre"},"nome": "Bujari"}, ...

onde antes não existia o nodo extJSWrapper, como faço para remove-lo, deixando apenas o data e seus subfilhos?

Lucas_Cavalcanti

precisa colocar o withoutRoot:

xstreamBuilder.withoutRoot().jsonInstance();
neguinho.etav

Lucas Cavalcanti:
precisa colocar o withoutRoot:

xstreamBuilder.withoutRoot().jsonInstance();

Opa Lucas,

Tentei fazer isso que vc me passou, só que quando eu coloco o withouRoot() ele ferra o Json novamente, colocando o @reference… se eu não colocar o withoutRoot ele rola tranquilo…

Alguma outra sugestão ou correção pra isso? :roll:

Lucas_Cavalcanti

tenta usar essa linha:

xstream.setMode(XStream.NO_REFERENCES);

depois de conseguir o xstream.

neguinho.etav

Lucas Cavalcanti:
tenta usar essa linha:

xstream.setMode(XStream.NO_REFERENCES);

depois de conseguir o xstream.

Nada feito… monta o JSon do mesmo jeito…

public DefaultExtJson(HttpServletResponse response, TypeNameExtractor extractor, ProxyInitializer initializer, XStreamBuilder xStreamBuilder) throws IOException { xstream = xStreamBuilder.indented().jsonInstance(); xstream.setMode(XStream.NO_REFERENCES); xstream.aliasField("data", ExtJSWrapper.class, "list"); serializer = new XStreamSerializer(xstream, response.getWriter(), extractor, initializer); }

Se eu utilizar o método withoutRoot ele renderiza o @reference… mesmo utilizando o XStream.NO_REFERENCES…

Se eu não coloco o withoutRoot, ele renderiza certinho… o único problema é o novo pai…

{"extJSWrapper": { "data": [ { "codigo": 1, "uf": { "codigo": 1, "sigla": "AC", "nome": "Acre" }, "nome": "Acrelândia" }, {
mais alguma tentativa?

neguinho.etav

Opa Lucas,

Consegui… o problema tava no xstream…

Eu utilizei da seguinte forma:

public DefaultExtJson(HttpServletResponse response, TypeNameExtractor extractor, ProxyInitializer initializer, XStreamBuilder xStreamBuilder) throws IOException { xstream = new XStream(new JsonHierarchicalStreamDriver() { @Override public HierarchicalStreamWriter createWriter(Writer out) { return new JsonWriter(out, JsonWriter.DROP_ROOT_MODE); } }); xstream.setMode(XStream.NO_REFERENCES); xstream.aliasField("data", ExtJSWrapper.class, "list"); serializer = new XStreamSerializer(xstream, response.getWriter(), extractor, initializer); }

Assim ele renderizou tudo como coisa linda do meu Deus…

Segue ai pra melhorias no vraptor…

Lucas_Cavalcanti

obrigado!

quer fazer essa mudança e mandar pro vraptor?

entre aqui:

edite o arquivo e mande um pull request.

[]'s

neguinho.etav

Lucas Cavalcanti:
obrigado!

quer fazer essa mudança e mandar pro vraptor?

entre aqui:

edite o arquivo e mande um pull request.

[]'s

Tá lá, Lucas… Valeu pela ajuda… aproveitei e criei 1 blog pra colocar também…

http://matutandoemjava.wordpress.com/2012/02/21/renderizacao-de-json-com-vraptor-3-hibernate/

Lucas_Cavalcanti

\o/

R

Boa tarde, estou com o mesmo problema aqui na aplicação, versão do stream eh a 1.3.1…
copiei as classes do jeito identico ao que deu certo pro neguinho.etav…mas aqui dá o seguinte erro…

obs: para fazer as classes criei um pacote e coloquei as duas classes dentro dele…teria que ser dentro do jar isso? desculpa se estou sendo muito ignorante, mas sou novo em java e novo no vraptor…e novo no ext rs.

obrigado.

Erro:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘defaultExtJson$’: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.cinemotion.util.DefaultExtJson]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.cinemotion.util.DefaultExtJson.()

Lucas_Cavalcanti

org.cinemotion.util.DefaultExtJson

essa classe é sua? está anotada com @Component?

R

Está anotada sim.
@Component
public class DefaultExtJson implements ExtJSJson {

Lucas_Cavalcanti

mas é o @Component do vraptor? deveria

R

@Componet é do vraptor sim…creio.
import br.com.caelum.vraptor.ioc.Component;

Lucas_Cavalcanti

estranho… como é o @Component do vraptor não deveria reclamar por não ter um construtor padrão… tenta dar um clean no projeto e no servidor, pode ser que ele esteja com uma versão antiga da classe (ou ela está dentro de um jar?)

se ainda assim não funcionar, tenta usar o @Autowired do spring em cima do construtor.

R

Já dei clear no projeto e no servidor, essa classe que criei não esta dentro de um jar…no xml está buscando essa classe vindo de um pacote diferente do que criei, não sei se tem muito a ver!

vou tentar usar o @Autowired e já te dou um retorno.

R

Lucas, continua a mesma coisa, mas agora pelo menos aparece os registros do mesmo jeito que aparecia antes!
o console me mostra isso, o cinema é associado com o complexo, e na lista me traz assim…tenho cinema ex1, ex2, se o ex1 por exemplo já ter sido cadastrado em um complexo, o primeiro registro dele aparece normal na lista, mas do segundo em diante vem em branco, com esse erro abaixo.

“cinema”: {"@reference": “…/…/org.cinemotion.entity.Complexo[2]/cinema”}…

estou usando o jar mais recente do vraptor 3.4.0…

Lucas_Cavalcanti

tenta fazer com a versão mais nova, 3.4.1, a gente corrigiu esse tipo de coisa

R

Nossa nem sabia que já havia uma mais recente, obrigado, vou testar e já te dou retorno.

R

Só uma coisa, deleto as classes que fiz então?

R

Lucas muito obrigado era esse mesmo o problema, deletei as classes e coloquei o JAR 3.4.1 do vraptor e funcionou direitinho.

Criado 10 de fevereiro de 2012
Ultima resposta 18 de abr. de 2012
Respostas 32
Participantes 3