segunda-feira, 24 de março de 2014

Implementando uma API REST

Bom dia, e boa semana! Nada como começar com um novo tutorial: Implementando uma API REST, que vai lhe mostrar, além da parte puramente técnica, as vantagens de usar uma API mais fluídica e expor suas informações para o Mundo. Existe um grande número de pessoas e empresas que desejam acessar o que você já tem, mas que esconde sob os escombros de frameworks corporativos. Monstros como SOAP e XML, abominações como EJB ou mesmo horrorosos "Portais" de conteúdo, que nada mais fazem do que criar camadas e mais camadas sobre suas informações, afastando mais ainda os seus clientes de você. 




Lançado antes do tempo...

Em 2007, ano em que a minha filha mais nova nasceu, eu lancei um livro chamado "Web 2.0 e Mashups, reinventando a Internet", cujo objetivo era mostrar como expor informações combinando o que já existe, de maneira a agregar maior valor aos websites. Apesar de ter vendido relativamente bem, não foi um grande sucesso. Nem mesmo a Editora compreendia exatamente o que era um "Mashup", e os desenvolvedores, "babando" com as "novidades" do Java EE, não prestaram muita atenção ao assunto. O livro era revolucionário por vários aspectos, inclusive por mostrar que existe vida fora do Java!

Eu já falava de REST, JSON e Ajax, quando isso tudo ainda era novidade...

O livro ainda está disponível e você pode adquiri-lo nas livrarias: 
E eu acredito firmemente que vale a pena escrever uma edição revista e atualizada, pois agora, temos mais alguns componentes a serem considerados: HTML 5, Mobile e Node.js. (veja minha série sobre arquitetura diluída e meu artigo que mostra exatamente estas três tecnologias em conjunto). 


Eu sempre acreditei que o negócio do futuro seria reempacotar informações, dando um novo toque a elas, mesclando-as com outras informações. Mesmo sem produzir novo conteúdo, podemos criar uma nova informação, apenas mudando sua forma, seu canal ou misturando-a com outros dados. Eu acho que muitas empresas e organizações tem verdadeiros tesouros, escondidos em "baús" corporativos, e é hora de botar isso pra fora, expondo ao grande público. A Sociedade do século 21 não tolera mais segredinhos.

Bem, eu ia escrever outro livro, desta vez focando em uma API REST. Talvez eu até faça isso, mas, como tenho recebido vários pedidos para escrever mais sobre o assunto, resolvi postar essa nova série de tutoriais sobre API REST. Espero que você goste e compartilhe com os amigos. Sim! Compartilhe no Google+, no Facebook, no Twitter, ou seja, na "tribo" que você mais gostar. 

Nessa primeira parte, vamos falar apenas sobre os conceitos fundamentais, e depois, vamos começar com exemplos mais técnicos.

REST

REpresentational State Transfer não é exatamente uma tecnologia ou protocolo, mas uma nova arquitetura de comunicação entre provedor e consumidor de serviços.

Ele utiliza os métodos (http): GET, POST, PUT e DELETE para transferir o estado de um objeto interno no servidor.

O REST é, por natureza, stateless ou seja o protocolo não mantém informações de estado. Apenas transfere o estado de objetos entre o produtor e o consumidor.

O método GET serve para obter o estado atual de um objeto no Servidor e o método POST para alterar este estado, acrescentando informações. O método PUT serve para substituir totalmente o estado do objeto no servidor pelo que está sendo enviado e o método DELETE serve para eliminar um objeto.

Os objetos no REST são chamados de RECURSOS (resources) e possuem sua própria URI. Cada recurso pode ser acessado independentemente e expõe apenas os quatro métodos para alteração ou troca de estado.

Recursos

Um recurso disponibilizado via REST possui uma única URI que o identifica. Por exemplo, "http://minhaloja.com/produtos/405934". Isto denota um produto, cujo identificador é 405934, e que pode ser acessado unicamente através dessa URI. É algo como um "permalink"... Uma vez que publicamos uma interface REST, devemos manter a sua estabilidade, pois esta é uma das bases de todo o estilo arquitetural REST. 

Podemos expor vários recursos, de diferentes tipos, para o mundo. Nossa interface pode até permitir que os usuários criem novos recursos, alterem os já existentes ou mesmo os apaguem. Tudo depende da exposição que fazemos em nossa API, com relação aos métodos HTTP

API REST

Uma API REST é o conjunto formado por:
  • Formato de URI;
  • Parâmetros;
  • Métodos disponíveis.
Por exemplo, no artigo "Arquitetura diluída: "limando" o Java EE !", eu expus uma pequena API REST (só implementei parte dos métodos). Vamos ver o que está sendo atendido pelo Webservice node.js:

  • URI básica: "/mb", sem parâmetos, com método GET: Retorna o arquivo "index.html";
  • URI: "/mb/server/session/:username/:password", GET: Faz "logon" usando o usuário e senha, passados como extra-path;
  • URI: "/mb/server/messages", POST: Recebe a sessão como conteúdo JSON e lista as mensagens do usuário;
E tem mais algumas... O importante é que não existe um "WSDL" descrevendo o Serviço, logo, é preciso manter certa coerência com o que fazemos.

RESTful-URI x Non RESTful-URI

Tem havido muita discussão saudável sobre o que seria uma URI REST ou não. Ainda não existe (graças a Deus) um padrão para isso, embora alguns "Framework Darklords" estejam tentando domar o REST, ele ainda é muito selvagem. 

Mas existem alguns princípios que devem guiar a criação de uma API REST, usando RESTful URIs. Tem um excelente artigo, do blog "2PartsMagic", que resume bem as características de uma RESTful URI, e eu selecionei algumas características com as quais estou plenamente de acordo, e mesclei com outros conceitos que considero relevantes:
  1. A URI deve ser curta;
  2. Deve seguir uma estrutura de árvore, permitindo o "drill-down" e a sumarização. Por exemplo, na URI "/produtos/405934", se eu remover o código do produto, deve ser possível obter uma lista de produtos, e, se eu acrescentar: ".../foto" à URI, deve ser possível ver a foto do produto "405934";
  3. Deve usar substantivos e não verbos;
  4. Deve retornar um "Content-type" com base nos HEADERS do Request, e não em informação da própria URI;
  5. Só usar querystrings para filtrar listagens, por exemplo: "/produtos?tipo=1", e não para identificar produtos, por exemplo, ao invés de "/produtos/id=405934", devemos usar: /produtos/405934";
Esses conceitos são fáceis de aceitar, porém, existe mais um: "Stateless", que requer uma análise. Segundo o próprio artigo citado, a URI deve ser livre para ser utilizada por qualquer um. Por exemplo, se eu enviar a URL completa por email, (http://...) qualquer pessoa deve poder obter o recurso, sem necessidade de fazer "logon". 

Isso é muito bonito para informações públicas, mas eu acredito que enviar informações de sessão é uma maneira de permitir o uso de REST em aplicações que restringem o acesso aos dados. Outra maneira de fazer isso seria deixar a autenticação por conta do HTTPS, exigindo certificado de Cliente. Mas, de qualquer forma, a URL não seria navegável por qualquer pessoa. 

Não devemos ser muito críticos com relação a isso, afinal de contas, os próprios provedores de informação, como a Google, usam URIs que não seguem exatamente todos esses conceitos. Um exemplo: 

https://maps.googleapis.com/maps/api/place/nearbysearch/xml?language=pt&location=-22.951913,-43.210481&radius=100&sensor=false&key=****

Eu omiti a minha "api-key". Essa URL permite pesquisar tudo o que há por perto de uma localização geográfica, mas exatamente, um ponto próximo à estrada do Corcovado, no Rio de Janeiro. Note que há três "violações" dos conceitos de RESTful URI: uso de verbo (nearbysearch), identificação de tipo de resposta na URL (xml) e passagem de identificador (api-key). 

Eu acho que a Google não está se importando muito com isso, e nem nós, usuários, pois ela continua a expor seus serviços usando uma interface REST. Podemos até obter cada localização individualmente, através de sua latitude e longitude. 

JSON

O JSON (Javascript Object Notation) é um formato de troca de dados que também serve para serializar objetos. Um objeto na memória pode ser transformado em um formato independente de linguagem e ser transportado por qualquer meio até o seu destino, de maneira semelhante ao que é feito com o XML, pelo framework JAX-WS.

Utilizamos o JSON para troca de dados entre funções de APIs existentes na Web e é muito utilizado em Mashups. 

Eis alguns casos que requerem o uso de JSON como interface de troca de dados:
  • Google: Usa para várias APIs, como Google Places, por exemplo;
  • Flickr: Usa para buscar e compartilhar fotos;
  • Twitter: Usa para acessar o microblog;
  • Yahoo: Várias APIs (busca web, busca imagens etc);

É uma alternativa muito utilizada como contrapartida ao XML na troca de mensagens entre o cliente e a API. 

Um Objeto JSON é definido como um conjunto de nomes e valores, separados por dois pontos, e delimitados por vírgulas. Este conjunto de nomes/valores representa as propriedades do objeto sendo definido. O objeto todo fica delimitado por chaves. Veja a sintaxe básica:

objetoJSON = {nome1:valor1[,nome2:valor2[,...,nomeX:valorX]]}

Vejamos um exemplo simples:

var objeto = {"nome" : "Fulano", "endereco" : "rua x numero y",  "codigo"   : 12345};

Neste exemplo estamos definindo um objeto contendo as propriedades: "nome", "endereço" e "codigo". E podemos acessar essas propriedades de forma muito simples: "alert(objeto.nome)".

Os objetos JSON podem ter funções agregadas (métodos), por exemplo: 

{
    "nome": "fulano",
    "funcao": "function(){ alert("ok"); }"
}

Existem duas vantagens imediatas de usar JSON: 

1. É fácil de entender;
2. É Javascript! Não precisa de nada para poder transformar em objeto;

Os valores das propriedades do JSON não precisam necessariamente ser strings ou números. Podemos ter Arrays também. Para isto, delimitamos os elementos do array entre colchetes "[" e "]": 

{nome : [valor1, valor2, ... , valorX]}

Por exemplo: 

    var aluno = {"nome":"fulano",  "notas": [10,5,7]};

Neste caso definimos uma propriedade "notas" que é um array contendo três elementos do tipo numérico. 

O valor de uma propriedade pode ser também um objeto JSON ou Javascript:

{nome : [ 
{<objeto JSON1>}, {<objeto JSON2},...,{<objeto JSON3>}]};

Confuso? Não. Veja um exemplo prático:

var pessoas = {"dados":[
               {"nome":"maria","email":"maria@teste.org"},
               {"nome":"pedro","email":"petro@xpto.com"},
               {"nome":"paulo","email":"paulo@abcd.com"}
               ]};

A propriedade "dados" é um array contendo três elementos que, por si só, são objetos JSON. 

Ajax

Ajax significa Assincronous Javascript And Xml, uma técnica para criação de páginas web dinâmicas com carregamento de conteúdo assíncrono.

O principal motivador para o uso do Ajax é melhorar a experiência do usuário com o site, através de maior responsividade da página. Com esta técnica evitamos que o usuário fique parado aguardando a renderização total do conteúdo.

Além disto podemos fazer com que a página se modifique e se atualize sem necessidade de fazer um refresh (operação de ida e volta ao servidor web). Tudo pode ser feito no próprio Browser do usuário.

Na verdade o Ajax é uma releitura das técnicas de script dinâmico com o uso de um objeto chamado XmlHttpRequest, capaz de enviar requisições http de dentro de scripts Javascript. Seu uso por grandes provedores de soluções, como o Goole, popularizou a técnica. 

Um exemplo de uso de Ajax um pouco antigo, mas que funciona:

Ele é um pouco antigo, por dois motivos: 1 - pessoas modernas não usam XML, e 2 - faz o request manualmente. Ele é altamente dependente de versão de navegador, logo, seu uso pode trazer muita dor de cabeça a você. Agora, usamos frameworks mais simples, como o jQuery.

jQuery

O jQuery é basicamente uma biblioteca Javascript, que facilita o uso de Ajax em aplicações HTML. Ele abstrai de tal forma a comunicação com o Servidor, que torna tudo extremamente mais simples.

Para usar o jQuery, nós fazemos o seguinte:

  1. Carregamos o arquivo javascript dele;
  2. Criamos alguns seletores para elementos em nossa página;
  3. Criamos as funções de "callback" para os eventos que nos interessam, baseados nos seletores.
Nessa primeira parte do Tutorial, não vamos entrar em muitos detalhes, mas vamos mostrar como funciona. Vamos rever a nossa página HTML 5 do artigo anterior: 

Agora, vamos identificar as três tarefas que enumerei, para uso do jQuery:

1 - Carregando o arquivo javascript do jQuery:

<html>
<head>
    <title>Microblog</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>

Existem vários repositórios de onde você pode baixar o jQuery, inclusive, pode copiá-lo para o seu próprio site, o que não é recomendado, afinal de contas, vai perder as atualizações.

2 - Criando Seletores:

$("#refresh").click(function(){
   updateMessages(); 
   });

Podemos criar seletores para qualquer elemento da página, sejam botões, caixas de texto etc. E também podemos referenciá-los por tipo de objeto ou "id". Neste caso acima, estamos selecionando o evento "click" do botão cujo "id" é "refresh".

3 - Criando funções de "callback":


$("#logon").click(function(){
    if (!$("#username").val()) {
     window.alert("Informe o username");
    }
    else {
     if (!$("#password").val()) {
      window.alert("Informe a password");
     }
     else {
      $.get("/mb/server/session/" 
        + $("#username").val()
        + "/"
        + $("#password").val(),
        function(responseTxt,statusTxt,xhr) {
         if (xhr.status == 200) {
          sessao = responseTxt;
          alert("Logon ok");
          showUser();
          updateMessages();
         }
         else {
          alert("Erro: " + statusTxt);
         }
        }
        );
     }
    }
});

Neste exemplo, criamos um seletor para o botão "logon" e criamos código de "callback" para o evento "click".

E podemos alterar o próprio conteúdo dos elementos da página, com os objetos que recebemos via Ajax. Por exemplo, este comando jQuery invoca um Webservice REST e trata a resposta:


$.get("/mb/server/session/" 
        + $("#username").val()
        + "/"
        + $("#password").val(),
        function(responseTxt,statusTxt,xhr) {
         if (xhr.status == 200) {
          sessao = responseTxt;
          alert("Logon ok");
          showUser();
          updateMessages();
         }
         else {
          alert("Erro: " + statusTxt);
         }
        }
        );

Não se preocupe em tentar entender tudo agora. Vamos explicar passo a passo nos próximos posts. Veja que criamos um REQUET GET para a URI: "/mb/server/session" e passamos o conteúdo de dois elementos "INPUT" para ele, como extra-path. Depois, no código de "callback", testamos se a resposta foi OK (status 200), e invocamos uma função (updateMessages()).

Podemos manipular o conteúdo dos elementos HTML com o valor da resposta:


function updateMessages() {
 if (!sessao) {
  alert("Tem que logar antes!");
 }
 else {
  $("#mensagens").empty();
  $("#mensagens").text("... aguardando ...");
  $.postJSON("/mb/server/messages", sessao, 
    function(resposta) {
        var lista = resposta;
        $("#mensagens").empty();
        for (var x=0; x < lista.length; x++) {
         var mensagem = lista[x];
         $("#mensagens")
                                         .append("<hr>" 
                                         + new Date(mensagem.map.data.map.$date) 
                                         + ", " + mensagem.map.texto);
        }
      }
    ); 
  
 }
}

Estamos adicionando a resposta, devidamente fomatada, à DIV cujo "id" é "mensagens".

Conclusão

Neste primeiro "post" do tutorial, falamos sobre o que vem a ser uma API REST, e quais são as tecnologias mais relevantes (REST, JSON, Ajax e jQuery). Nos próximos posts, vamos aprofundar o estudo, criando um pequeno tutorial para você codificar. Aguarde!