You are on page 1of 11

Criando um WebService Restful em Java

Utilizar um WebService uma das maneiras mais comuns de se integrar aplicaes diferentes. Existem diferentes tipos de arquiteturas para web services, e o RESTful mais simples em comparao aos outrosweb services, que geralmente utilizam o SOAP. Dada essa simplicidade, isso faz com que a arquitetura RESTful seja uma escolha popular principalmente para servios abertos ao pblico. Por exemplo, o Twitter possui uma API Restful. Alm do Twitter, o Flickrtambm possui uma API que segue os princpios da arquitetura REST. De certa forma uma tendncia que os servios conhecidos como a Web 2.0 disponibilizem uma API (geralmente REST), pois cada vez maior a necessidade que esses servios sejam integrados com diversos tipos aplicaes.

Caractersticas de um web service RESTful


Este post no pretende explicar a fundo o que REST, ou explicar todos os prncipios da arquitetura, pretende apenas mostrar uma introduo de como desenvolver o web service. Para quem quiser estudar mais a fundo a definio da arquitetura, existe disponvel a prpria tese do Roy Fielding sobre o tema. Oartigo sobre REST na Wikipedia tambm uma boa referncia. Porm, para uma breve introduo como a que ser mostrada aqui, no necessrio conhecer todos os termos e princpios. O que importante ter em mente que o principal em um restful web service so as URLs do sistema (geralmente so referidas como restful urls), e os resources. Um resource um recurso, uma entidade, ou seja, um objeto com informao que ser representado por meio de um XML. Em geral, a URL para acessar esse recurso ser sempre a mesma, porm caso mudemos o mtodo HTTP (GET, POST, PUT, DELETE) o resultado da requisio ser diferente. Veja os exemplos tabela abaixo: Mtodo exemplo.com/recurso exemplo.com/recurso/1 GET lista os recursos detalhes de um recurso POST adiciona um recurso PUT atualiza um recurso DELETE remove um recurso

Porm saiba que no REST no existe um padro definido, as operaes listadas acima so apenas uma sugesto. Ao desenvolver um web service voc no obrigado a implementar todas as operaes para seguir um determinado padro, voc s precisa implementar o que necessrio no seu contexto. Por exemplo, eu posso decidir que os recursos no podem ser apagados e no implementar nenhuma operao para o mtodo DELETE. O que deve ser levado em considerao a conveno das aes. GET deve ser usado para leitura, por exemplo listar os detalhes de um recurso. POST deve ser usado para adicionar novos recursos. PUT deve ser utilizado para alterar recursos j existentes. E DELETE para apagar recursos.

JAX-RS e Jersey
O JAX-RS uma especificao (a JSR-311) que define a criao de um WebService com arquitetura RESTful. Na sua API, so utilizadas anotaes, que simplificam a necessidade extra de configuraes. Atualmente, o JAX-RS parte integrante do Java EE. Como o JAX-RS apenas uma especificao, necessrio escolher uma implementao. Entre os projetos que o implementam, temos o Jersey, que open source e mantido pela Oracle, e que a implementao de referncia do JAX-RS.

Configurando o ambiente
O Jersey deve ser baixado no seu site oficial. Atualmente est na verso 1.4. Haver duas opes, uma um arquivo zip com todas as dependncias e documentao inclusas. A outra o jersey-bundle, um jar que j inclui todas as dependncias necessrias. Neste exemplo, vamos utilizar o zip mesmo. Havero quatro jars que devem ser adicionados ao projeto: asm.jar jersey-core jersey-server jsr311-api

Estes so os jars obrigatrios em qualquer projeto utilizando o Jersey. Claro que se voc quiser mais funcionalidades, como o suporte a JSON ter que adicionar mais jars, como o jersey-json, por exemplo. No caso do JAX-RS, para rodar o nosso web service RESTful necessrio um Web Container. No exemplo irei utilizar o Tomcat, porm qualquer outro WebContainer como o Jetty, ou mesmo um servidor de aplicao Java EE como o Glassfish ou o JBoss, que j possuem um WebContainer, funcionariam do mesmo jeito. Para comear, devemos criar um projeto do tipo Dynamic Web Project no Eclipse.

Em seguida, d um nome ao projeto e selecione o WebContainer (target runtime). Escolhi como nomejersey-tutorial e o Tomcat, como disse anteriormente.

Copie as jars anteriormente para a pasta WebContent/WEB-INF/lib, e pronto, j podemos comear a escrever um pouco de cdigo.

Criando o WebService
Primeiro vamos fazer o famigerado Hello World apenas para testar se o ambiente est configurado corretamente. Veja a classe abaixo: package com.k19.restful.resources; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; @Path("/helloworld") public class HelloWorldResource { @GET @Produces("text/plain") public String showHelloWorld() { return "Ol mundo!"; }} Antes de rodar o exemplo, devemos configurar o web.xml e cadastrar a servlet do Jersey. Preste ateno que devemos passar um parmetro na inicializao. Esse parmetro corresponde ao pacote onde esto os nossos resources. Basta seguir o exemplo conforme abaixo: <?xml version="1.0" encoding="UTF-8"?> <web-app> <display-name>jersey-tutorial</display-name> <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>com.k19.restful.resources</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey REST Service</servlet-name> <url-pattern>/*</ url-pattern> </servlet-mapping> </web-app>

Ao tentar rodar o exemplo pela primeira vez, possivelmente o Eclipse mostrar uma caixa de dilogo para escolher qual servidor utilizar. Lembre-se que voc j deve ter o Tomcat instalado e configurado no Eclipse para que ele aparea como uma das opes. Bem, aps clicar no boto de executar, caso no tenha aparecido nenhuma exception, podemos testar acessando http://localhost:8080/jersey-tutorial/helloworld na barra de endereos do navegador. Altere a URL caso voc tenha dado um nome diferente para a aplicao, ou tenha configurado o Tomcat em outra porta. Se tudo estiver certo, voc deve ver a mensagem Ol mundo!. Nada muito complicado, mas j o suficiente para saber que est funcionando.

Anotaes
Pelo nosso exemplo anterior, j vimos o Jersey em ao e a nica coisa que ns fizemos foi adicionar algumas anotaes nossa classe. O Jersey todo baseado em anotaes, e existem vrias delas. Vamos listar as mais importantes. @Path essa anotao recebe uma string como parmentro e indica qual o path da URL. No exemplo anterior, tivemos a classe anotada com o valor /helloworld, e por isso que acessamos a URL como http://localhost:8080/jersey-tutorial/helloworld. @GET anotao que indica qual o mtodo correspondente do HTTP. Como dito anteriormente, podemos ter a mesma URL para aes diferentes desde que o mtodo HTTP tambm seja diferente. Da mesma forma, temos as anotaes @POST, @PUT e @DELETE. @Produces anotao que indica qual o mime-type do contedo da resposta que ser enviada para o cliente. No exemplo acima, foi text/plain para indicar que texto puro. Em um web service isso pouco usual, em geral vamos utilizar valores como text/xml para devolver XML. @Consumes anotao que indica qual o mime-type do contedo da requisio. Em geral utilizado principalmente em requisies do tipo POST ou PUT, em que o cliente precisa enviar a informao do que ele deseja adicionar/alterar. Do mesmo jeito que o web service devolve XML, ele pode consumir (receber) contedo XML.

Exemplo de CRUD
Agora vamos fazer um exemplo bem simples de CRUD. Primeiro vamos precisar de uma entidade, um beanpara conter as informaes que ns queremos manipular. Veja o exemplo abaixo: package br.com.k19.models; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Banda { private String nome; private int anoDeFormacao; private int id; // getters e setters } Note a presena da anotao @XmlRootElement na definio da nossa classe. Ela fundamental para que o Jersey conhea a representao do objeto banda em XML. Desse modo os atributos iro se tornar ns no momento em que o XML for enviado ao cliente. E do mesmo jeito, quando chegar um XML no corpo de uma requisio, o Jersey vai saber converter esse XML em um objeto do tipo Banda. O prximo passo criar o nosso WebResource. No mundo real, geralmente voc vai ter uma tabela Banda em alguma base de dados e vai desejar buscar a informao quando for requisitado. Aqui para que o exemplo fique mais simples e a gente mantenha o foco apenas na funcionalidade do Jersey, vamos utilizar um Map para simular a nossa base de dados. Veja o exemplo abaixo:

package br.com.k19.resources; import import import import import import import import import import import import java.util.ArrayList; java.util.HashMap; java.util.List; java.util.Map; javax.ws.rs.Consumes; javax.ws.rs.DELETE; javax.ws.rs.GET; javax.ws.rs.POST; javax.ws.rs.PUT; javax.ws.rs.Path; javax.ws.rs.PathParam; javax.ws.rs.Produces;

import br.com.k19.models.Banda; @Path("/bandas") public class BandaResource { // vamos utilizar um Map esttico para // "simular" uma base de dados static private Map<Integer, Banda> bandasMap; static { bandasMap = new HashMap<Integer, Banda>(); Banda b1 = new Banda(); b1.setId(1); b1.setNome("Led Zeppelin"); b1.setAnoDeFormacao(1968); bandasMap.put(b1.getId(), b1); Banda b2 = new Banda(); b2.setId(2); b2.setNome("AC/DC"); b2.setAnoDeFormacao(1973); bandasMap.put(b2.getId(), b2); } @GET @Produces("text/xml") public List<Banda> getBandas() { return new ArrayList<Banda>(bandasMap.values()); } // continua depois

Para testar, basta acessar a url http://localhost:8080/jersey-tutorial/bandas em qualquer navegador, que o resultado ser um XML parecido com esse: <bandas> <banda> <anoDeFormacao>1968</anoDeFormacao> <id>1</id> <nome>Led Zeppelin</nome> </banda> <banda> <anoDeFormacaov1973</anoDeFormacao> <id>2</id> <nome>AC/DC</nome> </banda> </bandas> E caso queiramos listar apenas uma banda em vez de todas? Tambm podemos incluir a anotao @Pathnos mtodos igual ao exemplo abaixo: @Path("{id}") @GET @Produces("text/xml") public Banda getBanda(@PathParam("id") int id) { return bandasMap.get(id); } Nesse caso, a url para acessar o recurso passa a ser http://localhost:8080/jersey-tutorial/ bandas/{id}. As chaves indicam que id um parmetro, assim podemos passar diferentes valores para acessar diferentes recursos. Note tambm o uso da anotao @PathParam no parmetro id, que serve para indicar que o parmetro do mtodo se refere ao parmetro no path. Como teste, podemos acessar http://localhost:8080/jersey-tutorial/bandas/1 e ver algo parecido com o XML abaixo: <banda> <anoDeFormacao>1968</anoDeFormacao> <id>1</id> <nome>Led Zeppelin</nome> </banda>

Agora que conseguimos listar as bandas, precisamos tambm de uma maneira de adicion-las. Veja o exemplo abaixo: @POST @Consumes("text/xml") @Produces("text/plain") public String adicionaBanda(Banda banda) { banda.setId(bandasMap.size() + 1); bandasMap.put(banda.getId(), banda); return banda.getNome() + " adicionado."; } Temos uma mudana de mtodo do HTTP, de GET passou para POST. Fora essa mudana, a URL a mesma de quando listvamos todas as bandas, ou seja, http:// localhost:8080/jersey-tutorial/bandas. E agora tambm recebemos (ou consumimos) um XML que vai representar a banda. E se voc reparar bem, tambm v que o nosso mtodo recebe uma banda como parmetro. isso mesmo que voc est pensando, o objeto banda instanciado pelo Jersey e ser preenchido com os valores do XML que vierem no contedo da requisio. O problema que agora no temos como testar usando simplesmente o navegador, porque o padro que ele execute as requisies como GET, e no teramos como enviar o XML contendo as informaes da nova banda. Para quem usa Firefox, uma opo utilizar o add-on Poster, que permite customizar a requisio de vrias maneiras, alterando headers, adicionando contedo, etc. Outra opo para quem usa linux, usar o comando curl. Veja um exemplo para adicionar uma banda: $ curl -X POST -H "Content-type:text/xml" \ -d "<banda><nome>Teste</nome><anoDeFormacao>2010</anoDeFormacao> </banda>" \ http://localhost:8080/jersey-tutorial/bandas O parmetro -X serve para alterar o mtodo HTTP. O -H serve para alterar o cabealho da requisio. Nesse caso precisamos alterar para informar que estamos enviando um XML. O parmetro -d so os dados que sero enviados no contedo da requisio. E por fim passamos a URL.

Abaixo temos o restante do exemplo de CRUD, com as operaes para atualizar e remover bandas. O exemplo com PUT bem semelhante ao de adicionar uma nova banda, a diferena que devemos atualizar uma banda j existente. J o exemplo do DELETE ainda mais simples, pois no precisamos consumir nenhum XML, apenas identificamos o id pela URL e exclumos a banda correspondente. @Path("{id}") @PUT @Consumes("text/xml") @Produces("text/plain") public String atualizaBanda(Banda banda,@PathParam("id") int id) { Banda atual = bandasMap.get(id); atual.setNome(banda.getNome()); atual.setAnoDeFormacao(banda.getAnoDeFormacao()); return banda.getNome() + " atualizada."; } @Path("{id}") @DELETE @Produces("text/plain") public String removeBanda(@PathParam("id") int id) { bandasMap.remove(id); return "Banda removida."; }

Concluindo
Esta foi uma rpida introduo ao JAX-RS e ao Jersey, apenas para servir de ponto de partida. Existem muito mais detalhes na documentao oficial.

You might also like