Livro sobre web services RESTful

Figura 1: Livro sobre web services RESTful

Nos últimos tempos, uma forte tendência vem mudando a forma de pensar os Web Services. Ela aponta para uma solução que elimina a complexidade presumida presente nos padrões dos Web Services convencionais, conhecidos também como Web Services SOAP ou Web Services WS-* (nomenclatura dada devido usarem diversas tecnologias diferentes). Esta tendência é o REST (REpresentational StateTransfer).

O REST não é um padrão ou uma arquitetura, e sim uma nova forma de se pensar sobre HTTP. Ele é composto por um conjunto de princípios e restrições que definem como padrões Web, como HTTP e URIs, podem ser usados. Os defensores do REST ​​acreditam que suas idéias explicam uma forma mais simples de resolver problemas de integração entre aplicativos e simplificar a estrutura necessária para construir arquiteturas orientadas a serviços.

Princípios REST

Os princípios utilizados por REST permitem que utilizemos a arquitetura da Web a nosso favor. Para REST, qualquer informação disponível é um recurso, por exemplo, um documento, o cadastro de uma pessoa, uma imagem, uma lista de carros. Este é um princípio, mas existem outros não menos importantes. São eles:

  • Todos os recursos devem ter um identificador;
  • Hypermedia como máquina de estado da aplicação;
  • Interface Uniforme;
  • Recursos com múltiplas representações;
  • Não armazenamento de estado (stateless);

Todos os recursos devem ter um identificador

Cada recurso precisa ser identificado unicamente, ou seja, precisa de um "ID". Na Web, a forma de se conseguir um identificador assim é através de uma URI. A URI permite que se criem namespaces globais, podendo servir como um identificador único e global para os recursos. Um recurso pode conter uma informação, como em http://exemplo.com/cliente/12 onde diretamente podemos obter um cliente, ou um conjunto de informações, como em http://exemplo.com/pagamentos/2013/01 onde obtemos os pagamentos realizados em janeiro de 2013. A simplicidade da URI permite ainda, que se mantenha uma semântica que permite visualizar facilmente o recurso.

Hipermídia como máquina de estado da aplicação

Além de ser semanticamente coerente, a URI, ou mais precisamente a URL, permite que a hipermídia funcione como máquina de estado da aplicação (das iniciais em inglês HATEOAS). Calma, vejamos do que se trata! Parece ser uma coisa de outro mundo ao se julgar pelo nome, porém esse princípio nada mais é do que se utilizar a hipermídia (os links) para se acessar um recurso indiretamente, a partir da própria aplicação, sem interferência humana (sem termos que interagir com os links). E quanto ao estado da aplicação? O estado é alterado ao se seguir o link, ou seja, ao se acessar o outro recurso. Segue um exemplo:

Listagem 1: Exemplo de objeto com links nas propriedades


<venda self='http://exemplo.com/cliente/12' >  
   <quantidade>23</quantidade>  
   <produto ref='http://exemplo.com/produtos/41' />  
   <cliente ref='http://exemplo.com/cliente/12' />  
</venda>

No exemplo, podemos ver que estamos acessando uma venda, porém, ela permite que ao seguirmos um link, como o de cliente, estamos mudando o estado da aplicação.

Interface Uniforme

A URI ainda permite outras vantagens. Aliada aos métodos do HTTP, a URI sabe que todos os recursos suportam a mesma interface, o mesmo conjunto de métodos HTTP. O HTTP possui outros verbos, além dos conhecidos GET e POST, são eles: PUT, DELETE, HEAD e OPTIONS. Esses métodos permitem que se obtenha uma interface uniforme, associa estes verbos a necessidades de aplicativo de negócios padrão, mais conhecido por CRUD (do inglês Create, Retrieve, Update, Delete), ou seja, armazenamento, busca, atualização e deleção. A tabela 1 mostra esta associação.

Tarefa do AplicativoVerbo HTTP
CreatePOST
ReadGET
UpdatePUT
DeleteDELETE

Tabela 1: Mapeamento CRUD/HTTP

Ao associar os verbos HTTP, que na realidade são solicitações, aos recursos, que agem como nomes, obtêm-se uma semântica conversacional. Por exemplo, pode-se criar uma expressão lógica de comportamento, GET este documento e UPDATE aquele registro.

Recursos com múltiplas representações

Os resources também podem ser representados em diversos formatos (Media Type). Por exemplo, na internet ou em uma intranet, é normal que se possa obter o cadastro de um cliente em diversos formatos, como html, xml e json.

Não armazenamento de estado (Stateless)

Existem bons motivos para não se manter o estado de comunicação com o servidor. Quando necessário, deve-se mantê-lo no cliente. Isto permite alguns benefícios como: visibilidade, não é necessário verificar a requisição para determinar sua natureza; fiabilidade, a tarefa de recuperação a falhas parciais se torna fácil; escalabilidade, não necessitando armazenar estados entre as requisições, o servidor pode rapidamente liberar recursos facilitando seu gerenciamento.

A desvantagem é a redução de desempenho na rede devido aumenta os dados repetidos enviados nas requisições, e o controle do servidor sobre a consistência da aplicação é reduzido, já que todo o estado da aplicação fica no lado cliente.

RESTful no JEE6

Os conceitos de REST já existem a mais de uma década, porém somente nos últimos anos estão sendo utilizados com mais frequência, impulsionados principalmente pela expansão dos dispositivos móveis. Devido a ascendente utilização de REST, a plataforma JEE6 incorporou este conceito por meio da especificação JAX-RS 1.1, baseada em anotações. Esta especificação determina como deve ser implementado um serviço Restful, porém, não o implementa. Para implementar facilmente os Web Services Restful, é necessário se utilizar um framework como o RESTeasy, o RESTlet, restfulie ou Jersey.

O foco deste artigo é mostrar as principais anotações desta especificação, e explicá-las, de acordo com os princípios REST.

De acordo com a JAX-RS, os recursos Web são implementados por classes Java (resource classes). Conforme foi visto, todo recurso Web deve possuir uma URI. A anotação que define este recurso é @Path.

Listagem 2: Exemplo de uso da anotação @Path

@Path("/Cliente")
class ClienteResource{
	//Classe que representa o recurso
}

Para se mapear os métodos HTTP @GET, @PUT, @POST, @DELETE e @HEAD para métodos Java, deve-se utilizar também uma resource class.

Listagem 3: Mapeamento do método GET


@Path("/Cliente")
class ClienteResource{
	@GET
	@Produces(MediaType.TEXT_PLAIN)
	public String getCliente(){
		//implementação
	}
}

A especificação JAX-RS também permite que se apresente mais de um recurso por classe, a partir de sub-recursos.

Listagem 4: Usando sub-recursos


@Path("/Cliente")
class ClienteResource{
	@GET
	@Produces(MediaType.TEXT_PLAIN)
	public String getStatusCliente(){
		//implementação
	}

	@GET
	@Path("/bonus")
	@Produces(MediaType.TEXT_PLAIN)
	public String getBonusCliente(){
		//implementação	
	}
}

Os sub-recursos são representados pelo sufixo da URI, concatenando-se os valores das anotações @Path da classe recurso, com a anotação @Path dos sub-recursos. A partir do exemplo, temos: /Cliente/status e /Cliente/bonus. A anotação @Produces determina o tipo de retorno esperado. MediaType é a representação do recurso, no exemplo é um texto simples (TEXT_PLAIN).

Existe uma grande variedade de representações para os recursos, e diversos métodos implementados pela especificação JAX-RS.