Mostrando postagens com marcador Jersey. Mostrar todas as postagens
Mostrando postagens com marcador Jersey. Mostrar todas as postagens

quinta-feira, 30 de junho de 2011

RESTful Web Services com Jersey

Olá povo,

O padrão REST (Representational State Transfer) está cada vez mais se tornando um padrão para compartilhamento de informações nos serviços web. Criado em 2000 esse padrão utiliza o conceito de recursos que são identificados por um ids globais e utiliza os próprios métodos do protocolo HTTP para realizar operações sobre esses recursos em um servidor Web. Por exemplo, o método GET obtém um recurso ou uma lista deles, enquanto que o PUT insere, o POST atualiza e o DELETE remove. Outra característica interessante do REST é que podemos optar pelo tipo de retorno do serviço, ele pode ser: XML, JSON, ATOM, etc.

Para estabelecer um padrão para disponibilização de Web Services utilizando RESTful, foi criada a JSR-311, e sua implementação de referência é o Jersey, desenvolvido pela Sun (que saudade de você :) que utilizaremos nesse post.

Faça o download do Jersey (http://jersey.java.net/) e descompacte-o em algum lugar do seu computador (usei a versão 1.8). Para o nosso exemplo, além dele, você vai precisar do Tomcat (utilizei a versão 6.0), Eclipse for Java EE Developers ou o Eclipse comum com o plugin WTP (Web Tools Platform)

Inicie um novo Web/Dynamic Web Project no Eclipse chamado BlogWS_REST. Copie os JARs que estão na pasta lib do ZIP do Jersey para a pasta WebContent/WEB-INF/lib do seu projeto. Em seguida, adicione esses arquivos no Build Path do projeto. Clicando com o botão direito sobre eles com o botão direito, Build Path > Add to build path.

Agora, abra o arquivo Web Content/WEB-INF/web.xml e adicione as linhas abaixo dentro da tag <web-app>

<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>
com.sun.jersey.config.property.packages
</param-name>
<param-value>
ngvl.javaee.rest
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>

Quem já fez alguma coisa com Java Web já deve saber que estamos declarando o Servlet que responderá pelas requisições HTTP. As tags servlet-class está declarando o Servlet do Jersey. Passamos como parâmetros de inicialização o (init-param) o nome do pacote da nossa aplicação que terá os web services, no nosso caso, ngvl.javaee.rest. Depois informamos que esse servlet iniciará junto com o servidor (load-on-startup). E por último, fazemos o mapeamento de URL que esse Servlet responderá. No nosso caso, dizemos que qualquer requisição que venha pra http://servidor/BlogWS_REST/rest/ será tratado pelo Servlet do Jersey.

Agora vamos fazer o primeiro Web Service Rest. Crie a classe HelloResource e deixe-a conforme abaixo:

package ngvl.javaee.rest;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class HelloResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String sayHello() {
return "Hello Jersey";
}
}

A anotação @Path informa o caminho para acessar esse serviço. O @GET diz o método HTTP que estamos utilizando. Já o @Produces determina o tipo de retorno que é dado, neste caso, texto plano.

Execute a aplicação (botão direito sobre o projeto Run as > Run on server) e depois execute no browser http://localhost:8080/BlogWS_REST/rest/hello. Você verá o texto "Hello Jersey" no navegador :)

Muito lindo! Mas na vida real não trabalhamos com "Olá mundo" :) Assim como no post que falei sobre o AXIS e Web Services com SOAP, vou mostrar como trabalhar com objetos. Crie a classe Pessoa e deixe-a conforme abaixo.

package ngvl.javaee.rest;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Pessoa {
private int id;
private String nome;
@DefaultValue("")
private String outro; // atributo opcional

// Contrutor padrão é obrigatório
public Pessoa(){
}

public Pessoa(int id, String nome, String outro) {
this.id = id;
this.nome = nome;
this.outro = outro;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getOutro() {
return outro;
}
public void setOutro(String outro) {
this.outro = outro;
}
}


A única observação sobre essa classe é a notação @XmlRootElement para que ela possa ser retornada como JSON, XML, whatever... :) Outro detalhe é o campo opcional "outro", isso fará que ele não seja obrigatório sua informação
Agora vamos a implementação do Web Service :)
package ngvl.javaee.rest;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/pessoas")
public class PessoaResource {

static List<Pessoa> pessoas;
static {
pessoas = new ArrayList<Pessoa>();
pessoas.add(new Pessoa(1, "Nelson", "info1"));
pessoas.add(new Pessoa(2, "Glauber", null));
pessoas.add(new Pessoa(3, "Vasconcelos", null));
pessoas.add(new Pessoa(4, "Leal", "info2"));
}

@GET
@Produces({ MediaType.APPLICATION_JSON })
public List<Pessoa> obterPessoas() {
return pessoas;
}

@GET
@Path("{pessoa}")
@Produces(MediaType.APPLICATION_JSON)
public Pessoa obterPessoa(@PathParam("pessoa") int id) {
return obterPessoas().get(id);
}

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public String insert(Pessoa p){
if (p != null){
pessoas.add(p);
return "Funcionou!";
} else {
return "Erro ao adicionar pessoa.";
}
}
}


Quase todas as notações nós discutimos aqui. O método obterPessoas retorna um JSON com todas as pessoas da lista. Para acessar esse método, basta colocar no browser http://localhost:8080/BlogWS_REST/rest/pessoas o retorno será um arquivo nesse formato:

{"pessoa":[{"id":"1","nome":"Nelson"},{"id":"2","nome":"Glauber"},{"id":"3","nome":"Vasconcelos"},{"id":"4","nome":"Leal"}]}

Já o segundo método obtém apenas uma pessoa. Para acessa-lo, use a URL http://localhost:8080/BlogWS_REST/rest/pessoas/1 . Utilizar esse "1" no final é determinado pela notação @Path("{pessoa}") onde pessoa será o id do recurso desejado. O retorno dessa chamada será o arquivo abaixo:

{"id":"2","nome":"Glauber"}

O último método insere um objeto Pessoa na lista. Note que ele utiliza a notação @Consumes que indica que um parâmetro no formato JSON será enviado para esse método. Ou seja, um JSON será enviado e convertido "automagicamente" para um objeto Pessoa.

Bem pessoal, é isso. Esse post foi baseado nessa página aqui. Qualquer dúvida, deixem seus comentários.

4br4ç05,
nglauber