Posts Tagged ‘RESTEasy’

REST com RESTEasy – JAXB e RESTEasy Client

February 5th, 2009

Uma ótima apresentação sobre REST me fez querer escrever um pouco sobre. Mais especificamente sobre o RESTEasy, implemetação certificada JAX-RS da JBoss. No projeto que fiz para certificação JBoss Certified SOA Developer o usei bastante e quero falar de algumas interessantes funcionalidades dele. Primeiro algumas considerações sobre REST:

  1. RESTEasy é um framework para criação de RESTful Web Services, o que em algum senso já é uma desvirtuação de REST (tal como Roy Fielding definiu), que trata de recursos. O que tem haver um serviço RESTful que loga o usuário? (O que aliás abre uma sedutora brecha para quebrar outro conceito REST: o de statelessness) De agora em diante irei usar REST e RESTful Web Services indistintamente.
  2. REST não é uma alternativa a SOA! Na verdade podemos usar REST para implementar SOA com WOA. Confuso? REST é uma alternativa ao WS-*, podendo ser usado no lugar dele para implementar SOA. A implementação RESTful de SOA é chamada WOA, ou ROA (veja a página de TLAs), que é um subconjunto de SOA.

JAXB binding

RESTEasy possui suporte a marshalling/unmarshalling de classes usando JAXB. Sou péssimo para dar exemplos mas vamos lá…:

@Path("/")
public class Servico {
 
	@GET @Path("/tempo")
	@Produces("text/xml")
	public Tempo getTempo() {
		return new Tempo("Parcialmente nublado", 20.3);
	}
 
	@POST @Path("/literal")
	@Consumes("text/xml")
	public void setTempo(Tempo tempo) {
		System.out.format("Descrição: %s%n", tempo.getDescricao());
		System.out.format("Temperatura: %d%n", tempo.getTemperatura());
	}
}
 
// classe anotada com JAXB
@XmlRootElement
class Tempo {
	private String descricao;
	private Double temperatura;
 
	public Tempo() {}
 
	public Tempo(String nome, Double preco) {
		this.descricao = nome;
		this.temperatura = preco;
	}
 
	public String getDescricao() {
		return descricao;
	}
	public void setDescricao(String nome) {
		this.descricao = nome;
	}
	public Double getTemperatura() {
		return temperatura;
	}
	public void setTemperatura(Double preco) {
		this.temperatura = preco;
	}
 
}

Na invocação de getTempo() RESTEasy vai ver que o tipo de retorno é o objeto Tempo e que ele está anotado com @XmlRootElement e vai fazer um marshalling dele. A anotação @Produces(“text/xml”) diz que a representação gerada deve ser XML. Quer que seja em JSON? Basta mudar para @Produces(“application/json”)!

Do mesmo jeito funciona o setTempo(). O parâmetro passados sem nenhuma anotação é interpretado como o corpo da requisição HTTP, que no caso é um objeto.

RESTEasy Client

Algo muito interessante que não é da especificação JAX-RS é o suporte a clients. Esses clients são proxies que transformam invocações Java em requisições HTTP. Para isso devemos criar uma interface com as mesmas assinaturas do nosso serviço e anotá-las:

public class Main {
	static {
		// precisa ser chamo uma única vez para registrar providers RESTEasy, scanear classes, etc
		 RegisterBuiltin.register(ResteasyProviderFactory.getInstance()); // precisa ser chamado uma única vez para
	}
 
	public static void main(String args[]) {
 		 IServico client = ProxyFactory.create(IServico.class, "http://localhost:8080/<Context>");
 
		 Tempo tempo = client.getTempo();
		 tempo.setTemperatura(tempo.getTemperatura() + 5.0);
		 client.setTempo(tempo);
	}
}
 
interface IServico {
 
	@GET @Path("/tempo")
	@Produces("text/xml")
	public abstract Tempo getTempo();
 
	@POST @Path("/literal")
	@Consumes("text/xml")
	public abstract void setTempo(Tempo tempo);
}
 
// classe anotada com JAXB
@XmlRootElement
class Tempo {
	private String descricao;
	private Double temperatura;
 
	public Tempo() {}
 
	public Tempo(String nome, Double preco) {
		this.descricao = nome;
		this.temperatura = preco;
	}
 
	public String getDescricao() {
		return descricao;
	}
	public void setDescricao(String nome) {
		this.descricao = nome;
	}
	public Double getTemperatura() {
		return temperatura;
	}
	public void setTemperatura(Double preco) {
		this.temperatura = preco;
	}
 
}

Agora você deve ver no console:

Descrição: Parcialmente nublado
Temperatura: 34.000000

Precisamos a classe Tempo também apenas porque estamos usando JAXB. Tudo transparente, muito fácil agora fazer teste unitários de serviços RESTful!