A especificação JAX-RS é uma ótima opção para criar web services REST e fornece meios de desenvolver componentes server-side, mas não descreve como os desenvolvedores devem desenvolver seus componentes client-side em Java, e essa já é uma das promessas para a próxima release do JAX-RS.
Pelo fato de nossos serviços RESTful serem URIs e a forma de acesso a estes serviços serem os próprios métodos HTTP, podemos trabalhar diretamente com requisições HTTP ou utilizar bibliotecas para facilitar este trabalho. Felizmente é relativamente fácil trabalhar diretamente com requests e responses HTTP, e as linguagens mais populares de programação possuem métodos/bibliotecas HTTP, como por exemplo, urllib2 e httplib em Python, libcurl em PHP, HTTPWebRequest em C#, open-uri em Ruby, e o pacote java.net.* e o projeto HttpClient da Apache para Java, entre outros. Mas para qualquer linguagem que seja feito a requisição ao serviço RESTful, temos que passar por alguns passos, conforme segue:
- Montar os dados que irão trafegar pelo requisição HTTP, como a URI, HTTP header (se houver), e o método HTTP desejado.
- Formatar estes dados como uma requisição HTTP, e enviá-lo para um servidor HTTP apropriado.
- Efetuar o parsing dos dados retornados (XML, JSON, etc..) para as estruturas de dados que o seu programa precisa.
Para facilitar a pesquisa, montamos um pequeno guia, para os desenvolvedores e estudiosos que querem aprender um pouco mais sobre REST, onde iremos apresentar algumas bibliotecas para teste e consumo de serviços RESTful.
cURL
Se o intuito for apenas testar os serviços REST desenvolvidos e validar o retorno, o mais simples é utilizar ferramentas existentes na web como é o caso da biblioteca cURL, que é uma ferramenta de transferência de arquivos entre cliente-servidor desenvolvida em C, e suporta protocolos como HTTP, HTTPS, FTP, FTPS, etc.
A listagem 1 apresenta alguns exemplos de como fazer uma requisição GET e POST com uso da biblioteca cURL, como podemos ver, ela não possui uma interface gráfica, sendo uma ferramenta de linha de comando.
Fazendo uma requisição (GET), passando como parâmetro de headerv tipo de conteúdo json, (-H "Accept:application/json")
// Fazendo uma requisição POST, passando como query parameter name = JumboComLtda
$ curl -d name=JumboComLtda http://localhost:8080/Contatos/resources/customers/2/cliente/
// Excluindo um registro com DELETE, pelo parâmetro –X
$ curl -v –X DELETE http://localhost:8080/Contatos/resources/customers/99/
Registro excluído com sucesso !
Listagem 1: Uso da biblioteca cURL.
Referências:
- cURL - Site Oficial http://curl.haxx.se/
- Artigo Testing RESTful WebServices Made Easy (em inglês), publicado na revista Linux 4You em Maio de 2009.
- RESTClient Cookbook, vários receitas e demonstrações de como extender o RESTClient.
RESTClient
RESTClient é uma aplicação Java própria para auxiliar nos testes de serviços RESTful, complementar a isto, ela pode ser utilizada para testar Web Services POX (Plain Old XML) sobre HTTP. Para utilizar, basta efetuar o download do arquivo jar (com dependências) da ultima versão, no momento que escrevo este artigo, a versão mais recente é a versão 2.3, e vem com duas opções.
- RESTClient 2.3 GUI: restclient-ui-2.3-jar-with-dependencies.jar
- RESTClient 2.3 Command-line: restclient-cli-2.3-jar-with-dependencies.jar
A versão GUI, é uma aplicação Swing com diversas opções, e bem conhecida de quem trabalha com o RESTClient desde suas primeiras versões, e a outra versão "cli" é para execução batch de arquivos .rcq. Para começar utilizar a versão em Swing, basta digitar o seguinte comando (A aplicação requer Java 6 para rodar):
$java -jar restclient-ui-2.3-jar-with-dependencies.jar
Após executar a aplicação, deverá ser apresentado a tela conforme ilustra a Figura 1.
Figura 01 - Interface Swing do RESTClient.
Pela aparência da interface gráfica, podemos deduzir facilmente o modo de utiliza-lá, basta digitar no campo URL o caminho desejado, selecionar algum método HTTP na aba Method, e executar a consulta clicando no botão [>>]. O resultado será apresentando no bloco HTTP Response.
Funcionalidades
Com RESTClient, podemos fazer qualquer tipo de requisição HTTP (GET, PUT, POST, DELETE, HEAD, OPTIONS, TRACE), ainda existe o suporte a SSL e a possibilidade de adicionar parâmetros de Header adicionais.
É possível salvar as requests, responses, e o Response Body (atráves do menu File > Save Request, ou Save Response, Save Response Body), o que é útil para testes de regressão, que podemos utiliza-los posteriormente na versão de linha de comando.
RESTClient ainda vem com o Conteiner Jetty embutido, que possui um Servlet que imprime os detalhes das requisições submetidas a ele. Para iniciar o servidor basta acessar o menu Tools > Opção Start Trace Server (subirá na porta 10101).
E por fim, uma das funcionalidades mais interessantes é o seu suporte integrado para testes, que podem inclusive ser escritos em Groovy, o suporte a testes é baseado no JUnit 3.x e os tests são atachados a cada requisição. Para iniciar os testes, na aba "Test Script", clique o no botão Insert Template, RESTClient irá criar o código para você, conforme mostra a Listagem 02:
// The test class name should end with `Test'--this is a convention: public class TemplateClassTest extends org.wiztools.restclient.RESTTestCase{ // Test method names should start with `test': public void testStatus(){ if(response.getStatusCode() != 200){ fail("This will fail the test!"); } } }Listagem 2: Template de Test gerado pelo RESTClient.
A partir da versão 2.3, RESTClient possui uma versão em linha de comando, está versão é utilizada para executar requisições de forma batch e armazenar o resultado dos testes. Para executar está versão, basta na linha de comando executar:
$java -jar restclient-cli-2.3-jar-with-dependencies.jar -o /temp/diretorioResponse *.rcq
Esse comando, irá executar todos as requisições contidas nos arquivos de extensão (.rcq) no diretório de execução atual, e irá salvar as responses (na extensão .rcs) no diretório /temp/diretorioResponse. E por fim, o RESTClient, imprime um resumo da execução dos testes.
Referências:
- Artigo RESTFul Web Services e a API JAX-RS na revista Mundo Java edição 35
- Artigo Testing RESTful WebServices Made Easy (em inglês), publicado na revista Linux 4You em Maio de 2009.
- RESTClient Cookbook, vários receitas e demonstrações de como extender o RESTClient.
Testando Web Services RESTful no NetBeans.
Para quem é usuário do NetBeans, uma outra opção para testar Web Services RESTful é utilizar o suporte do próprio IDE, com um projeto Web criado e os serviços RESTful devidamente configurados, é possível testá-los clicando com o botão direito do mouse em cima do projeto e selecionar a opção “Test RESTful Web Services” (Figura 02), lembrando que está opção só estará disponível, se o projeto WEB possuir serviços WEB.
Figura 02 -Suporte a REST no NetBeans.
Ao selecionar esta opção, será feito o build e o deploy da aplicação web, e ao final do processo será disponibilizado uma página de testes web, como mostra a Figura 03.
Figura 03 - Tela de testes de Web Services RESTful
Na página apresentada é possível testar todos os serviços disponíveis, criar novos parâmetros para a requisição (botão “Add Parameter”), e também é possível selecionar o tipo de método HTTP para teste e o tipo MIME de retorno.
Para iniciar o teste, basta clicar no botão “Test”, após a execução, dentro da seção Response, podemos analisar os dados de retorno, os dados do cabeçalho e o status da chamada.
Além disso, de acordo com os serviços criados, o NetBeans ainda gera o arquivo WADL, visível no canto superior esquerdo da Figura 03.
Referências:
- NetBeans - Site Oficial: http://netbeans.org/
- Creating a RESTFul Web Service Using NetBeans - Tutorial do site da Sun.
JAXB
JAXB (Java Architecture for XML Binding) fornece a API, as ferramentas e um framework que automatiza o mapeamento entre documentos XML e objetos Java. Ou seja, fornece compiladores que compilam Schemas XML para objetos Java. Em tempo de execução podemos deserializar (unmarshal) o conteúdo de um arquivo XML para representações Java.
Além disso, podemos acessar, alterar e validar a representação Java contra regras de um Schema e por fim, podemos serializar (marshal) o conteúdo de um objeto Java em conteúdo XML. Veja sua arquitetura na Figura 04:
Figura 04 - Overview do JAXB.
Esta fora deste artigo um estudo mais aprofundado sobre o JAXB, mas apenas para conhecimento, a API JAXB acabou se tornando a forma padrão de mapeamento entre Java e XML, com JAXB temos anotações que nos permitem criar uma representação em Java de um Schema XML, estas anotações estão presentes no pacote javax.xml.bind.annotations, e possuem anotações associadas a pacotes Java (@XmlSchema, @XmlSchemaType, etc..), a classes Java (@XmlType, @XmlRootElement), a propriedades e campos (@XmlElement, @XmlAttribute), entre outras anotaçõe.
Para exemplificar, considere o exemplo da listagem 3, esta é uma classe POJO representando uma pessoa, com anotações JAXB. Ao fazer um marshalling de uma instância da classe PessoaBinding para XML, teremos o resultado apresentado na listagem 04.
@XmlRootElement(name="pessoa") @XmlType(name="", propOrder={"nome","idade","statusCivil"}) public class PessoaBinding { /* Construtores e Setters omitidos */ private String nome; private int idade; private String statusCivil; private String cpf; @XmlElement public String getNome() { return nome; } @XmlElement public int getIdade() { return idade; } @XmlAttribute(name="num_cpf") public String getCpf() { return cpf; } @XmlElement public String getStatusCivil() { return statusCivil; } }Listagem 03 - Classe PessoaBinding com anotações JAXB.
Listagem 04 - XML Gerado após marshalling de classe JAXB PessoaBinding.Wagner 29 Casado
A especificação do JAX-RS fornece alguns Entity Providers padrões, entre eles, provedores para JAXB, para quando o tipo de conteúdo trafegado for do tipo xml (application/xml, text/xml e application/*+xml), de modo que o programador não precisa criar código para converter um objeto Java em código XML e vice versa, facilitando muito nossa vida.
Ainda na classe PessoaBinding da listagem 03, poderíamos então, no nosso exemplo, criar um serviço RESTful cujo retorno seja a classe JAXB PessoaBinding , neste caso a declaração do serviço seria similar ao método da listagem 05.
@GET @Produces("application/xml") @Path("/NetFeijao/autor/{idPessoa}/") public PessoaBinding getPessoa(@PathParam("idPessoa") Integer id) { return dao.getPessoaAsBinding(id); // Retorna uma entidade Pessoa como PessoaBinding }Listagem 05 - Serviço RESTful cujo retorno é uma classe JAXB.
Ao fazermos o consumo deste serviço RESTful, vamos perceber que a conversão é feita automaticamente pelo entity provider padrão para XML (veja o teste na Figura 05, utilizando a ferramenta RESTClient). De maneira inversa poderíamos criar um serviço RESTful para receber requisições PUT e receber como parâmetro de entrada do método a classe PessoaBinding via HTTP Body. Conforme apresenta a listagem 06:
@PUT @Consumes("application/xml") @Path("/NetFeijao/") public void putPessoa(PessoaBinding pessoa) { // Operação de update }Listagem 06 - Convertendo código XML para objeto JAXB em chamada PUT com REST.
Referências:
- Site Oficial no java.net. - https://jaxb.dev.java.net/
- Java Architectura for XML Binding - Tutorial do site da Sun.
JAKARTA COMMONS - HTTP CLIENT
HttpClient é um subprojeto open source da Jakarta Commons que se tornou independente em 2007, e que foi concebido para facilitar o desenvolvimento de aplicações que utilizam o protocolo HTTP.
Ele é um projeto escrito totalmente em Java, e implementa todos os métodos HTTP (GET, POST, PUT, DELETE, HEAD, OPTIONS e TRACE).
Possui suporte ao protocolo HTTPS, suporte ao gerenciamento de conexões para uso em aplicações multi-thread, suporte a cookie, possui mecanismos de autenticação Basic, Digest e criptografia NTLM.
Na listagem 07, demonstramos o uso da biblioteca HttpClient, onde consumimos dois serviços RESTful, um com uma chamada GET e outra com uma chamada PUT.
public void testHTTPClient() { try { HttpClient client = new HttpClient(new MultiThreadedHttpConnectionManager()); client.getHttpConnectionManager().getParams().setConnectionTimeout(30000); final String CONTENT_TYPE = "application/xml"; final String CHARSET = "UTF8"; /* Executando chamada com método HTTP GET */ String getURI = "http://localhost:8080/ProjetoREST/NetFeijao/autores/Wagner/?idade=29"; GetMethod get = new GetMethod(getURI); Header meuHeader = new Header("CPF","123456789"); get.setRequestHeader(meuHeader); int statusCodeGET = client.executeMethod(get); String responseBody = get.getResponseBodyAsString(); System.out.println("Chamada GET"); System.out.println(" Status Code: "+statusCodeGET+" \nResponse Body:\n"+responseBody); /* Executando chamada com método HTTP PUT */ String putURI = "http://localhost:8080/ProjetoREST/NetFeijao/autores/update/"; PutMethod put = new PutMethod(putURI); StringRequestEntity requestEntity = new StringRequestEntity(responseBody, CONTENT_TYPE, CHARSET); put.setRequestEntity(requestEntity); int statusCodePUT = client.executeMethod(put); responseBody = put.getResponseBodyAsString(); System.out.println("Chamada PUT"); System.out.println(" Status Code: "+statusCodePUT+" \nResponse Body:\n"+responseBody); } catch (Exception ex) {/* OMITIDO */} }Retorno da chamada ao método.
Chamada GET
Status Code: 200
Response Body:
Chamada PUT
Status Code: 202
Response Body:
Bem vindo Wagner
Listagem 07: Consumindo serviços REST via GET e PUT com HTTPClient.
Primeiro, na linha 3 instanciamos a classe HttpClient que é o nosso agente HTTP que irá conter os atributos de persistência com cookies, e credenciais de autenticação através da classe HttpState. E também onde será armazenado uma ou mais conexões HTTP, cujo qual faremos chamadas aos métodos HTTP.
Na linha 4 atribuímos um timeout para a conexão de 30 segundos. Depois nas linhas 5, 6 e 9 declaramos as variáveis quer irão determinar o tipo de conteúdo, o character set e a URI de acesso ao serviço REST.
Na linha 10, instanciamos a classe GetMethod, que como o próprio nome indica representa o método GET, passando como parâmetro a URL do nosso serviço RESTful (getURI). Na linha 11 criamos um objeto Header, passando como parâmetro no construtor a chave e o valor que representam o parâmetro e o valor do cabeçalho, no nosso exemplo, passamos um número fictício de CPF. Na linha 12 atribuímos o objeto header para o objeto GetMethod.
Na linha 13, fazemos a chamada ao serviço RESTful via HTTP GET, e armazenamos o código de status do retorno na variável statusCodeGET, na linha 14 extraímos os dados da Response como String para a variável responseBody. Pelo fato do retorno ser em XML, poderíamos facilmente utilizar JAXB para trabalhar o retorno como um objeto Java. Finalmente nas linhas 15 e 16 imprimimos no console o retorno da chamada a estes métodos.
A partir da linha 18, iniciamos o mesmo processo, mas agora para efetuar uma chamada via método PUT, as únicas diferenças, são o uso do método PutMethod, que implementa o método HTTP PUT e o uso da classe StringRequestEntity na linha 21, com esta classe atribuímos uma entidade como String ao método PUT que será enviado junto a requisição.
Nas linhas 25 e 26 imprimimos o retorno da requisição PUT.
JavaScript:
Na listagem 08, temos um exemplo de uma função em JavaScript que consume um serviço RESTful cujo retorno é um XML.
var xmlHttp; function showCustomer(str){ xmlHttp=GetXmlHttpObject(); // omitido código do método0 if (xmlHttp==null) { alert ("Your browser does not support AJAX!"); return; } var url='http://localhost:8080/Contatos/resources/customers/58/'; xmlHttp.onreadystatechange=stateChanged; xmlHttp.open('GET',url,true); xmlHttp.send(null); } function stateChanged() { if (xmlHttp.readyState==4){ var xmlDoc=xmlHttp.responseXML.documentElement; document.getElementById("nome").innerHTML= xmlDoc.getElementsByTagName("name")[0].childNodes[0].nodeValue; } }Listagem 08 - Consumindo um serviço RESTful (retorno XML) com Ajax.
Na listagem 08, vimos um exemplo de um serviço que retorna XML, mas uma das grandes vantagens dos serviços REST, é que podemos trabalhar com diversos formatos para troca de informação de um mesmo recurso. Entre eles JSON.
JQuery é uma biblioteca JavaScript que vem chamando atenção por conta de sua facilidade de desenvolvimento, ela simplifica muito a manipulação dos elementos de um documento HTML, o tratamento de eventos e as interações Ajax para prover um desenvolvimento rápido de aplicações web, livrando o desenvolvedor de preocupações relacionadas a compatibilidade de navegadores e aderência a CSS.
A biblioteca jQuery fornece algumas funções para tratamento de requisições Ajax, ideais para o consumo de serviços REST, que reduzem muito a complexidade e a quantidade de linhas necessárias para consumir um serviço REST. Com a função $.ajax() do jQuery, conseguimos um alto nível de controle nas requisições ajax.
A sintaxe do comando é $.ajax(options), onde o parâmetro options são as propriedades que passamos para controlar como a requisição é feita e retorno da chamada.
Na listagem 09, demonstramos o uso das funções $.ajax().
$.ajax({ type: ‘DELETE’, url: "http://localhost:8080/ProjetREST/NetFeijao/autores/"+idAutor+"/", success: function(msg){ $("#alert").html(msg); } });Listagem 09 - Consumindo um serviço REST com a função $.ajax().
Na listagem 09, usamos dois parâmetros na função $.ajax(), o parâmetro type para indicar o método HTTP que queremos executar e a url de chamada.
Para tratar tipos de retorno JSON, o jQuery oferece a função $.getJSON(), utilizada para carregar dados JSON mediante uma requisição HTTP GET.
Na listagem 10 mostramos um exemplo de uso da função $.getJSON() em um serviço REST do Flickr, nós fazemos uma chamada ao serviço REST e passamos o retorno da chamada ao método de callback. Dentro da função de callback criamos a tag passando como valor o endereço da foto retornada pelo serviço REST e a incluímos na div #foto. Note que a variável data, é um map chave-valor dos dados retornados pela função REST.
$.getJSON("http://api.flickr.com/services/rest/?method=flickr.photosets.getPhotos& photoset_id=72157614488723406&format=json&jsoncallback=?", function(data){ $.each(data.photoset.photo, function(i,item){ if (item.title == foto){ $("").attr("src", "http://farm"+item.farm+".static.flickr.com/"+item.server+"/"+item.id+"_"+item.secret+"_m.jpg").appendTo("#foto"); } }); });Listagem 10 - Uso da função $.getJSON para consumo de dados no formato JSON.
É isso aí, consumir serviços REST é diversão garantida !!! E a todos um Feliz Ano Novo repleto de código \o/ !!!