Você está na página 1de 19

Conhecendo o modelo arquitetural REST Engenharia de Software Magazine 58

Neste artigo so abordados os conceitos-chave do modelo arquitetural REST, suas origens e caractersticas. Ser visto tambm as principais vantagens e desvantagens da sua aplicao e sua estreita relao com o funcionamento da prpria WEB
Artigo do tipo Tutorial Recursos especiais neste artigo: Contm nota Quickupdate, Contedo sobre agilidade. Autores: Diego Antonio Lusa e Robson Paulo Kraemer

Desmistificando o modelo arquitetural REST O desenvolvimento de sistemas distribudos uma atividade naturalmente complexa, pois envolve a criao de artefatos para o atendimento dos requisitos de negcio, bem como dos requisitos da aplicao como protocolos de comunicao e gerenciamento de transaes distribudas. Todavia, o uso de boas prticas de programao aliado a um modelo arquitetural simplista e robusto podem reduzir drasticamente o tempo necessrio para construir tais sistemas. Neste sentido, o REST (Representational State Transfer) apresenta-se como um modelo arquitetural poderoso e suficientemente maduro, capaz de atender requisitos complexos de integrao sem agregar complexidade e excesso de acoplamento. Utilizando-se de tecnologias j consagradas e de grande penetrao no mercado, o modelo arquitetural REST visa orientar o desenvolvimento de uma aplicao dentro de uma filosofia WEB-Like, fortemente baseada nos fundamentos de funcionamento da WEB, em especial, do protocolo HTTP (Hypertext Transfer Protocol). REST ganhou notoriedade por ser um estilo arquitetural simplista e ao mesmo tempo poderoso. Isso despertou o interesse da comunidade Java que, por meio da JCP (Java Community Process), iniciou um processo para padronizao tcnica deste modelo dentro da plataforma. Contudo, o uso do modelo REST deve ser adequadamente estudado, suas vantagens e desvantagens devem ser pesadas para que, ao final, os resultados para o projeto sejam realmente positivos. Neste artigo so abordados os conceitos-chave do modelo arquitetural REST, suas origens e caractersticas. Ser visto tambm as principais vantagens e desvantagens da sua aplicao, sua estreita relao com o funcionamento da prpria WEB e sua aplicabilidade dentro do mundo Java.

Em que situao o tema til Os conceitos aqui explorados podem ser utilizados em projetos de desenvolvimento de qualquer aplicao com caractersticas distribudas, seja ela Web ou no. Tambm possvel aplicar tal conhecimento na concepo de arquiteturas de integrao de sistemas heterogneos e desconexos, cujo estilo de integrao tenha caractersticas de ser do tipo on-line. A revoluo promovida pela rpida expanso do uso da internet no mundo dos negcios, em especial, do seu servio mais conhecido, o WWW, promoveu mudanas significativas na forma como as organizaes trocam informaes. Surgiram novos modelos de interao entre os consumidores e organizaes empresariais, como o B2C (Business to Customers) e B2B (Business to Business), por exemplo. Tais interaes demandam trocas de informaes entre os diferentes envolvidos nos mais variados formatos de mdia. Internamente, as organizaes tambm sofreram grandes mudanas. Houve uma migrao de responsabilidade, onde a sustentao do negcio deixou de estar unicamente nas mos dos colaboradores e passou a ser mantida pela infraestrutura de tecnologia da informao, atravs de sofisticados recursos de hardware e software. Os

processos de negcio foram automatizados e tornaram-se workflows orquestrados via software, interagindo com pessoas e outros sistemas de forma autnoma. Surgindo um modelo de processamento distribudo, de escala global, interconectado pelas tecnologias oferecidas pela internet. Novos e promissores horizontes se abriam trazendo consigo grandes desafios para a engenharia de software. Como interligar sistemas essencialmente heterognios, permitindo a troca de informaes e mantendo a mesma semntica dos dados em todas as pontas envolvidas? Como garantir segurana, integridade e consistncia nos dados distribudos? Como construir sistemas essencialmente distribudos com baixo acoplamento entre as diferentes partes? Vrias solues foram propostas para tratar destes e de outros problemas caracterstos destes tipos de aplicaes. Uma delas, talvez a mais utilizada de todas, a arquitetura orientada a servios (Service Oriented Archicteture - SOA). Neste modelo arquitetural, provedores de servio expem uma ou mais funcionalidades a diversos consumidores. A comunicao entre as partes facilitada atravs de um contrato, chamado WSDL (Web Service Description Language), que especifica o formato das mensagens, as operaes suportadas e o modelo de comunicao. Comumente, as mensagens trocadas entre provedores e consumidores est em formato XML, trafegando atravs do protocolo SOAP (Simple Object Access Protocol). Outro paradigma proposto para construo de aplicaes web distribudas ou integrao de sistemas independentes atravs da Web o REST (Representational State Transfer). Como fruto da dissertao de doutorado de Roy T. Fielding, defendida na Universidade da California, em 2000, o REST ganhou rpida aceitao na comunidade como um modelo de desenvolvimento maduro e escalvel, de grande aplicabilidade na concepo de modernos sistemas web essencialmente distribudos. No modelo arquitetural REST, o protocolo HTTP (Hypertext Transfer Protocol) tem seus recursos amplamente explorados, firmando-se como um modelo de comunicao seguro, amplamente testado e, acima de tudo, padro. Alm do HTTP, outras tecnologias padro de mercado so utilizadas, como XML (eXtensible Markup Language), JSON (Javascript Object Notation) e URI (Uniform Resource Identifier), por exemplo. Ao unir tais tecnologias amplamente conhecidas, o REST permite construir aplicaes web distribudas de forma rpida, robusta e com investimentos relativamente mais baixos quando comparado com outros modelos arquiteturais, como o SOA, por exemplo. Na sequncia sero apresentadas a origem do modelo REST, suas principais caractersticas e ponderaes necessrias, antes de optar por sua escolha na concepo de um projeto de software. Ao final, apresentado um exemplo simples de construo dentro do modelo REST em Java, com intuito de demonstrar a aplicabilidade do modelo em sistemas reais. As origens do REST Ao analisar o estilo arquitetural REST, pode-se inferir o quo similar so suas caractersticas s encontradas no maior sistema hypermedia distribudo atualmente no mundo, a web. Na web existe a possibilidade de navegar em portais de notcias, realizar compras em sites de e-commerce, estabelecer comunicao com outras pessoas em redes sociais, assistir vdeos e etc. Nela cada pgina, vdeo, documento acessvel chamado de recurso. Assim, pode-se entender os recursos como a fundao da arquitetura de sistemas baseados na web. Eles so as peas-chave de interesse nesse modelo de arquitetura resource-oriented. Cada um desses recursos necessita de um mecanismo de identificao para que possa efetivamente ser encontrado e manipulado. Nesse sentido a web prov o padro URI, que identifica unicamente um recurso ao mesmo tempo em que o torna enderevel e manipulvel por um protocolo de aplicao, como o HTTP. Dessa forma possvel compreender o que um recurso e como o mesmo identificado na web. Mas uma dvida ainda prevalece: como um recurso efetivamente manipulado na web?

Manipulam-se recursos atravs de suas representaes. Uma representao uma viso de um estado do recurso em determinado instante do tempo; esta viso codificada em formatos padronizados e passveis de transferncia atravs da web, como, XHTML, JSON, XML, PLAIN TEXT, CSV e etc. Toda interao com um recurso , portanto, mediada atravs de uma representao do mesmo, em que tanto o cliente quanto o servidor, convergem no entendimento da codificao daquela representao. Esse acordo entre cliente e servidor obtido em tempo de execuo, atravs de um mecanismo chamado Content Negotiation. A Figura 1 exemplifica os conceitos e mecanismos relacionados Web. Observe que a arquitetura cliente servidor utilizada e que os recursos, disponibilizados para serem acessados pela aplicao, podem ser definidos utilizando diferentes formatos de representaes como XML e JSON.

abrir imagem em nova janela Figura 1. Viso esquemtica da WEB Dessa maneira, evidencia-se que todo o intercmbio de informaes em uma arquitetura Web realizado atravs de representaes dos recursos, e no do recurso propriamente dito. Baseado nessas tecnologias, componentes e princpios arquiteturais da web, comearam a haver estudos para compreender o seu sucesso e rpido crescimento em escala global, e como essas lies arquiteturais poderiam ser estendidas para suportar o desenvolvimento atual de aplicaes distribudas baseadas na web. Roy T. Fielding, em sua dissertao de doutorado, analisa os princpios arquiteturais da web e os apresenta sob a forma de um framework de constraints, definindo assim um estilo arquitetural. Este estilo foi denominado REST (REpresentational State Transfer), o qual descreve a web como uma aplicao hypermedia distribuda, onde recursos interligados comunicam-se entre si atravs da troca de representaes de seus estados. Mas alm dessa definio, o trabalho de Fielding, da maneira como foi estabelecido, possibilitou a introduo do HATEOAS (Hypermedia As The Engine Of Application State), o qual uma das restries do conjunto que define a Interface Uniforme (conceito que ser definido mais frente neste artigo).

HATEOAS permite estabelecer um padro em que o progresso de uma aplicao distribuda realizado atravs de transies de um estado para outro, de maneira similar a uma mquina de estados. Este modelo remete a maneira como usurios humanos interagem em websites, onde cada pgina est relacionada outra por meio de hyperlinks, e os mesmos passam a informao semntica necessria para guiar o usurio pelo processo que o mesmo objetiva. A ideia do HATEOAS no REST fazer com que este modelo no se restrinja apenas interao humanocomputador, mas que tambm seja aplicado na interao entre computadores, j que os mesmos so capazes de seguir protocolos. Adiante sero demonstrados mais detalhes de cada uma das restries arquiteturais do REST. Caractersticas do estilo arquitetural REST As caractersticas do REST esto intimamente ligadas s da prpria topologia da web, em especial, do protocolo HTTP. O modelo de interao entre os componentes ditado por uma arquitetura do tipo clienteservidor sem estado e se d atravs da troca de mensagens no formato requisio-resposta. A seguir, cada uma das principais caractersticas do modelo arquitetural REST sero detalhadas. Modelo Cliente-Servidor Especifica uma separao lgica das atribuies dos componentes dentro da arquitetura. O cliente inicia a comunicao enviando requisies ao servidor. Este, por sua vez, realiza o processamento das requisies e devolve as respostas apropriadas. Embora cliente e servidor sejam capazes de comunicar-se entre si, no h nenhuma forma de dependncia que impea a evoluo das partes de forma independente. Stateless Uma implementao que segue os princpios REST, no deve preocupar-se com a manuteno de estado no lado servidor. O nico componente que pode manter o estado dos objetos entre diferentes requisies o prprio cliente. O servidor deve receber todas as informaes necessrias para realizar o processamento requerido, sem depender de qualquer informao de estado armazenada previamente. Assim, acrescido ao modelo cliente-servidor tradicional a importante caracterstica de ser indiferente a estados, eliminando qualquer forma de acoplamento entre o servidor e seus clientes. Esta caracterstica tambm facilita o processo de escalar horizontalmente a aplicao, pois cada novo servidor instalado independe do estado de outros, bastando apenas realizar a correta configurao do ambiente. Cacheable Uma vez que o modelo arquitetural REST tem sua fundamentao no protocolo HTTP, toda a comunicao efetuada entre clientes e servidor pode ser cacheada, ou seja, armazenada temporariamente no cliente e/ou em servios intermedirios, reduzindo o tempo necessrio para resposta e aumentando a eficincia global do sistema em termos de consumo de recursos. Sistema em Camadas (Layered System) Dividir um sistema complexo em camadas estruturalmente independentes uma das outras, apresenta-se como uma boa prtica de engenharia. Cada camada liga-se s adjacentes, atravs de interfaces padres, reduzindo assim o nvel de acoplamento ao conhecimento de tais interfaces. Sistemas RESTful tm seu desenvolvimento direcionado construo em camadas, visando desacoplamento e encapsulamento das funcionalidades providas.

Interface Uniforme A comunicao entre os componentes de uma arquitetura REST se d atravs de uma interface padronizada e genrica, a qual baseia-se no uso dos verbos HTTP e na orientao recursos. Interfaces REST devem atender a quatro requisitos bsicos: Identificao dos recursos; Manipulao dos recursos atravs de representaes; Mensagens autodescritivas; Hipermdia como nico mecanismo de transio de estados. Basicamente, numa arquitetura REST existe um mapeamento um-para-um entre as operaes bsicas de criao, edio, leitura e excluso (CRUD) e os verbos HTTP POST, PUT, GET e DELETE. Esta relao definida por: POST: Deve ser utilizado para criar um recurso no servidor; GET: Deve ser utilizado para recuperar a representao de um recurso. A operao deve ser somente-leitura, idempotente, no realizando qualquer alterao de estado no lado servidor; PUT: Altera o estado de um recurso. Realiza uma atualizao; DELETE: Elimina um recurso. Code on Demand uma caracterstica arquitetural opcional, onde o cliente pode receber um trecho de cdigo do servidor e execut-lo localmente, possibilitando a expanso da funcionalidade do cliente em tempo de execuo. Embora seja uma caracterstica primeira vista muito interessante, deve ser utilizada com cuidado, pois ela reduz a visibilidade do que est sendo realizado no ecossistema REST. Benefcios da adoo do REST O desenvolvimento de sistemas uma atividade que envolve inmeros riscos. Muitas vezes, o projeto em questo estratgico para o negcio, o que torna qualquer problema ou falha dispendioso e, muitas vezes, fatal. A escolha pela adoo da filosofia de desenvolvimento A ou B prpria de cada projeto. Nem sempre a escolha justificada pelo que h de melhor no mercado, mas sim pelo que melhor se ajusta s necessidades do projeto em questo. Assim como as demais tecnologias, o REST tem seus prs e contras, que devem ser pesados no momento da escolha do caminho seguir. As vantagens do uso do REST residem nos seguintes pontos: Todos os recursos so identificados de forma nica atravs de URIs. Tal caracterstica gera maior consistncia no ambiente, pois uma vez que determinado recurso endereado por um URI, este estar vinculado ao recurso durante todo seu ciclo de vida; O uso dos verbos e cdigos HTTP de forma consistente garante uniformidade arquitetural. Qualquer cliente que entenda HTTP capaz de interagir com a aplicao REST. Essa uniformidade gera padronizao, o que um fator sempre positivo no desenvolvimento de aplicaes;

O tempo de aprendizado para aplicar o modelo REST, bem como a baixa complexidade de codificao contribuem para reduzir o tempo necessrio entre a construo da aplicao e a sua disponibilizao no mercado; O consumo de recursos de rede e necessidade de hardware reduzido, quando se compara o REST com a arquitetura orientada a servio (SOA). H menor fluxo de dados pela rede, menor quantidade de metainformao e se pode utilizar os recursos do prprio HTTP para realizar cache dos dados; Uma aplicao REST facilmente escalvel. Sua topologia pode ser modificada de forma transparente sem grandes impactos; Servios RESTFul so facilmente integrados; Os recursos do cliente podem ser melhor utilizados, reduzindo consideravelmente a carga computacional do servidor. Em termos prticos, significa que a necessidade de upgrade de hardware do servidor menor, gerando menos custos com infraestrutura; Pode-se implementar REST utilizando qualquer linguagem que fornea suporte ao protocolo HTTP; Aplicaes REST so nativamente portveis, herdando tal caracterstica da prpria WEB. Por outro lado, tem-se tambm algumas desvantagens. Algumas delas so: Ecossistemas REST esto sujeitos a todos os males que podem afetar uma aplicao web qualquer; Existncia de bibliotecas e frameworks que no do suporte pleno ao modelo REST, induzindo construo de sistemas em tese RESTFul, quando na verdade no o so. Muitas vezes tais bibliotecas dificultam o trabalho de desenvolvimento ao invs de otimiz-lo; Existe pouco ferramental REST. Isso, algumas vezes, leva o desenvolvedor a se preocupar com aspectos indiretos ao negcio da aplicao, que com outras tecnologias j estaria padronizado e disponibilizado nativamente; Tratando-se de sistemas crticos, nos quais o alto desempenho seja um requisito no funcional latente, a restrio da interface uniforme, bem como o mecanismo de cache provido pelo HTTP podem no atender de maneira satisfatria. Rest no mundo Java REST ganhou notoriedade por ser um estilo arquitetural simplista e ao mesmo tempo poderoso. Isso despertou o interesse da comunidade Java que, por meio da JCP (Java Community Process), iniciou um processo para padronizao tcnica deste modelo dentro da plataforma. Surgia ento o projeto JAX-RS (Java API for RESTful Services) (ler Nota do DevMan 1). A primeira especificao JSR 311 (ler Nota do DevMan 2) teve seu primeiro rascunho definido em 30 de maro de 2007. Este tinha como objetivos definir meios de expor os recursos de uma maneira POJO-based (Plain Old Java Object) (ler Nota do DevMan 3) por meio de um conjunto de anotaes, classes e interfaces, levando em considerao um estilo centrado no HTTP, utilizando-o no apenas como um protocolo de transporte. A especificao tambm j previa independncia de formato nas representaes dos recursos web, permitindo uma maneira padronizada de definies, de novos formatos de acordo com a necessidade de cada aplicao. Outro objetivo importante era incorporar a especificao no Java EE, alm de torn-la passvel de instalao em diversos contineres de aplicao, como Servlet e Java EE.

Nota do DevMan 1. JAX-RS

JAX-RS a soluo definida pelo JCP para o desenvolvimento de aplicaes Java seguindo o estilo de programao REST. Para isso, ela define um conjunto de APIs que fornece uma srie de anotaes, classes e interfaces para a elaborao de classes POJO. Nota do DevMan 2. JSR - Java Specification Request JSR so documentos formais que descrevem especificaes propostas e tecnologias que se pretende adicionar plataforma Java. Nota do DevMan 3. POJO POJO so objetos definidos na linguagem Java que possuem um projeto simplificado. Houve muitos rascunhos at a consolidao da verso 1.0 da JAX-RS, por meio da JSR 311 - Final Release. Porm, ao mesmo tempo em que o REST foi padronizado no ecossistema Java, foi, de certa forma, decepcionante observar que algumas restries muito importantes de seu estilo arquitetural no haviam sido contempladas nessa primeira verso. Dentre elas pode-se destacar o hypermedia. Este cenrio fez com que surgisse, cerca de um ano aps, a finalizao da JAX-RS 1.0, uma nova reviso visando manuteno da primeira verso. Esta nova verso JAX-RS 1.1 trouxe algumas melhorias e correes, porm, a lacuna do hypermedia permaneceu, o que levou seu adiamento para o prximo grande release, do projeto JAX-RS: a verso 2.0, por meio da JSR 339. A JSR 339 ainda est em processo de definio. Na data do presente artigo, o estgio Proposed Final Draft est em andamento, no entanto, as principais implementaes dessa especificao, como Jersey e RESTEasy, j esto disponibilizando verses BETA para avaliao parcial das novas funcionalidades. Dentro do escopo das mudanas que a verso 2.0 trar, pode-se destacar: Melhor suporte a Hypermedia; API cliente para o consumo de Recursos; Validao de parmetros recebidos (integrao com Bean Validation API); Filtros e interceptadores. Nas sees seguintes so apresentados exemplos prticos do uso da JAX-RS na concepo de sistemas REST. Exemplificando o uso da JAX-RS Foi apresentado um pouco da histria e da conceituao do estilo arquitetural REST. A partir de agora, ser visto um simples exemplo de como empregar REST em uma aplicao Java. O exemplo se dar com a utilizao da JAX-RS atravs da implementao RESTEasy, da JBoss. Para este artigo, foi utilizada a verso 3.0-beta-3, que a verso mais recente disponibilizada em conformidade com a JSR 339. Para o desenvolvimento desse exemplo foi utilizado um estudo de caso, que consiste na disponibilizao de uma interface REST para criao, deleo, consulta, ativao e desativao de clusters de computadores (ler Nota do DevMan 4). Nota do DevMan 4. Cluster Um cluster define um sistema distribudo composto por um aglomerado de computadores que atuam em conjunto para disponibilizar servios ou realizar tarefas especficas que exigem alto processamento.

A fim de facilitar a gesto das dependncias do projeto, ser feito o uso da ferramenta Apache Maven (ler Nota do DevMan 5), cuja finalidade facilitar o gerenciamento do projeto de software, em termos de cdigo, por meio da simplificao e padronizao dos processos de construo, relatrios e documentao do mesmo. Nota do DevMan 5. Maven O Apache Maven uma ferramenta de automao de compilao utilizada em projetos desenvolvidos na linguagem Java. O Maven permite definir atravs de um XML o projeto de software que est sendo construdo, suas dependncias sobre mdulos e componentes externos, a ordem de compilao, diretrios e plug-ins necessrios. Declarando um Recurso Os recursos so as principais peas de um ambiente arquitetural REST, pois eles que so expostos publicamente pela aplicao. Logo, deve-se identific-los dentro do domnio da aplicao para ento modelar sua disponibilizao. Dentro do estudo de caso escolhido, o recurso disponibilizado ser o cluster. Para isso, ser definida, primeiramente, a classe Cluster, que representar o recurso propriamente dito e tambm a classe Computador, a qual diretamente relacionada a um cluster. A Listagem 1 ilustra este procedimento. Listagem 1. Definio do recurso REST
@XmlRootElement(name = "cluster") public class Cluster { @NotNull private String nome; private boolean ativo; @XmlElementWrapper(name = "computadores") @XmlElement(name = "computador") @NotNull @Size(min = 1) private List<Computador> computadores = new ArrayList<Computador>(); public Cluster() {} public Cluster(String nome, boolean ativo) { this.nome = nome; this.ativo = ativo; } public void adicionarComputador(Computador computador) { computadores.add(computador); } public void removerComputador(Computador computador) { computadores.remove(computador); } ... @Override public String toString() { return getNome() + " - " + getComputadores(); } @Override public boolean equals(Object obj) { if (!(obj instanceof Cluster)) return false; Cluster that = (Cluster) obj; return this.getNome().equals(that.getNome()); } } public class Computador { private String nome; private short numeroDeCPUs;

private int capacidadeDeRAM; private int capacidadeDeHD; public Computador() { } public Computador(String nome) { this.nome = nome; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } @Override public boolean equals(Object obj) { if (!(obj instanceof Computador)) return false; Computador that = (Computador) obj; return this.getNome().equals(that.getNome()); } }

A classe Cluster um POJO, e, como pode ser visto, alm dos mtodos getters e setters, ela possui algumas anotaes Java. Estas anotaes atendem a dois objetivos: Configurar a classe para que seus objetos possam ser serializados em XML pela engine JAXB (Java Architecture for XML Binding), a qual ser utilizada para representaes em XML dos recursos nesse exemplo; Configurar a classe, para que seus atributos possam ser validados durante as requisies ao servio REST, que alteraram o estado dos objetos. Essas validaes so baseadas na Bean Validation API. Uma vez definida a classe Cluster e Computador, necessrio realizar a criao da classe que ser responsvel por disponibilizar os clusters como um servio web. Esta classe se chamar ClusterResource e definir mtodos pblicos que sero traduzidos em URIs para que possam ser acessados atravs da web. A Listagem 2 define esta classe. Listagem 2. Definio da Classe de Servio REST
@Path("/clusters") public class ClusterResource { private ClusterDatabase db = new ClusterDatabase(); @GET @Path("{nome}") @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response getByNome(@PathParam("nome") String nome) { Response response; try { Cluster cluster = db.getByNome(nome); response = Response.ok(cluster) .header("Link", generateLink(cluster)) .build(); } catch (ClusterInexistenteException e) { response = Response.status(Status.NOT_FOUND).build(); } return response; } private String generateLink(Cluster cluster) { String linkHeader = "<%s>; rel=\"%s\";"; URI uri;

if (cluster.isAtivo()) { uri = UriBuilder.fromUri("/clusters/" + cluster.getNome() + "/ativo/false").build(); linkHeader = String.format(linkHeader, uri.toString(), "desativar"); } else { uri = UriBuilder.fromUri("/clusters/" + cluster.getNome() + "/ativo/true").build(); linkHeader = String.format(linkHeader, uri.toString(), "ativar"); } return linkHeader; } @PUT @Path("{nome}/ativo/{ativar}") @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response ativarDesativarCluster(@PathParam("nome") String nome, @PathParam("ativar") boolean ativar) { Cluster cluster; try { cluster = db.getByNome(nome); cluster.setAtivo(ativar); db.atualizar(cluster); return Response.ok(cluster).build(); } catch (ClusterInexistenteException e) { return Response.status(Status.NOT_FOUND).build(); } } @GET @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Wrapped(element = "clusters") public List<Cluster> listaTodos() { return db.getTodos(); } @POST @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @ValidateRequest public Response criaCluster(@Valid Cluster cluster) { db.criar(cluster); return Response.created( UriBuilder.fromUri("/clusters/" + cluster.getNome()).build() ).build(); } @PUT @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @ValidateRequest public Response atualizaCluster(@Valid Cluster cluster) { db.atualizar(cluster); return Response.ok(cluster).build(); } @DELETE @Path("{nome}") public Response deletaCluster(@PathParam("nome") String nome) { Response response; try { Cluster cluster; cluster = db.getByNome(nome); db.remover(cluster); response = Response.noContent().build(); } catch (ClusterInexistenteException e) { response = Response.status(Status.NOT_FOUND).build();

} return response; } }

Nessa classe existem vrias anotaes Java pertencentes JAX-RS. So elas que permitem a exposio do recurso. O papel de cada uma dessas anotaes no exemplo anterior : @Path: Esta anotao visa definir o endereo (URI) pelo qual o recurso ser acessado, pode-se declar-la tanto sobre classes quanto mtodos; @PathParam: Esta anotao faz a vinculao de um valor dinmico vindo no URI template de uma anotao @Path uma varivel Java declarada como argumento de mtodo; @GET, @POST, @PUT, @DELETE: So anotaes que representam o verbo HTTP ao qual um determinado mtodo ser vinculado. Pode-se declar-las apenas em mtodos; @Produces: Tem a finalidade de especificar os media types de representaes de recursos suportados pelo servio. No exemplo, o servio disponibiliza recursos em dois formatos: XML e JSON. Caso o cliente solicite no cabealho HTTP um media type no suportado, a runtime JAX-RS retornar um erro HTTP 406 Not Acceptable. Esta anotao pode ser declarada sobre classes e mtodos. @Consumes: Tem por objetivo especificar os media types de representaes de recursos que o servio aceita, ou consome, do cliente. No exemplo, o servio consome recursos em dois formatos: XML e JSON. Caso o cliente envie o request com um media type no suportado, a runtime JAX-RS retornar um erro HTTP 415 Unsupported Media Type. Esta anotao pode ser declarada sobre classes e mtodos. @Valid: Esta anotao pertencente especificao Bean Validation API, porm, pode ser utilizada em conjunto com a JAX-RS. Sua funo no exemplo validar a entidade Cluster, ao receb-la em algum mtodo que ir alterar o estado da aplicao. Para isso, a runtime ir validar as regras definidas na classe Cluster (@NotNull, @Size). Na implementao JAX-RS RESTEasy, mandatrio que a anotao @ValidateRequest esteja sobre o mtodo cujo(s) argumento(s) deva(m) ser validado(s). Existem ainda duas anotaes especficas da implementao RESTEasy: @ValidateRequest e @Wrapped. A primeira foi explicada anteriormente, a segunda anotao utilizada para sinalizar a runtime JAX-RS RESTEasy que a mesma deve sobrescrever o nome do elemento root em uma coleo de registros para o media type XML de maneira customizada. No exemplo, o elemento root da representao XML configurado para chamar-se clusters. O nome padro collection. Mtodos pblicos: a interface de um recurso Na classe ClusterResource existem vrios mtodos pblicos. Cada um desses mtodos, somados s anotaes que definem o endereo URI (@Path), o verbo HTTP (@GET, @POST, @PUT, @DELETE entre outros) e os media types suportados (@Produces), tornam-se interfaces pblicas de acesso. Nesse ponto, percebe-se na prtica a constraint REST da Interface Uniforme. Uma vez que a interface est definida, o recurso vinculado mesma pode ser acessado e manipulado pelos clientes nos formatos suportados. A partir de agora analisaremos o funcionamento de cada um dos mtodos definidos na classe. A Listagem 3 define um mtodo que responsvel por retornar um cluster especfico de acordo com seu nome. Para acess-lo, o URI a ser utilizado o http://dominio.com/clusters/nome-do-cluster e o verbo HTTP da requisio deve ser GET. importante ressaltar que o trecho domnio.com no URI varivel de acordo com o domnio em que a aplicao foi implantada. Outro ponto a destacar que o URI para este mtodo foi composto de duas anotaes @Path, uma definida na classe e a outra sobre o mtodo, isso chamado de subrecurso, de acordo com a JAX-RS.

Listagem 3. Mtodo getByNome


@GET @Path("{nome}") @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response getByNome(@PathParam("nome") String nome) { Response response; try { Cluster cluster = db.getByNome(nome); response = Response.ok(cluster).header("Link", generateLink(cluster)).build(); } catch (ClusterInexistenteException e) { response = Response.status(Status.NOT_FOUND).build(); } return response; }

Ao chegar uma requisio para este mtodo, a engine JAX-RS extrai o nome do cluster do URI informado e o repassa para o mesmo. O retorno deste mtodo do tipo Response, o qual um tipo definido pela JAX-RS. por esta classe e suas inner-classes, como ResponseBuilder, por exemplo, que toda a mensagem de reposta ao cliente construda. No exemplo, ao encontrar com sucesso um cluster com o nome solicitado, retornada uma mensagem HTTP 200 OK contendo uma representao do cluster em questo. Esta representao por padro XML, caso o cliente no informe o desejo de outro media type, como JSON, por exemplo. Caso no exista um cluster com o nome informado, o banco de dados dos clusters lana uma exceo ClusterInexistenteException, a qual capturada e tratada, retornando uma mensagem HTTP 404 Not Found. Percebe-se um detalhe importante na linha de cdigo responsvel por construir uma resposta HTTP de sucesso. Est sendo definida uma propriedade chamada Link no cabealho HTTP. A finalidade proporcionar ao cliente a possibilidade de captura e utilizao do mesmo. Neste caso especfico do exemplo, retornado um Link Header que permite ativar ou desativar o cluster, de acordo com seu atual estado. Este link segue o padro definido na RFC 5988. importante mencionar que, para esta definio de link, foi utilizado o mtodo header(String, Object) da classe ResponseBuilder ao invs da utilizao do mtodo links(Link...) e da classe utilitria LinkBuilder, pois os mesmos no foram implementados na verso beta utilizada do RESTEasy. Contudo, altamente recomendado utiliz-los aps a especificao JAX-RS 2.0 ser efetivamente concluda. Este exemplo do link header demonstra o uso de hypermedia na aplicao. O mtodo definido na Listagem 4 tem a responsabilidade de ativar ou desativar um cluster na aplicao. Ele recebe dois parmetros: nome do cluster e uma flag indicando a ao a ser tomada. A requisio vinda do cliente no precisa conter payload, o URI obtido pelo cliente atravs do link header definido no mtodo explicado anteriormente. A construo da resposta HTTP segue o mesmo procedimento utilizado no mtodo getByNome. Um detalhe importante que a ao de ativao ou desativao do cluster executada apenas quando a requisio do cliente for com o mtodo HTTP PUT, pois o intuito alterar o estado do cluster em questo. Listagem 4. Mtodo ativarDesativarCluster
@PUT @Path("{nome}/ativo/{ativar}") @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response ativarDesativarCluster(@PathParam("nome") String nome, @PathParam("ativar") boolean ativar) { Cluster cluster; try { cluster = db.getByNome(nome); cluster.setAtivo(ativar); db.atualizar(cluster); return Response.ok(cluster).build();

} catch (ClusterInexistenteException e) { return Response.status(Status.NOT_FOUND).build(); } }

A Listagem 5 define um mtodo simples, cuja finalidade retornar uma coleo de recursos cluster. Os pontos de ateno se referem ao tipo de retorno e anotao @Wrapper, que j teve sua funcionalidade explicada. O retorno deste mtodo a prpria representao da entidade que deve ser inserida no corpo da resposta HTTP, uma lista de clusters. A runtime JAX-RS capaz de fazer esta converso e gerar uma resposta HTTP adequada, cujo cdigo o 200 OK. Listagem 5. Mtodo listaTodos
@GET @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Wrapped(element = "clusters") public List<Cluster> listaTodos() { return db.getTodos(); }

O mtodo cuja definio est apresentada na Listagem 6 responsvel pela criao de novos clusters na aplicao. Ele responde por requisies HTTP POST e aceita entidades Cluster representadas em XML ou JSON. Para este mtodo, destaca-se o uso das anotaes responsveis pela validao da entidade no servio (@ValidateRequest e @Valid), alm da classe UriBuilder, que utilitria para criao dinmica de URIs. Nesse exemplo, aps a criao do cluster no banco de dados, uma resposta HTTP 201 Created enviada juntamente com a localizao do recurso recm-criado, isso realizado atravs da propriedade Location do cabealho HTTP. Listagem 6. Mtodo criaCluster
@POST @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @ValidateRequest public Response criaCluster(@Valid Cluster cluster) { db.criar(cluster); return Response.created( UriBuilder.fromUri("/clusters/" + cluster.getNome()).build() ).build(); }

O mtodo definido na Listagem 7 similar ao mtodo criaCluster visto anteriormente. A diferena crucial que o mesmo responde por requisies HTTP PUT e, quando o recurso atualizado com sucesso na aplicao, uma resposta HTTP 200 OK retornada juntamente com a representao do recurso recm atualizado. Listagem 7. Mtodo atualizaCluster
@PUT @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @ValidateRequest public Response atualizaCluster(@Valid Cluster cluster) { db.atualizar(cluster); return Response.ok(cluster).build(); }

Por fim, o mtodo definido na Listagem 8 tem a responsabilidade de realizar a deleo de um determinado cluster da aplicao. O URI vinculado a este exatamente o mesmo do mtodo getByNome, com a diferena do verbo HTTP utilizado, no deletaCluster feito o uso do HTTP DELETE. No exemplo, o mtodo identifica

pelo URI o cluster que deve ser excludo e ento realiza esta operao junto ao banco de dados. Aps a deleo, retornada uma resposta HTTP 204 No Content indicando que o processamento da requisio foi realizado e que a resposta no possui entidade associada, ou seja, no possui contedo. Por outro lado, caso o nome do cluster passado na URI no remeta a um cluster existente, o mtodo retorna uma resposta HTTP 404 Not Found. Listagem 8. Mtodo deletaCluster
@DELETE @Path("{nome}") public Response deletaCluster(@PathParam("nome") String nome) { Response response; try { Cluster cluster; cluster = db.getByNome(nome); db.remover(cluster); response = Response.noContent().build(); } catch (ClusterInexistenteException e) { response = Response.status(Status.NOT_FOUND).build(); } return response; }

Definindo o cliente da aplicao Foi visto que uma das novidades da JAX-RS 2.0 a incluso de uma API cliente para facilitar o desenvolvimento de aplicaes RESTful. Nesse estudo de caso, foi criada uma srie de testes unitrios que realizam chamadas aos recursos por meio desta API. Esses testes unitrios so escritos com o auxlio do JUnit, uma conhecida ferramenta de testes amplamente difundida na comunidade Java. Antes da execuo de cada teste unitrio, realizada a preparao do ambiente por meio do mtodo setUp, onde so configurados a instncia do cliente REST alm do objeto representando um endpoint para a URI base da aplicao. Tambm realizada a inicializao e paralizao do servidor servlet embutido atravs do mtodo iniciarServidor e pararServidor respectivamente. Esses mtodos so invocados uma nica vez pelo JUnit durante a execuo da sute de testes. A Listagem 9 ilustra o cdigo Java que realiza essa tarefa. Listagem 9. Set Up para os Testes Unitrios
public class ClusterResourceTeste { private Client cliente; private WebTarget app; @BeforeClass public static void iniciarServidor() { Server.iniciar(); } @AfterClass public static void pararServidor() { Server.parar(); } @Before public void setUp() { cliente = ClientBuilder.newClient(); app = cliente.target(Server.BASE_URI); } // restante do cdigo omitido }

Apresentado isso, vejamos alguns exemplos em cdigo da utilizao desta API. Na Listagem 10 se observa um teste unitrio cuja finalidade buscar um recurso externo por meio de uma requisio HTTP GET. O cdigo em destaque nesse teste realiza uma requisio para o recurso identificado pelo URI http://<dominio>/clusters/cluster-1. A requisio sinaliza que aguarda uma representao XML desse recurso. H uma maneira alternativa e mais concisa de se fazer a mesma requisio, conforme ilustrado na Listagem 11. Nesse exemplo, a necessidade da invocao do mtodo readEntity em Response eliminada, pois o consumo da representao do recurso realizado diretamente pelo mtodo get. Listagem 10. Invocao HTTP GET
@Test public void deveRecuperarUmClusterEmXML() { Response resp = app.path("/clusters/cluster-1") .request(MediaType.APPLICATION_XML) .get(); Cluster c = resp.readEntity(Cluster.class); Assert.assertEquals(200, resp.getStatus()); Assert.assertEquals("cluster-1", c.getNome()); Assert.assertEquals(1, c.getComputadores().size()); Assert.assertEquals("pc1-ximango", c.getComputadores().get(0).getNome()); }

Listagem 11. Invocao HTTP GET alternativa


Cluster c = app.path("/clusters/cluster-1") .request(MediaType.APPLICATION_XML) .get(Cluster.class);

A Listagem 12 ilustra a definio de um teste unitrio que tem por objetivo criar um novo recurso na aplicao. Destaque novamente para o cdigo no qual realizada uma requisio HTTP POST, cujo corpo contm uma representao em XML do cluster (recurso) a ser criado. A converso do objeto Java para a representao desejada e vice-versa realizada automaticamente pela runtime JAX-RS, desde que o provedor adequado esteja no classpath da aplicao. Outros pontos importantes nesse teste unitrio referem-se obteno da localizao do recurso recm-criado e utilizao da mesma para recuperar este recurso. Listagem 12. Invocao HTTP POST
@Test public void deveCriarUmNovoClusterEmXML() { Cluster cluster = new Cluster("novo-cluster-xml", true); cluster.adicionarComputador(new Computador("pc1")); cluster.adicionarComputador(new Computador("pc2")); cluster.adicionarComputador(new Computador("pc3")); Response resp = app.path("/clusters") .request(MediaType.APPLICATION_XML) .post(Entity.entity(cluster, MediaType.APPLICATION_XML)); Assert.assertEquals(201, resp.getStatus()); String createdClusterPath = resp.getLocation().toString(); resp.close();

resp = cliente.target(createdClusterPath) .request(MediaType.APPLICATION_XML) .get(); Cluster created = resp.readEntity(Cluster.class); Assert.assertEquals("novo-cluster-xml", created.getNome()); }

O cdigo da Listagem 13 um teste unitrio que realiza a atualizao de um recurso na aplicao. realizada uma requisio HTTP PUT, cujo corpo preenchido com a representao em XML do recurso que deve ser atualizado. Alm disso, esse teste introduz uma funcionalidade presente na JAX-RS 2.0, at ento no demonstrada, a capacidade de construir invocaes para um determinado recurso permitindo sua execuo em um momento futuro. Alm dessa possibilidade, a construo de invocaes encoraja a reutilizao, evitando assim que cdigo possa ser duplicado. Listagem 13. Invocao HTTP PUT
@Test public void deveAtualizarUmClusterEmXML() { Invocation clusterGetInvoc = app.path("/clusters/cluster-2") .request(MediaType.APPLICATION_XML) .buildGet(); Cluster cluster = clusterGetInvoc.invoke().readEntity(Cluster.class); Assert.assertEquals(0, cluster.getComputadores().size()); cluster.adicionarComputador(new Computador("new-machine")); app.path("/clusters") .request() .put(Entity.entity(cluster, MediaType.APPLICATION_XML)) .close(); cluster = null; cluster = clusterGetInvoc.invoke().readEntity(Cluster.class); Assert.assertEquals(1, cluster.getComputadores().size()); }

Por fim, na Listagem 14 observa-se um teste unitrio cujo objetivo excluir determinado recurso da aplicao. realizada uma requisio HTTP DELETE para a aplicao, a mesma recupera o recurso definido no URI para realizar sua deleo e retorna uma resposta HTTP 204 No Content sinalizado o sucesso da operao. Listagem 14. Invocao HTTP DELETE
@Test public void deveDeletarUmClusterExistente() { Response resp = app.path("clusters/cluster-2").request().delete(); Assert.assertEquals(204, resp.getStatus()); // "204 No content" Deletado porm sem contedo }

Testando o Hypermedia na aplicao Conforme apresentado na definio do mtodo getByNome da classe ClusterResource, recursos hypermedia foram adicionados na parte servidora, o que torna a API cliente apta a usar todo o poder do HATEOAS. Porm, em virtude da verso beta do RESTEasy utilizada neste artigo ainda no possuir implementao para tratamento de hypermedia no cliente, foi considerado utilizar uma soluo prpria e simples para suportar Link Headers. Todavia, reforado, mais uma vez, que a API JAX-RS 2.0 dever ser utilizada para este fim aps a finalizao da especificao. Para o controle hypermedia no cliente foi criada uma classe utilitria, conforme demonstrado na Listagem 15.

Listagem 15. Classe Utilitria para Hypermedia


public class ExtractLinks { public static class Links { private final List<Link> jaxLinks; Links(List<Link> jaxLinks) { this.jaxLinks = jaxLinks; } public Link getByRel(String rel) { for (Link link : jaxLinks) if (rel.equals(link.getRel())) return link; return null; } } static public Links from(Response response) { String[] links = response.getHeaderString("Link").split(","); if (links == null) return null; List<Link> jaxLinks = new ArrayList<Link>(); for (String link : links) { final String uri = link.split(";")[0].trim() .replaceAll("[<>]", ""); final String rel = link.split(";")[1].trim().replaceAll("(rel=)|(\")", ""); Link jaxLink = createJaxRSLink(uri, rel); jaxLinks.add(jaxLink); } return new Links(jaxLinks); } private static Link createJaxRSLink(final String uri, final String rel) { return new Link() { @Override public String toString() { return uri + " - " + rel; } @Override public UriBuilder getUriBuilder() { return null; } @Override public URI getUri() { try { return new URI(uri); } catch (URISyntaxException e) { return null; } ... }; } }

A classe ExtractLinks basicamente realiza a extrao dos Link Headers do cabealho HTTP oriundo da resposta do servidor. Esses links extrados so ento convertidos em objetos Link da especificao JAX-RS 2.0 e disponibilizados para uso. A Listagem 16 demonstra um exemplo no qual a classe ExtractLinks utilizada. Observa-se no cdigo que a resposta HTTP, obtida da requisio que buscou o cluster de nome cluster-1 repassada ao mtodo from da classe ExtractLinks. A classe ento recupera o link definido na resposta pelo servidor e o disponibiliza para utilizao em uma requisio HTTP PUT, objetivando, efetivamente, a desativao do cluster. Listagem 16. Exemplo de interao HATEOAS

@Test public void deveDesativarUmCluster() { String clusterName = "cluster-1"; Response r = app.path("/clusters/" + clusterName).request().get(); Cluster cluster = r.readEntity(Cluster.class); Assert.assertTrue(cluster.isAtivo()); Links links = ExtractLinks.from(r); Link desativar = links.getByRel("desativar"); r.close(); r = app.path(desativar.getUri().toString()).request().put(null); Assert.assertEquals(200, r.getStatus()); r.close(); cluster = app.path("/clusters/" + clusterName).request().get(Cluster.class); Assert.assertFalse(cluster.isAtivo()); }

O exemplo apresentado, embora simples, expe grande parte dos recursos providos para JAX-RS e pode ser utilizado seguramente como uma base introdutria API. Concluso Como pode se observar no decorrer do artigo, a aplicao do modelo REST traz grandes benefcios para projetos de software. Provavelmente o principal deles seja o reuso de toda uma infraestrutura de comunicao j consolidada, que o protocolo HTTP. Como reuso normalmente sinnimo de reduo de tempo de desenvolvimento, pode-se deduzir que aplicaes construdas nas bases do REST tem reduo dos custos finais envolvidos com a concepo do projeto. Outros benefcios diretos da adoo do REST so a facilidade de integrao posterior do sistema, escalabilidade, menor exigncia por infraestrutura de hardware e tempo para entrega do projeto reduzidos em relao a outras tecnologias. Torna-se fundamental, avaliar a real aplicabilidade do REST ao projeto em questo. REST no a soluo para todos os problemas de engenharia e seus benefcios esto intimamente ligados adequao de suas caractersticas s caractersticas do projeto. Bom senso e estudo prvio das necessidades mostram-se essenciais para se obter bons resultados. Por fim, foi apresentado o que oferecido dentro do mundo Java para dar suporte concepo de sistemas REST. A JAX-RS, conforme visto, a API padro, concebida para este fim. As primeiras verses deixaram muito a desejar em relao ao atendimento das caractersticas pregadas pelo REST, o que vem sido melhorado com as novas releases da mesma. O uso da JAX-RS relativamente simples, envolvendo um nvel mdio de complexidade. Seu uso justifica-se principalmente por estar em conformidade aos demais padres estabelecidos pelo Java. E como sabido, no mundo Java, seguir padres sempre importante. Links RESTful Web services: The basics http://www.ibm.com/developerworks/webservices/library/ ws-restful/ws-restful-pdf.pdf Arquitetura REST: um estudo de sua implementao em linguagens de programao https://projetos.inf.ufsc.br/arquivos_projetos/projeto_673/TCCRicardoGhisi.pdf

Architectural Styles and the Design of Network-based Software Architectures http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm Java API for RESTful Services (JAX-RS) http://jax-rs-spec.java.net/ Java Community Process http://www.jcp.org/en/home/index JSR-000311 JAX-RS: The JavaTM API for RESTful Web Services 1.0 Final Release http://download.oracle.com/otndocs/jcp/jaxrs-1.0-fr-eval-oth-JSpec/ JSR-000311 JAX-RS: The JavaTM API for RESTful Web Services 1.1 Maintenance Release http://download.oracle.com/otndocs/jcp/jaxrs-1.1-mrel-eval-oth-JSpec/ JSR-000339 JAX-RS 2.0 Early Draft Review 3 http://download.oracle.com/otndocs/jcp/jaxrs-2_0-edr3-spec/index.html What's New in JAX-RS 2.0 http://java.dzone.com/articles/whats-new-jax-rs-20 Guidelines for Implementation of REST http://www.nsa.gov/ia/_files/support/guidelines_implementation_rest.pdf Rest in Practice Robinson ,Ian; Webber, Jim; Parastatidis, Savas. Rest in Practice. O'Reilly Media, 2010. Web services WS-* versus Web Services REST http://seer.ufrgs.br/reic/article/download/22140/12928

Leia mais em: Conhecendo o modelo arquitetural REST - Engenharia de Software Magazine 58 http://www.devmedia.com.br/conhecendo-o-modelo-arquitetural-rest-engenharia-de-software-magazine58/28052#ixzz2W0fOgmOe

Você também pode gostar