Mostrando postagens com marcador Web Service. Mostrar todas as postagens
Mostrando postagens com marcador Web Service. 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

sexta-feira, 25 de fevereiro de 2011

Web Service com Apache Axis2

Olá povo,

Todo mundo já sabe da atual importância dos Web Services no mundo da TI. Eles promovem a integração entre sistemas inclusive que podem inclusive utilizar tecnologias heterogêneas. Mas como criar esse tipo de software? Bem, como diria a velha propaganda, "existem mil maneiras de se fazer Neston". Traduzindo pra o nosso contexto, existem mil maneiras de se fazer web services. Podemos utilizar os protocolos JSON ou SOAP (pelo menos que eu conheço), e com esses dois podemos desenvolver em várias tecnologias (.net, Java, PHP, ...) , e por fim, para essas tecnologias podemos utilizar alguns frameworks disponíveis no mercado.

Nesse post, que é baseado nesse tutorial de Lars Vogel, apresentarei um exemplo da disponibilização de um Web Service utilizando o padrão SOAP, criado com a linguagem Java e usando o framework Apache Axis2. Vamos utilizar o Eclipse EE com WTP (Web Tools Platform) e as ferramentas Tomcat 6.0 e obviamente do Axis 2. Baixe essas ferramentas e mãos a obra!

Devemos incialmente configurar o Eclipse indicando onde decompactamos o Axis2. Para isso, vá até o menu Window > Preferences. No lado esquerdo, selecione Web Services > Axis 2 Preferences, e na aba Axis 2 Runtime indique o diretório do Axis 2. Ainda na opção Web Services, selecione a subopção Server and Runtime. Então, selecione Tomcat v6.0 Server e Apache Axis 2 nos campos Server e Web service runtime respectivamente.

Crie um novo Dynamic Web Project, vou dar o nome de BlogWS. Uma vez com o projeto criado, adicione um novo pacote, nomearei como ngvl.jee.blogws. Inciaremos criando um serviço bem simples que simplesmente dirá um olá com a hora do servidor. Crie uma classe chamada HelloWS conforme abaixo:

package ngvl.jee.blogws;

import java.text.SimpleDateFormat;
import java.util.Date;

public class HelloWS {
public String digaOla(String nome){
String result;
SimpleDateFormat df =
new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");

Date date = new Date(System.currentTimeMillis());
result = df.format(date);

return "Olá "+ nome +" a hora atual é "+ result;
}
}

Criada a classe, clique com o botão direito sobre a classe e selecione a opção Web Services > Create Web service. A tela abaixo será exibida:


Selecione Web service runtime: Apache Axis2 e clique em Next. Na tela que abrirá em seguida, selecione Generate default services.xml file e clique em Finish.

Feito isso seu WebService está pronto! Mas já? :) Pois é. O Axis2 é bem simples. E com uma ajudinha do WTP fica mais fácil ainda. Pra ver seu serviço rodando, basta clicar com o botão direito sobre o projeto e escolher a opção Run as > Run on server. O browser deve exibir esse endereço (se não exibir digite-o): http://localhost:8080/BlogWS/axis2-web/. Será exibida uma tela de boas vindas do Axis2. Clique no link Services e será exibido os serviços disponíveis. Entre eles está o nosso magistoso HelloWS :) com a operação digaOla. Se você clicar sobre o nome do serviço verá o WSDL (Web Service Descriptor Language) que é o XML que define nosso WS. Nele temos detalhes sobre o serviço, como as operações que estamos disponibilizando, tipos de parâmetros de entrada (response) e de retorno (response).
Mostraremos no próximo post como acessar esse serviço através de uma aplicação Android. Mas antes vamos fugir a regra. Milhões de tutoriais na internet mostram como fazer um serviço simples, que não envolve tipos complexos. Vamos mostrar como criar um serviço que retorna uma lista de objetos do tipo Pessoa.
Primeiro crie uma interface que vai representar seu objeto complexo.


package ngvl.jee.blogws;

public interface Pessoa {
void setNome(String nome);
String getNome();
void setIdade(int idade);
int getIdade();
}

Depois crie a classe que implementa essa interface:

package ngvl.jee.blogws;

public class PessoaImpl implements Pessoa {
private int idade;
private String nome;

public PessoaImpl(String nome, int idade) {
setIdade(idade);
setNome(nome);
}

public int getIdade() {
return idade;
}

public String getNome() {
return nome;
}

public void setIdade(int idade) {
this.idade = idade;
}

public void setNome(String nome) {
this.nome = nome;
}
}


Feito isso, criaremos agora o serviço que retornará uma lista fake de objetos do tipo Pessoa. No mundo real, esse serviço faria uma busca no banco de dados. Mas não vamos colocar isso aqui :)

public class PessoaWS {

public Pessoa[] obterPessoas(){
Pessoa[] pessoas = new Pessoa[]{
new PessoaImpl("Nelson", 27),
new PessoaImpl("Glauber", 18),
new PessoaImpl("Leal", 65)
};
return pessoas;
}
}

Agora gere o WebService a partir dessa última classe, e em seguida execute-a conforme fizemos no exemplo anterior. O resultado ficará como na imagem abaixo:


Pronto! Temos dois serviços HelloWS e PessoaWS publicados. No próximo artigo mostrarei como acessá-los com uma aplicação Android.

4br4ç0s,
nglauber