HATEOAS com VRaptor 3.3.1 - Serializando os links

Caros,

Estou usando VRaptor, versão 3.3.1, para expor uma API REST.
Atualmente, a API exibe apenas os dados, mas estamos tentando incluir links para os próximos recursos disponíveis.

O problema é que os links não estão sendo serializados.

Tenho um Controller:

[code]package controller;

import static br.com.caelum.vraptor.view.Results.representation;

import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.restfulie.hypermedia.Transition;

@Resource
@Path("/clientes")
public class ClientesResource {
@Get("/{clienteId}")
@Transition
public void visualiza(Long clienteId) {
Cliente cliente = new TodosClientes().get(clienteId);

	if( cliente != null ) {
		result.use(representation()).from(cliente).recursive().serialize();
	} else {
		result.notFound();
	}
}

}[/code]

Na documentação do VRaptor fala que tenho que implementar a interface br.com.caelum.vraptor.restfulie.hypermedia.HypermediaResource: https://github.com/caelum/restfulie-java

Aqui começam os problemas. O VRaptor mudou o método desta interface. Até aí nada, fiz a implementação de acordo com a nova interface:

[code]package model;

import br.com.caelum.vraptor.restfulie.hypermedia.HypermediaResource;
import br.com.caelum.vraptor.restfulie.relation.RelationBuilder;

public class Cliente implements HypermediaResource {

private Long id;
private String nome;

@Override
public void configureRelations(RelationBuilder builder) {
	builder.relation("desbloquear").uses(AssinaturasResource.class).visualizaTitular(getId());
}

//… Uns getters e setters.
}
[/code]

O seguinte request, usando curl:

Deveria retornar:

<cliente> <id>1</id> <nome>Antonio Carlos</nome> <atom:link rel="desbloquear" href="http://localhost:8080/clientes/1/desbloquear" xmlns:atom="http://www.w3.org/2005/Atom"/> </cliente>

Mas não está incluindo o link. Inclusive, coloco um breakpoint no método configureRelations e não está passando lá.
Alguém teria alguma idéia?

vc configurou o pacote do restfulie no web.xml?

    <context-param>
        <param-name>br.com.caelum.vraptor.packages</param-name>
        <param-value>br.com.caelum.vraptor.restfulie</param-value>
    </context-param>

se vc não fizer isso o VRaptor não registra os componentes do restfulie server

Sim. Segue meu web.xml

[code]<?xml version="1.0" encoding="UTF-8"?>

CoreISPWS

<filter>
	<filter-name>vraptor</filter-name>
	<filter-class>br.com.caelum.vraptor.VRaptor</filter-class>
</filter>

<context-param>  
     <param-name>br.com.caelum.vraptor.encoding</param-name>  
     <param-value>UTF-8</param-value>  
</context-param>

<context-param>
	<param-name>br.com.caelum.vraptor.packages</param-name>
	<param-value>br.com.caelum.vraptor.restfulie,meu.pacote</param-value>
</context-param>

<filter-mapping>
	<filter-name>vraptor</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>FORWARD</dispatcher>
	<dispatcher>REQUEST</dispatcher>
</filter-mapping>

[/code]

Todos as classes estão no package meu.pacote.

Esse erro poderia estar relacionado com isso? https://github.com/caelum/vraptor/issues/241

hum… é possível que sim =(

vc chegou a testar com xml()?

o problema é a ordem em que o representation() está testando os serializers… ele tá pegando o xml puro antes do restfulie

Se eu mudar de:

Para:

E, fizer o request:

Tenho a resposta:

HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-Powered-By: Servlet 2.4; JBoss-4.0.5.GA (build: CVSTag=Branch_4_0 date=200610162339)/Tomcat-5.5 Set-Cookie: JSESSIONID=601069A5860083B2C08918D071299FA6; Path=/ Content-Type: application/xml;charset=UTF-8 Content-Length: 0 Date: Wed, 06 Jul 2011 15:20:54 GMT

Atente para o tamanho do body: Content-Length: 0

Se eu passo um Id inexistente ele retorna um 404. Isto é, tenho certeza de quem tem um Cliente com dados neste Id.

Alguma idéia? Começo a baixar o código do VRaptor? :slight_smile:

faz só um teste: tire o recursive(). o método serialize precisa ser chamado também…

Vamos lá…

1. result.use(representation()).from(cliente) .recursive() .serialize();

HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-Powered-By: Servlet 2.4; JBoss-4.0.5.GA (build: CVSTag=Branch_4_0 date=200610162339)/Tomcat-5.5 Set-Cookie: JSESSIONID=AB13D004C77D3A1D3CCAEC5984FAEE2D; Path=/ Content-Length: 0 Date: Wed, 06 Jul 2011 17:12:46 GMT

2. result.use(representation()).from(cliente) .serialize();

[code]HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.4; JBoss-4.0.5.GA (build: CVSTag=Branch_4_0 date=200610162339)/Tomcat-5.5
Set-Cookie: JSESSIONID=D0358159645870ED532D9B396957A169; Path=/
ETag: 1939066069
Content-Type: application/xml;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 06 Jul 2011 17:19:12 GMT

1 Antonio Carlos de Souza [/code]
  1. Fiz um outro teste passando o header ‘Accept: application/json’

result.use(representation()).from(cliente) .serialize();

[code]HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.4; JBoss-4.0.5.GA (build: CVSTag=Branch_4_0 date=200610162339)/Tomcat-5.5
Set-Cookie: JSESSIONID=3C14185B57CC4C1135757D7526DED566; Path=/
ETag: 1158703507
Content-Type: application/json;charset=UTF-8
Content-Length: 739
Date: Wed, 06 Jul 2011 17:23:23 GMT

{“id”:1,“nome”:“Antonio Carlos de Souza”}[/code]

Resumindo: Nem o recursive, nem a representação em JSON, estão tratando os relations da classe root.

dá algum erro no console do servidor? é estranho o conteúdo vir vazio…

Não reparei se dava erro. Estou olhando a implementação dos serializadores e não estou entendendo onde ele faz o parse dos links.

Olhando a classe DefaultRepresentationResult, vi que ela só executa os serializadores. E, a XStreamXMLSerialization seriaiza para XML. Certo?
Então, nesta segunda, não entendi onde ele faz a criação dos links. Poderia me ajudar?

o que gera os links é o RestfulSerialization

Mas o RestfulSerialization é só para o XStreamXMLSerialization, certo? Estava precisando para o JSON.

Não encontrei uma implementação de serializador para JSON. Devo implementar um?

A idéia é ter um JSON assim:

{ "id":1, "nome":"Antonio Carlos de Souza", "links":[ { "rel":"desbloquear", "href":"http://localhost:8080/clientes/1/desbloquear" } ] }

pra json não está implementado mesmo… quer ajuda pra implementar a extensão?

Sim. #comofaz? :slight_smile:

Estou vendo a implementação das classes do pacote: br.com.caelum.vraptor.restfulie.serialization

Acredito que saberia criar um parse, mas não sei como fazer ele ser utilizado. Por onde começo?

vc pode criar uma classe bem parecida com essa:

daí vc estende XStreamJSONSerialization ao inves do XML, e talvez vc tenha que modificar o linkConverter (ele já vai gerar um json com links, mas talvez não esteja no formato que vc quer)

qqer coisa grita :wink:

AAAAHHHHH :!: :!: :!: :!: :lol:

Então, baixei o VRaptor do github, dei um checkout para a tag 3.3.1 e criei um branch a partir dessa tag com o nome vraptor-3.3.2

Até aí tudo bem, mas não estou conseguindo compilar o projeto usando o maven. Mesmo depois de executar o maven_fix.sh

Falta a dependência do jersey-core/server. No pom.xml está dizendo que depende de uma versão 1(com o groupId errado), só que esta não existe. No ant está sendo usado uma versão 1.5-SNAPSHOT, só que não acho o snapshot usado. Tem alguma coisa que estou esquecendo de fazer?

Esqueci de falar, mudei o groupId para com.sun.jersey e a versão para 1.5-SNAPSHOT, como diz no pom.xml dentro do jar que o ant usa.

Outra coisa: Continuo a conversa por aqui mesmo ou mando para a lista vraptor-dev?

acho que é legal continuar pela lista de dev mesmo…

o snapshot deve estar em vraptor-core/lib/[optional]/jersey

Isso! Mas não encontrei nos repos do Maven. Estou usando o Central, Java.net e Jboss.

acho que não tem mesmo, é SNAPSHOT ainda… vc tem que fazer o install local

Só para linkar os assuntos:
[list]Discussão sobre serialização dos links com representação JSON, na lista de discussão dos desenvolvedores.[/list]
[list]Pull-request, no Github para a adição da funcionalidade.[/list]