Desvendando Serviços Web RESTful – Parte 1

Versão 1.0

23.06.2014


Este é o primeiro artigo de uma série de artigos sobre serviços web RESTful. Este começa pelos principais conceitos dos serviços RESTful e alguns aspectos envolvendo o seu projeto. É apresentado o emprego do padrão Data Transfer Object (DTO) no projeto, bem como estratégias para diminuir o esforço extra advindo no uso desse padrão. A parte 2 é mais prática e apresenta o serviço RESTful do ponto de vista do protocolo HTTP.

As famosas IDE’s Java (Eclipse, Netbeans) facilitam o desenvolvimento e abstraem todo o conhecimento da dinâmica por trás do desenvolvimento do serviço. O deploy de um serviço simples pode ser feito em questão de minutos. Apesar dessa mágica, é importante dominar os conceitos básicos dos serviços e conhecer o que realmente ocorre por detrás dos panos. Principalmente pelo fato que quando sua aplicação ou serviço não está se comportando de maneira adequada, você precisa verificar se aquela requisição foi enviada como esperado ou entender como foi a resposta recebida.

Um serviço web RESTful trata-se de um modelo para integração de sistemas que tem como base o protocolo HTTP e padrões abertos como o XML e JSON. É um modelo semelhante ao da Web (cliente servidor), a diferença é que ao invés de se ter requisições para código HTML (páginas), o cliente consume informações (recursos) oferecidos pelo serviço em termos de XML/JSON. O cliente aqui pode ser uma aplicação para celular ou uma aplicação web desenvolvida em qualquer tipo de plataforma.

O serviço web provê um conjunto de informações e responsabilidades bem definidas, entretanto elas somente fazem sentido quando consumidas (utilizadas) pelos clientes. O consumo inicia-se disparando a execução de métodos no serviço com o intuito de receber informações de interesse para a aplicação. Todo o processo é comandado pelo cliente que inicia e dá um significado aos dados recebidos.

O RESTful é todo baseado nas tecnologias web e no protocolo HTTP. Os recursos que queremos usar são identificados unicamente através de URI’s e os métodos do protocolo HTTP são utilizados para operar sobre determinado recurso. Por exemplo, o POST é usado para criar um novo recurso; o GET para lê as informações atuais do recurso; o PUT para atualizar um recurso; e o DELETE para deletar um recurso.

A URI é nada mais do que um hiperlink que nomalmente vem após o domínio do serviço. Ele é organizado de modo a identificar unicamente todos os recursos ofertados pelo serviço. Por exemplo, ao usar a API do Google Places, se quisermos ter acesso aos lugares próximos da gente (operação GET), a URI é /maps/api/place/nearbysearch. Outras URI’s são /maps/api/place/textsearch e /maps/api/place/radarsearch que identificam outros tipos de buscas.

O principal fator para interoperabilidade dos serviços web é que os dados são trocados utilizando padrões abertos como o XML e JSON. Do lado do cliente, ao recuperar informações dos recursos (GET), os dados recebidos pelo cliente estão num formato inteligível. E da mesma forma quando queremos criar novos recursos (POST), os dados são enviados no formato que o serviço também entende. Na parte 2 iremos exemplificar esses e outros casos no consumo de um serviço web real.

Do ponto de vista do projeto do serviço, o desenvolvedor representa as mensagens XML/JSON a partir dos objetos do domínio (por exemplo, clientes, produtos, etc.). Para cada requisição que chega os dados JSON/XML são transformados em objetos, em seguida um processamento é realizado e o serviço devolve uma resposta para o cliente. No lado do cliente, o cliente transforma o XML/JSON em objetos que passam a ser utilizados na aplicação. A figura abaixo ilustra esse cenário que ocorre numa típica requisição POST, onde o cliente envia e recebe os dados em XML/JSON.

Visão Geral das etapas de serialização/deserialização numa requisição

Visão Geral das etapas de serialização/deserialização numa requisição

Esse é um processo de serialização e deserialização feito tanto no cliente como no servidor e que utiliza a rede como meio para transportar os dados. Diversos frameworks como JAXB, XStream, GSON e Jackson, podem ajudar nessa tarefa de mapeamento de objetos para JSON/XML. O desenvolvedor precisa apenas anotar as classes (seus atributos e métodos) que o framework transforma os objetos do domínio em XML/JSON como também em recupera-o de volta. Dessa forma, os desenvolvedores trabalham apenas no nível dos objetos e ficam livres da tarefa ardua de usar API’s especificas para gerar e fazer o parser de XML/JSON.

O grande problema em usar os próprios objetos da camada de domínio para representar as estruturas de requisição ou resposta é torná-los fortemente acoplados. Essa dependencia faz com que qualquer alteração feita no modelo de objeto repercuta nas respostas enviadas para os clientes, o que implica em mudanças no lado do cliente. Do mesmo modo, uma mudança na estrutura de requisição ou resposta pode exigir que o modelo de domínio seja alterado.

Para resolver isso, o padrão Data Transfer Object (DTO) é empregado para representar em novas classes as requisições e respostas, bem como a lógica para serialização e deserialização. Com o DTO é criado uma camada responsável apenas pela manipulação das mensagens. Dessa forma, tanto a manipulação das estruturas de requisições e respostas quanto o modelo de domínio podem variar de forma independente.

O DTO são classes que representam apenas os dados das mensagens e não possuem regras de negócio. Originalmente, sua motivação foi reduzir o número de chamadas a uma interface remota [2], quando os dados necessários estavam espalhados no grafo de objetos do domínio. Apesar disso, ele acabou sendo usado no cenário de serviços web para desacoplar a manipulação das mensagens das entidades do domínio.

Outra vantagem do DTO é o seu reuso no lado do cliente. Normalmente essa tarefa é feita reusando as classes do próprio domínio do serviço ou então criando novas classes no lado do cliente. Porém, reusar o domínio do serviço causa forte acoplamento da aplicação com o domínio e muitas vezes esse reuso não é possível devido a como ele foi projetado. Por exemplo, o reuso de um domínio anotado com JPA numa aplicação Android, apesar de ser possível, deve ser gerenciado.

A figura abaixo resume a estrutura geral de um serviço web com o uso de DTO. Os Domain Objects são os objetos do domínio e descrevem a lógica do serviço. Os DTO Objects representam as requisições e respostas e podem ser usados tanto no lado do cliente como no lado do servidor. Normalmente ele é criado como um módulo separado que é reusado no cliente. Com o uso do DTO é preciso mapear os objetos do domínio nos objetos DTO. Afinal o serviço é implementado em termos destes.

Estrutura do serviço com Data Transfer Objects (DTO)

Esse esforço extra pode ser considerado uma desvantagem da abordagem DTO, pois demanda trabalho para criar os objetos DTO a partir dos objetos do domínio e vice e versa. Para facilitar essa tarefa, existem diversos frameworks que fazem esse trabalho automaticamente. Soluções como Dozer e Automapper podem ser usados nessa tarefa enfadonha. Em cenários mais simples, quando o objeto DTO é semelhante ao objeto do domínio, nenhuma configuração é necessária. O DTO é transformado em JSON/XML usando frameworks como JAXB, XStream, Jackson, etc.

DTO de forma geral auxilia na manutenção do código do serviço diminuindo o acoplamento entre a manipulação da mensagens e o domínio, além de promover reuso de código no lado do cliente. Apesar no esforço extra em manter novas classes, estrategias de mapeamento objeto-objeto facilitam o uso desse padrão.

Criar um serviço RESTful passa não só pelo dominio das ferramentas (API’s, frameworks e IDE’s) usadas para desenvolvê-lo. É necessário também saber o que acontece de fato quando uma requisição chega no servidor e como ocorre o uso do serviço pelo cliente (consumo do serviço). É essencial entender como são as requisições e as repostas durante a comunicação, além de dominar como o protocolo HTTP é usado pelo RESTful. A parte 2 desse artigo apresenta como o serviço RESTful utiliza o HTTP durante a comunicação.

Referências

Service Design Patterns: Fundamental Design Solutions for SOAP/WSDL and RESTful Web Services. Robert Daigneau. Addison-Wesley.

Artigo Martin Fowler Data Transfer Objects