HATEOAS com VRaptor 3.3.1 - Serializando os links

19 respostas
acdesouza

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:

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

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

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:
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.
}

O seguinte request, usando curl:

curl -i -X GET "http://localhost:8080/clientes/1" -H "Accept: text/xml"
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?

19 Respostas

Lucas_Cavalcanti

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

acdesouza

Sim. Segue meu web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:web="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
	version="2.4">
	<display-name>CoreISPWS</display-name>

	<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>
</web-app>

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

acdesouza

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

Lucas_Cavalcanti

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

acdesouza

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:

Lucas_Cavalcanti

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

acdesouza

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();
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: [telefone removido]
Content-Type: application/xml;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 06 Jul 2011 17:19:12 GMT

<cliente>
  <id>1</id>
  <nome>Antonio Carlos de Souza</nome>
  <atom:link rel="desbloquear" href="http://localhost:8090/MinhaApp/clientes/1/desbloquear" xmlns:atom="http://www.w3.org/2005/Atom"/>
</cliente>
3. Fiz um outro teste passando o header 'Accept: application/json'
result.use(representation()).from(cliente)
				.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=3C14185B57CC4C1135757D7526DED566; Path=/
ETag: [telefone removido]
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"}

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

Lucas_Cavalcanti

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

acdesouza

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?

Lucas_Cavalcanti

o que gera os links é o RestfulSerialization

acdesouza

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" } ] }

Lucas_Cavalcanti

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

acdesouza

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?

Lucas_Cavalcanti

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:

acdesouza

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?

Lucas_Cavalcanti

acho que é legal continuar pela lista de dev mesmo…

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

acdesouza

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

Lucas_Cavalcanti

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

acdesouza

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]

Criado 6 de julho de 2011
Ultima resposta 11 de jul. de 2011
Respostas 19
Participantes 2