quinta-feira, 22 de setembro de 2016

Spring e Rest

Continuando os estudos sobre Rest e Spring. Ontem fiz uma busca em meus emails antigos procurando alguma documentação sobre versões antigas do Spring. Encontrei o seguinte manual:


O manual é do Jerome Jaglale que é autor do livro Spring Cookbook da editora de livros tecnológicos Packt. A versão do manual se refere ao Spring 2.5 e hoje estamos na versão 4. Na mesma página existe um link para o manual na versão 4 do Spring:


O link do item 4 direciona para o processamento de um form:

Repare que essa implementação utiliza um form Java com JSTL no front-end. E no back-end uma implementação muito próxima ao Rest. No fim da página o código completo está disponível no Github:


Dentro do Github, acessando o controle temos a classe de controle do exemplo carro:




Repare no código.



  1. package com.jeromejaglale.controller;
  2. import java.util.List;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.stereotype.Controller;
  5. import org.springframework.ui.Model;
  6. import org.springframework.web.bind.annotation.ModelAttribute;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RequestMethod;
  9. import com.jeromejaglale.domain.Car;
  10. import com.jeromejaglale.service.CarService;
  11. @Controller
  12. public class CarController {
  13.     @Autowired
  14.     private CarService carService;
  15.    
  16.     @RequestMapping("/car/list")
  17.     public void carList(Model model) {
  18.         List<Car> carList = carService.findAll();
  19.         model.addAttribute("carList", carList);
  20.     }
  21.    
  22.     @RequestMapping("/car/add")
  23.     public void carAdd() {
  24.     }
  25.    
  26.     @RequestMapping(value="/car/add", method=RequestMethod.POST)
  27.     public String carAddSubmit(@ModelAttribute Car car) {
  28.         carService.add(car);
  29.         return "redirect:/car/list";
  30.     }
  31. }

A classe é muito similar a um controle Rest. Similar porque a classe acima não é Rest e sim Spring. A implementação da chamada carService.findAll() até o model são do padrão MVC utilizados no Spring. Na verdade um Rest se limita ao controller. O Rest é WebService, e WebService é por definição a troca de mensagens geralmente entre servidores distribuídos. Essa troca é realizada através de um XML ou JSON.

O que precisaria para esta aplicação de controle se transformasse em um Web Service Rest? A annotation @Controller deveria ser @RestController. A diferença entre uma e outra é a resposta da da troca de mensagens. Por exemplo:


Response
200 OK


Response
204 No Content


A annotation @RestController possui a implementação de @ResponseBody internamente. No caso, as duas implementações abaixo são equivalentes.


  1.     @Controller
  2.     @ResponseBody
  3.     public class CarController { }
  4.     @RestController
  5.     public class CarController { }

A segunda alteração necessária seria avisar dentro do código o padrão de documento na troca de mensagens.

Para JSON


  1. @RequestMapping(value="/car/add", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)

ou para XML

  1. @RequestMapping(value="/car/add", method=RequestMethod.POST, consumes=MediaType.APPLICATION_XML_VALUE)


Feitas estas alterações a parte da aplicação que vai do controller ao model (back-end) poderiam estar em um servidor e o front-end que é JSTL no exemplo poderia ser substituído por uma implementação com requisições Rest. Então, o front-end poderia rodar em um outro servidor ou em um dispositivo móvel e estaria desacoplado da implementação de back-end que estaria em outro servidor.

Repare mais uma coisa interessante. Os imports da aplicação são todos do pacote do spring:

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.ui.Model;
  4. import org.springframework.web.bind.annotation.ModelAttribute;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RequestMethod;

E no caso da annotation @RestController o import seria:

  1. import org.springframework.web.bind.annotation.RestController;


Isso quer dizer que o REST está sendo implementado dentro do pacote Spring. Dependendo do tipo de projeto, o import é realizado diretamente no pacote javax.ws.

De certo modo a própria requisição POST já seria parte do REST, porém existem várias questões, como os metadados que envolvem essa requisição (XML/JSON).

Ao procurar uma definição para REST a melhor que encontrei foi a de que REST é uma interface.

Segundo Ricardo Lecheta, autor do livro Web Services RESTful, REST é uma técnica de desenvolvimento de Web Service.

Se estudamos o REST como um Web Service, então uma definição de Web Service deveria resolver.

Porém, o REST atualmente não está sendo utilizado apenas em sistemas distribuídos e aqui começa uma certa confusão.


Procurando uma definição nos documentos da Oracle:



Porém, repare que o exemplo exibe um retorno que não é XML e não é JSON e sim um HTML.


Pesquisando mais a fundo procurei uma definição melhor para Rest. W3C é o órgão que regulamenta várias das questões da internet. Mesmo o W3C não possui uma definição clara de REST. Isso porque o conceito de REST surgiu a partir de uma dissertação de Roy Fielding.


Segue a dissertação:



Eu tomei a liberdade de copiar alguns trechos interessantes onde possível concluir de uma forma global alguns conceitos de REST.


[…]The first constraints added to our hybrid style are those of the client-server architectural style (Figure 5-2), described in Section 3.4.1. Separation of concerns is the principle behind the client-server constraints. By separating the user interface concerns from the data storage concerns, we improve the portability of the user interface across multiple platforms and improve scalability by simplifying the server components. […]
As primeiras constraints adicionadas ao nosso estilo híbrido são aquelas da arquitetura cliente-servidor estilo (Figura 5-2), descrito no ponto 3.4.1. Através da separação dos princípios da interface de usuário em relação aos princípios do armazenamento de dados, podemos melhorar a portabilidade da interface do usuário em múltiplas plataformas e melhorar a escalabilidade, simplificando os componentes do servidor.

[…]The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components[…]
A característica central que distingue o estilo de arquitetura REST a partir de outros estilos baseados em rede é sua ênfase em uma interface uniforme entre os componentes

[…]The Representational State Transfer (REST) style is an abstraction of the architectural elements within a distributed hypermedia system. REST ignores the details of component implementation and protocol syntax in order to focus on the roles of components, the constraints upon their interaction with other components, and their interpretation of significant data elements. It encompasses the fundamental constraints upon components, connectors, and data that define the basis of the Web architecture, and thus the essence of its behavior as a network-based application. […]
O estilo Representational State Transfer (REST) é uma abstração dos elementos de arquitetura dentro de um sistema distribuído de hipermídia. REST ignora os detalhes da implementação do componente e da sintaxe do protocolo, a fim de se concentrar nas regras dos componentes, as restrições sobre a sua interação com outros componentes, e sua interpretação de elementos de dados significativos. Ela abrange as restrições fundamentais sobre os componentes, conectores e dados que definem as bases da arquitetura Web , portanto, a essência do seu comportamento como um aplicativo baseado na rede.



[…]A representation is a sequence of bytes, plus representation metadata to describe those bytes. […]
A representação é uma sequência de bytes, mais a representação de metadados para descrever esses bytes.


[…]A representation consists of data, metadata describing the data, and, on occasion, metadata to describe the metadata (usually for the purpose of verifying message integrity). […]
Uma representação consiste em dados, metadados descrevendo os dados, e, na ocasião, metadados para descrever os metadados (geralmente com a finalidade de verificar a integridade da mensagem).


Metadados são dados utilizados como limitadores de outros dados. No caso um XML(Extended Markup Language) seria uma representação, assim como o HTML do exemplo da Oracle.


Existem outros pontos de vista que podem manter uma longa discussão sobre o que é e que não é REST.

Referencias:






Nenhum comentário:

Postar um comentário