Você está na página 1de 144

Desenvolvimento de uma API REST com Java EE.

Apresentando a especificação JAX-RS do Java EE do básico ao avançado.

Autor: Luan Felipe Knebel.


Desenvolvedor Java na Cooperativa Agroindustrial Alfa.
1
Tópicos abordados:

● Web Service.
● Estrutura do protocolo HTTP.
● Verbos HTTP.
● API - Application Programming Interface (Interface de Programação de Aplicações).
● REST - Representational State Transfer (Transferência de Estado Representacional).
● Diferença entre REST e RESTful.
● Implementações da Especificação JAX-RS.
● Convenção de URIs REST amigáveis.
● Modelagem de dados.
● DTO - Data Transfer Object (Objeto de Transferência de Dados).
● Aplicação Web Java EE com Maven.
● Repositório de dados da API REST.
● Configuração JAX-RS e o primeiro serviço REST.
● Parâmetros de URIs @PathParam e @QueryParam

2
Tópicos abordados:

● Níveis de Maturidade REST.


● Implementação do Nível 0 de Maturidade - POX.
● Implementação do Nível 1 de Maturidade - Recursos.
● Implementação do Nível 2 de Maturidade - Verbos HTTP.
● Implementação da API REST.
● Implementação do Nível 3 de Maturidade - HATEOAS.
● Versionamento da API RESTful.
● Providers JAX-RS.
● Mapeamento de Exceções de Negócio.
● Segurança e Autenticação com JWT (Json Web Token).
● Customização de Hypermedia JSON (Serialização e Desserialização).
● Disponibilizando a API RESTful para clientes Java.
● Consumir a API RESTful via Interface Proxy.
● Conclusão.

3
Introdução

Este curso tem como objetivo demonstrar o desenvolvimento de uma API RESTful com Java EE
iniciando pelos conceitos do protocolo HTTP. Após a apresentação básica da estrutura HTTP será
demonstrado os padrões utilizados no desenvolvimento de uma API RESTful.

O desenvolvimento do projeto desta apresentação será partir de um modelo de dados, onde os


quatro níveis de maturidade REST serão aplicados, até chegar em uma API completa e robusta.

Além da API RESTful, serão apresentados algumas funcionalidades do JAX-RS, como tratamento
de exceções com a utilização de Providers, customização de Hypermedia, autenticação com JWT (Json
Web Token) e a exportação das interfaces da API RESTful para que outras aplicações java possam
consumir a API via cliente proxy.

Bons estudos!

4
Requisitos

Ferramentas do Ambiente de Desenvolvimento:

● Java JDK 8.
● Eclipse IDE.
● JBoss WildFly Server versão 14 ou superior.
● Git.
● Postman

As aplicações estão disponíveis no repositório BitBucket no link:


https://bitbucket.org/luan_knebel/vendarapidarestapi/src/master

5
Web Service:

Com a evolução dos sistemas computacionais, a integração entre sistemas diferentes vem
crescendo cada vez mais.

As integrações são realizadas a partir de trocas de informações e execução de serviços de negócio


onde ambos os sistemas devem utilizam um protocolo de comunicação para a realização das tarefas.

A comunicação entre os sistemas via Web Services normalmente é realizada a partir do protocolo
HTTP, onde dados são trafegados entre um cliente e um servidor, com serviços expostos na rede.

6
Estrutura do Protocolo HTTP

O protocolo HTTP (Hypertext Transport Protocol) é uma forma padronizada de tráfego de informações
na Web, onde que o cliente envia uma requisição (Request) e o servidor retorna um uma resposta (Response).

O Request e o Response possuem informações padronizadas pela arquitetura do protocolo HTTP, ou


seja, ambos objetos possuem Headers, Cookies e Boby, com exceção do Status Code que somente o Response
irá conter.

7
Estrutura do Protocolo HTTP

● Headers: Os Headers são uma coleção de metadados que trafegam entre o cliente e o servidor por
chave e valor, estes metadados possuem informações referente ao servidor que a requisição está sendo
executada, tipos de Hypermedia que está sendo trafegado, controles de acesso, autenticação, controles
de cache, tamanho do dado trafegado, entre outras informações que podem ser repassadas para o
cliente e para o servidor. Os headers podem ser customizados conforme a necessidade pelo
desenvolvedor e são informações transitivas em cada requisição / resposta.

● Cookie: Esta estrutura também possui informações de metadados, no entanto os cookies são utilizados
para manter informações no cliente, como uma sessão de login. Os cookies são registrados no cliente
com o nome de domínio, chave e valor, versão e data de expiração. Os cookies são informações não
transitivas, ou seja, não se perdem a cada requisição / resposta. Na maioria dos casos, um cookie é criado
com um token de autenticação quando um usuário realiza o login em um sistema, e este token é enviado
via Header na requisição para poder acessar recursos restritos.

8
Estrutura do Protocolo HTTP

● Status Code: O Status Code é a forma utilizada pelo protocolo HTTP para informar ao cliente o estado
da resposta, se houve erros de negócio, se a requisição foi processada com sucesso ou se ocorreu um
erro interno no sistema, os Status Codes são divididos por famílias e possuem três atributos:
○ Code: Código em formato numérico do tipo inteiro.
○ Reason: Razão do Status Code, descrição do código.
○ Family: Família a qual o Status Code pertence.

Família do Status Code:


1xx: (Informational) Status de informação de requisição provisória recebida.
2xx: (Success) Sucesso na requisição, informações processadas e enviadas com sucesso.
3xx: (Redirection) Sucesso na requisição, ações adicionais devem ser executadas para concluir a
solicitação.
4xx: (Client Error) Erro na requisição do cliente.
5xx: (Server Error) O servidor é incapaz de processar a solicitação por um erro interno.

9
Estrutura do Protocolo HTTP

● Body: O corpo do protocolo HTTP possui as informações que de fato interessam ao negócio entre o
cliente e o servidor, estes dados são transportados em formato de texto e binário, no caso dos dados em
formato textual, geralmente é utilizado criptografia HTTPS onde os dados são criptografados para
trafegar com segurança, esta criptografia necessita de um certificado digital instalado no servidor da
aplicação.

No corpo da requisição o cliente pode enviar dados para o servidor processar e o servidor poderá
retornar informações na resposta para o cliente processar.

Em serviços REST, os dados geralmente são trafegados no formato JSON ou XML.

10
Verbos HTTP

O protocolo HTTP possui um conjunto de verbos para indicar ao servidor quais ações devem ser
executadas. Na tabela abaixo estão listados apenas alguns verbos utilizados em aplicações REST.

Verbo: Ação:

GET Retorna a representação de um dado, utilizado somente para consultas.

POST Inclusão de novas informações, geralmente retorna o ID do registro criado.

PUT Aplicar modificações integrais.

PATCH Aplicar modificações parciais.

DELETE Remove uma informação.

OPTIONS Retorna as operações possíveis de um recurso.

11
API - Application Programming Interface

Uma API (Interface de Programação de Aplicativos) é um conjunto de interfaces, classes e métodos


que dispõem funcionalidades de um sistema para que outras aplicações possam se comunicar e utilizar de
seus recursos sem expor a sua implementação e regras de negócio.

Uma API após ser modelada não pode sofrer grandes mudanças, para não impactar os sistemas que
a utilizam, desta forma, ela deve ser bem projetada.

12
REST - Representational State Transfer
REST (Transferência de Estado Representacional) é um estilo arquitetural que define um conjunto
de serviços de uma aplicação Web, esses serviços oferecem a outras aplicações a representação de dados
que definem o estado do recurso solicitado, geralmente é utilizado os formatos HTML, JSON e XML ou
binário.

Para que um Web Service seja considerado REST, o mesmo deve utilizar o protocolo HTTP, os
serviços devem ser stateless, utilizar URIs amigáveis, utilizar os verbos HTTP para definição das
operações executadas e os componentes do sistema não podem visualizar além da sua camada da API.

Requisição Requisição
POST http:localhost:8080/MinhaAplicacao/cliente GET http:localhost:8080/MinhaAplicacao/cliente/1
{ Resposta 200 - OK:
“nome”: “João”, {
“aniversario”: “16/10/1993” “idCliente”: 1,
} “nome”: “João”,
Resposta 201 - Created: “aniversario”: “16/10/1993”
{ }
“idCliente”: 1
} 13
Diferenças entre REST e RESTful.

A Transferência de Estado Representacional (REST) é um estilo de arquitetura de software que


basicamente explora a tecnologia e o protocolo HTTP na Web.

O RESTful é normalmente usado para se referir a serviços da Web que implementam essa
arquitetura, utilizando os quatro níveis de maturidade REST.

Desta forma, um conjunto de serviços REST somente podem ser considerados uma API RESTful
somente se atender ao modelo arquitetural REST de forma completa.

14
Implementação da Especificação JAX-RS

A especificação JAX-RS (JSR339) desenvolvida pela JCP (Java Community Process) documenta
como os desenvolvedores da comunidade Java e empresas de tecnologia devem implementar a
especificação, estas implementações são distribuídas em containers Java EE, bibliotecas e frameworks.

Atualmente as implementações mais utilizadas são Jersey da Sun (Glassfish, Payara e WebLogic),
RestEasy da JBoss (WildFly), Apache CXF (Tomcat).

Mesmo seguindo a especificação JAX-RS, as implementações podem ter características específicas


na forma de utilizar algumas funcionalidades.

15
Convenção de URIs REST amigáveis.

As URIs de acesso aos recursos REST devem ser amigáveis para que o cliente possa compreender o
uso da API, as URIs devem conter nomes descritivos, facilitando o entendimento das funcionalidades dos
recursos expostos.

A URI de acesso ao um recurso REST é separada em quatro partes:

1. Base: http://localhost:8080/MinhaAplicacao (Acesso a aplicação web)


2. Application Path: /api/rest/v1 (Caminho onde é registrado todos os resources)
3. Resource Path: /cliente (Caminho de resource)
4. Method Path: /buscar (Caminho de método do resource)
Resultando em: http://localhost:8080/MinhaAplicacao/api/rest/v1/cliente/buscar

As URIs amigáveis não utilizam CamelCase em sua definição, em caso de separação de palavras, deve-se
utilizar o hífen, exemplo: http://localhost:8080/MinhaAplicacao/api/rest/v1/cliente/buscar-por-codigo

16
Modelagem de dados

Durante o curso, será desenvolvido uma aplicação RESTful a partir de um modelo de dados, esta
aplicação consiste em uma API para cadastrar Usuários, Clientes, Produtos e Pedidos de Venda.

Após o desenvolvimento da API RESTful será disponibilizado uma aplicação pronta em Java EE
com JSF (Java Server Faces) para que possamos implementar um cliente que irá comunicar com a API de
Pedidos de Venda.

17
Modelagem de dados

Este tópico demonstra a modelagem de dados que será utilizada como exemplo para o
desenvolvimento da API RESTful, segue abaixo o diagrama de entidades e relacionamento a qual irá
representar uma API de cadastro de Pedidos de Venda.

18
DTO - Data Transfer Object

Um DTO (Objeto de Transferência de Dados) é um padrão utilizado para trafegar informações


entre sistemas, os DTOs são utilizados em conjunto a objetos do banco de dados representados por
entidades, onde um DTO representa uma entidade do banco de dados.

A utilização de DTOs para trafegar dados é necessária para não expor dados sensíveis da aplicação
externamente, desta forma, um DTO pode representar uma entidade do banco de dados, mas ela não
precisa ter necessariamente todos os atributos da entidade, outro detalhe a ser levado em consideração
é que um DTO poderá conter atributos customizados sem impactar diretamente em sua entidade.

19
Aplicação Web Java EE com Maven

Para o desenvolvimento da aplicação REST, será utilizado no ambiente de desenvolvimento o


Eclipse IDE, servidor de aplicação WildFly com a versão 8 da API JavaEE.

Inicialmente será criado uma aplicação Java EE pelo Maven conforme a imagem abaixo:

20
Aplicação Web Java EE com Maven

Selecione a pasta no workspace que deverá ser criado o projeto, após este passo, selecionar o
Archetype maven-archetype-webapp para o Maven criar a estrutura e arquivos de um projeto Java EE.

21
Aplicação Web Java EE com Maven

Por fim, deverá ser informado o Group Id (grupo em que a aplicação pertence), Artifact Id (Nome
do projeto), Version (versão do projeto) e o Package (pacote de classes do projeto) .

Após esta etapa o Maven irá criar os arquivos e pastas necessárias para um projeto Java EE.

22
Aplicação Web Java EE com Maven

Por padrão, o Maven não cria o arquivo web.xml com as configurações necessárias para rodar o
projeto corretamente, desta forma, é necessário obter o xml de exemplo no site da Oracle para incluir no
projeto no link: http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/index.html#1 ou o
exemplo do web.xml poderá ser copiado no próximo slide.

23
Aplicação Web Java EE com Maven
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee webapp_4_0.xsd"
version="4.0">
<display-name>VendaRapidaRestAPI</display-name>
</web-app>

24
Aplicação Web Java EE com Maven

Após incluir as configurações básicas no projeto Java EE, é necessário informar o Maven a versão
do Java em que o projeto será compilado. Esta configuração deverá ser incluída no pom.xml. Neste caso
será utilizado a versão 8 do Java, conforme a configuração abaixo:

<build>
<finalName>VendaRapidaRestAPI</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

25
Aplicação Web Java EE com Maven

Ao configurar a versão de compilação do Java, é necessário incluir o plugin de gerenciamento


WAR para que o Maven possa gerar o empacotamento correto do projeto, esta configuração pode ser
visualizada abaixo. Neste caso, é necessário copiar somente o conteúdo da tag <plugin> para ser incluída
dentro da tag <plugins> configurada anteriormente no plugin de compilação do Java.
<build>
<finalName>VendaRapidaRestAPI</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<version>4.0</version>
<warSourceDirectory>src/main/webapp</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>

26
Aplicação Web Java EE com Maven

Para que a aplicação possa utilizar os recursos do JAX-RS é necessário incluir a dependência da API
do Java EE, desta forma teremos acesso às classes, interfaces e anotações para poder utilizar todos os
recursos disponíveis da plataforma Java EE.

Neste caso, será utilizado a versão 8 do Java EE com escopo provided, desta forma o Maven não irá
empacotar a dependência do Java EE no projeto, pois a mesma será disponibilizada pelo servidor de
aplicação.

<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

27
Aplicação Web Java EE com Maven
Após configurar a aplicação Java Web, é necessário executar o Maven Update no projeto para que
as configurações realizadas sejam efetivadas.

O Eclipse IDE utiliza os Facets para definir características e requisitos do projeto, além de auxiliar a
IDE em conjunto com o Maven na compilação e empacotamento da aplicação. A configuração do plugin
maven-war-plugin no pom.xml informa ao Maven que a versão 4.0 será utilizada para o empacotamento
WAR, desta forma, é necessário alterar o Facet Dynamic Web Module do eclipse para a versão 4.0 nas
propriedades do projeto conforme a imagem abaixo:

28
Aplicação Web Java EE com Maven

Após realizar as configurações necessárias no projeto, será realizado um deploy da aplicação no


servidor WildFly para fim de testes, ao acessar a aplicação no navegador na URL
http://localhost:8080/VendaRapidaRestAPI, uma página de “Hello World” deverá ser exibida.

29
Repositório de dados da API REST.

Durante o desenvolvimento da API REST, vamos precisar de um repositório de dados para que
possamos realizar simulações na utilização da API, as aplicações reais utilizam um banco de dados e um
framework para acessar a base de dados.

Para simplificar o desenvolvimento do projeto, iremos simular os repositórios dados com Managed
Bean de escopo de aplicação, cada entidade do modelo de dados terá a sua classe Repository que irá
simular um DAO (Data Access Object), a partir destas classes os nossos serviços REST irão obter
informações para disponibilizar aos clientes que irão consumir a API.

As classes de repositório de dados irão manter os dados em memória enquanto a aplicação estiver
sendo executada.

30
Configuração JAX-RS e o primeiro serviço REST.

Os serviços REST são representados por classes Java, essas classes devem ser configuradas com
anotações para informar ao servidor de aplicação a URI de acesso aos serviços.

A partir dos conceitos apresentados até agora, será criado uma classe ClienteDTO que irá
representar entidade Cliente do nosso modelo, e uma classe ClienteResource que irá representar a classe
de serviços REST para realizar operações com o Cliente.

31
Configuração JAX-RS e o primeiro serviço REST.

Para criar uma classe de Resource, algumas anotações deverão ser utilizadas para compor o
serviço, sendo elas:

@Path: Utilizado para informar o caminho de acesso ao resource ou método do resource, esta
anotação deverá ser informada na classe resource e nos métodos da classe, compondo a URI de acesso
aos serviços.

@Consumes: Utilizado para informar o tipo de Hypermedia que o serviço irá aceitar, geralmente é
utilizado JSON ou XML.

@Produces: Utilizado para informar o tipo de Hypermedia que o serviço irá produzir, geralmente é
utilizado JSON ou XML.

Os verbos HTTP são definidos pelas anotações @GET, @POST, @PUT, @DELETE, @PATCH e
@OPTIONS.

32
Configuração JAX-RS e o primeiro serviço REST.

Segue abaixo a classe ClienteResource configurada com as anotações JAX-RS para acessar os seus
serviços REST, o método buscarClientes() foi implementado para retornar uma lista de ClienteDTO.

33
Configuração JAX-RS e o primeiro serviço REST.
Para que os Resources estejam disponíveis para o acesso via URI REST, é necessário informar ao
servidor de aplicação quais classes deverão ser registradas como serviço web.

Essa configuração é realizada a partir da classe javax.ws.rs.core.Application, para isso, será criado
uma classe chamada ApplicationConfig que irá extender da classe javax.ws.rs.core.Application
sobrescrevendo o método getClasses(), este método deverá retornar uma coleção de classes de todos os
resources REST. A anotação @ApplicationPath é utilizada para informar o caminho URL que os recursos
serão registrados.

34
Configuração JAX-RS e o primeiro serviço REST.

Ao realizar o deploy da aplicação e acessar a URI do método buscarClientes() do resource


ClienteResource, o navegador irá realizar a operação GET e o serviço REST irá retornar um JSON da lista
de ClienteDTO.

Por padrão o navegador utiliza o verbo GET do HTTP para acessar recursos da web.

35
Parâmetros de URIs @PathParam e @QueryParam

Em algumas requisições REST é necessário enviar parâmetros pela URI para realizar uma operação
ou acessar um recurso específico, os parâmetros mais utilizados são os parâmetros de caminho e
parâmetros de operações arbitrárias, sendo eles:

@PathParam: Utilizado para compor o caminho de um recurso em uma URI, este tipo de parâmetro
também é utilizado para acessar sub recursos de um recurso. Exemplo:

http://localhost:8080/VendaRapidaRestAPI/api/rest/v1/cliente/buscar/1 irá retornar o cliente


com o código 1.

http://localhost:8080/VendaRapidaRestAPI/api/rest/v1/cliente/buscar/1/nome irá retornar


somente o nome do cliente com código 1, o caminho nome que compõem a URI pode ser compreendido
como um sub recurso do recurso cliente.

36
Parâmetros de URL @PathParam e @QueryParam

Ao utilizar parâmetro de caminho, a descrição do parâmetro em @PathParam deve ser igual a


descrição do parâmetro no @Path do método, para que o Java atribua o valor informado na URL para o
parâmetro do método.

O parâmetro deve estar identificado com chaves {nomeParametro} no Path do método para que o
JAX-RS possa identificar que esta parte da URI pertence a um PathParam.

37
Parâmetros de URL @PathParam e @QueryParam

Os parâmetros de consulta QueryParam são utilizados em operações e consultas arbitrárias, este


tipo de parâmetro é utilizado quando é necessário enviar um ou mais parâmetros para um serviço REST,
lembrando que os parâmetros de caminho PathParam podem ser utilizados em conjunto com
QueryParam dando precedência ao PathParam.

38
Parâmetros de URL @PathParam e @QueryParam

O serviços compostos pelo QueryParam deverão ser repassados após o ponto de interrogação da URI do
método.

Considerando o método buscarClientePorNome implementado anteriormente, a requisição abaixo é


realizada informando ?nomeParametro=valorParametro. Nos casos onde o recurso possui mais de um parâmetro
a seguinte sintaxe deve ser utilizada ?nomeParametro1=valorParametro1&nomeParametro2=valorParametro2

39
Níveis de Maturidade REST.

Os níveis de maturidade REST propostos por Leonard Richardson definem o modelo arquitetural
REST em níveis de implementação, onde cada nível propõem padrões para solução de problemas.

A aplicação que será desenvolvida nesta apresentação irá demonstrar exemplos de


implementações de cada nível até chegar a “Glória do REST” ,utilizando todos o padrões definidos pela
arquitetura REST.

40
Implementação do Nível 0 de Maturidade - POX.

Neste nível de implementação, é utilizado somente o protocolo HTTP na implementação de


serviços, nenhum padrão da arquitetura REST é utilizado, os serviços implementados neste nível
baseiam-se somente no envio e recebimento de mensagens no estilo XML-RPC (Remote Procedure Call),
da mesma forma como os serviços SOAP são implementados com a utilização do POX (Plain Old Object),
o que dificulta na interoperabilidade dos serviços REST.

Este nível de implementação não utilizam resources, verbos HTTP e HATEOAS, e são
disponibilizados em uma única URI e um único verbo HTTP, geralmente POST, para trafegar dados em
XML.

41
Implementação do Nível 0 de Maturidade - POX.

O exemplo de um serviço REST em nível zero pode ser identificado pelas chamadas URI, onde
somente o nome do método está exposto para o cliente com a utilização do verbo POST sem a
identificação do recurso que está sendo acessado. Com exemplo do serviço abaixo, o ApplicationPath e o
Path do resource ficariam com uma String vazia, e a URI ficaria da seguinte forma:

POST http://localhost:8080/VendaRapidaRestAPI/buscar-clientes

42
Implementação do Nível 1 de Maturidade - Recursos

A implementação no nível 1 de maturidade REST faz o uso de URIs sobre uma URI, ou seja, o acesso
a um recurso é identificado por uma URI. Quando queremos realizar operações sobre uma entidade ou
processo, esta entidade ou processo é identificado em uma URI, para então termos acesso às URIs
disponíveis, exemplo:

Para acessar operações no Cliente: http://localhost:8080/VendaRapidaRestAPI/cliente, desta


forma, podemos ter acesso às URIs da URI do Cliente:

http://localhost:8080/VendaRapidaRestAPI/cliente/cadastrar

http://localhost:8080/VendaRapidaRestAPI/cliente/excluir/1

43
Implementação do Nível 2 de Maturidade - Verbos HTTP

O nível de maturidade 2 contempla a utilização dos verbos HTTP para realizar operações na API
REST, todas as operações de CRUD (Create, Read, Update, Delete) são realizadas pelo verbo HTTP.

O nível de maturidade 1 não utiliza os verbos HTTP, necessitando a identificação das operações de
CRUD por URI, exemplo:

http://localhost:8080/VendaRapidaRestAPI/cliente/buscar/1

http://localhost:8080/VendaRapidaRestAPI/cliente/cadastrar

http://localhost:8080/VendaRapidaRestAPI/cliente/atualizar/1

http://localhost:8080/VendaRapidaRestAPI/cliente/excluir/1

44
Implementação do Nível 2 de Maturidade - Verbos HTTP

No nível de maturidade 2 fica mais simples de realizar as operações de CRUD, utilizando o que o
HTTP oferece de melhor para identificar o que está sendo realizado no recurso acessado, os verbos!

Desta forma, as operações de CRUD ficariam da seguinte forma:

GET: http://localhost:8080/VendaRapidaRestAPI/cliente/1 (Buscar Cliente com código 1)

POST: http://localhost:8080/VendaRapidaRestAPI/cliente (Cadastrar novo Cliente)

PUT: http://localhost:8080/VendaRapidaRestAPI/cliente/1 (Atualizar Cliente com código 1)

DELETE: http://localhost:8080/VendaRapidaRestAPI/cliente/1 (Excluir Cliente com código 1)

45
Implementação do Nível 2 de Maturidade - Verbos HTTP

Avançamos bastante com os padrões REST apresentados até agora, a partir do nível 2 de
maturidade, podemos dar continuidade no desenvolvimento da API REST de cadastros de Pedidos de
Venda.

A partir do modelo de dados apresentado no slide 18 (Modelagem de dados), será criado os DTOs,
Resources e Repository de cada entidade representada no modelo nossa aplicação.

Cada resource irá contemplar as operações de CRUD seguindo os padrões REST do nível de
maturidade 2.

Mão na massa!

46
Implementação da API REST

Para iniciar a implementação da API REST, os DTOs deverão herdar da classe abstrata
AbstractDTO, essa classe abstrata possui um método getId() que os DTOs deverão implementar, este
método deverá retornar o ID do DTO, esta abstração tem como objetivo padronizar métodos e atributos
genéricos dos DTOs da API.

47
Implementação da API REST

Implementação do resource do Cliente com as operações de CRUD com verbos HTTP

48
Implementação da API REST

Implementação do resource do Usuário com as operações de CRUD com verbos HTTP

49
Implementação da API REST

Implementação do resource do Produto com as operações de CRUD com verbos HTTP

50
Implementação da API REST

Implementação do resource do PedidoVenda com as operações de CRUD com verbos HTTP

51
Implementação da API REST

A entidade ItemPedidoVenda pertence ao PedidoVenda, desta forma, o acesso aos Itens de


um Pedido de Venda somente podem ser acessados a partir de um Pedido de Venda.

Onde o resource do Pedido de Venda com código 1 é:


http://localhost:8080/VendaRapidaRestAPI/api/rest/v1/pedidovenda/1

O resource para acessar os Itens do Pedido de Venda de código 1 deve ser:


http://localhost:8080/VendaRapidaRestAPI/api/rest/v1/pedidovenda/1/itempedidovenda

Desta forma, o resource do ItemPedidoVenda é um sub resource do PedidoVenda, pois


somente pode-se ter acesso aos itens de um pedido a partir de um pedido.
Esta regra é aplicável a todos os casos onde que um resource filho somente pode ser
acessado a partir de um resource pai.

52
Implementação da API REST

Por padrão, todos os sub resources devem conter em seu Path o ID do resource pai, onde
cada método do resource deverá conter um PathParam para mapear o ID do registro pai.
No exemplo abaixo, o Path é definido por pedidovenda/{idPedidoVenda}/itempedidovenda e
todos os métodos do resource devem ter como precedência o PathParam de {idPedidoVenda}.

53
Implementação da API REST

Implementação do Resource do ItemPedidoVenda com as operações de CRUD com verbos HTTP

54
Implementação da API REST

Após concluir o desenvolvimento de todos os Resources do modelo de dados, as operações de


CRUD poderão ser realizadas por um cliente da API REST de Pedidos de Venda, onde as informações
serão mantidas na memória das classes Repository enquanto a aplicação estiver rodando no servidor
WildFly.

Após deixar a API REST com todas as funcionalidades que um cliente da API necessita para
utilizá-la, não podemos classificar a API como RESTful, pois estamos utilizando recursos de nível de
maturidade 2.

Para torná-la uma API RESTful é necessário a implementação do nível de maturidade 3, que utiliza
o mecanismo de HATEOAS na representação dos estados das entidades trafegadas na API REST.

55
Implementação do Nível 3 de Maturidade - HATEOAS

Quando navegamos em um site, ele nos oferece opções de ações e navegação entre as páginas
disponíveis na web, isso facilita a ergonomia do site para o usuário.

Da mesma forma que um site dispões de links de ações e navegação, uma API RESTful deve
disponibilizar ao cliente da API as ações que podem ser executadas a partir do recurso solicitado, estas
ações são disponibilizadas por links URIs, desta forma facilitamos a navegação entre os recursos da API
além das opções que podem ser tomadas a partir do estado do recurso requisitado.

O mecanismo HATEOAS (Hypermedia As The Engine Of Application State), em português:


Hipermídia como o Mecanismo do Estado do Aplicativo, utiliza controles de hipermídia para fornecer ao
cliente da API links de navegação e ações que podem ser executadas com base no estado do recurso
requisitado, estes links são disponibilizados dinamicamente em conjunto com o JSON retornado.

56
Implementação do Nível 3 de Maturidade - HATEOAS

Quando requisitamos um usuário na API REST, o HATEOAS poderá retornar na lista de links com
as ações possíveis que podem ser tomadas a partir do estado do usuário requisitado.

No exemplo abaixo, as ações disponíveis são repassadas para o cliente da API REST em uma lista de
links, informando que a ação de bloquear está disponível para ser executada com o usuário retornado.

Requisição
GET http://localhost:8080/VendaRapidaRestAPI/api/rest/v1/usuario/1
Resposta 200 - OK:
{
“idUsuario”: 1,
“login”: “joao”,
“links”:[ {
“rel”: “bloquear”
“href”: “http://localhost:8080/VendaRapidaRestAPI/api/rest/v1/usuario/bloquear/1 ”
}]
}

57
Implementação do Nível 3 de Maturidade - HATEOAS

Quando adicionamos um recurso HATEOAS, o link deve conter dois atributos:

● rel: Significa o relacionamento da ação ou navegação.


● href: URI completa de acesso ao relacionamento.

O DTO LinkDTO irá representar um recurso HATEOAS de um DTO qualquer.

58
Implementação do Nível 3 de Maturidade - HATEOAS

Um DTO poderá conter uma lista de links HATEOAS, considerando que todos os DTOs da
aplicação herdam da classe abstrata AbstractDTO, a lista de links será adicionada na classe AbstractDTO,
desta forma todos os DTOs irão herdar a lista de links do tipo LinkDTO.

59
Implementação do Nível 3 de Maturidade - HATEOAS

A especificação JAX-RS não dispões de uma implementação pronta para disponibilizar HATEOAS
em uma API REST, desta forma, será necessário implementar uma classe que irá nos auxiliar na
construção das URIs HATEOAS em nossos resources REST.

Para isso será desenvolvido uma classe abstrata chamada HateoasResolver, essa classe irá conter os
métodos que irão auxiliar na construção das URIs de cada DTO da API REST, onde cada resource da API
REST irá conter uma implementação de HateoasResolver.

A implementação da classe HateoasResolver poderá ser visualizada com mais detalhes no


repositório do BitBucket.

60
Implementação do Nível 3 de Maturidade - HATEOAS

No primeiro exemplo, será implementado o bloqueio e desbloqueio de um usuário na API REST,


este bloqueio será utilizado na implementação da autenticação, onde usuários bloqueados não poderão
autenticar na API REST.

Para isso, será criado um atributo booleano bloqueado no UsuarioDTO para identificar se um
usuário está bloqueado ou não.

61
Implementação do Nível 3 de Maturidade - HATEOAS

No UsuarioResource será criado dois métodos que serão utilizados para bloquear e desbloquear um
usuário, estes métodos serão disponibilizados via HATEOAS quando um usuário for requisitado a API
REST.

62
Implementação do Nível 3 de Maturidade - HATEOAS
A classe UsuarioHateoas tem como responsabilidade controlar a criação das URIs dos usuários
requisitados na API REST.

A classe UsuarioHateoas deverá estender da classe HateoasResolver passando por parâmetro o


Resource e o DTO que deverão ser controlados pelo HateoasResolver. O método resolveHateoas terá a
implementação para criar os links do UsuarioDTO passado por parâmetro.

63
Implementação do Nível 3 de Maturidade - HATEOAS
A classe UsuarioHateoas irá conter as regras de criação de cada link HATEOAS do usuário, quando o
método buildHateoasLink for chamado o link será criado e adicionado ao objeto UsuarioDTO, passando a
UriInfo, UsuarioDTO, o nome do método do resource e o nome do relacionamento (atributo rel do link
HATEOAS).

64
Implementação do Nível 3 de Maturidade - HATEOAS

Para utilizar a classe UsuarioHateoas no resource UsuarioResouce, é necessário injetar uma instância
do UriInfo com a anotação @Context, esta instância possui todas as informações da URI do resource do
usuário que o HateoasResolver necessita para criar os links.

Uma instância do UsuarioHateoas deverá ser criada no resource para utilizarmos dos seus recursos.

65
Implementação do Nível 3 de Maturidade - HATEOAS

Na classe UsuarioResource criamos dois métodos que irão auxiliar na chamada do método
buildHateoas da classe UsuarioHateoas, um método para receber uma coleção de UsuarioDTO e outro
método que irá receber um UsuarioDTO.

Estes métodos serão chamados em todos os métodos do resource que retornam usuários ao
cliente da API REST.

66
Implementação do Nível 3 de Maturidade - HATEOAS

Atualmente temos somente dois métodos que retornam usuários, estes métodos deverão chamar
o método criarHateoas antes de retornar as informações para o cliente da API REST, conforme a imagem
abaixo.

67
Implementação do Nível 3 de Maturidade - HATEOAS

Ao executar a chamada de da URI para buscar um usuário os links HATEOAS serão adicionados
automaticamente conforme as regras de negócio definidas na classe UsuarioHateoas.

68
Implementação do Nível 3 de Maturidade - HATEOAS

A partir do exemplo de implementação do HATEOAS do UsuarioDTO, os recursos que necessitam


de HATEOAS poderão ter as suas próprias implementações, como PedidoVendaHateoas, ClienteHateoas,
ProdutoHateoas e ItemPedidoVendaHateoas, contendo as regras de negócio e necessidades da API REST,
disponibilizando todos os links de navegação necessários para deixar a API RESTful mais clara e simples
possível ao cliente da API.

Ao implementar o nível 3 de maturidade REST podemos chamar a nossa API REST de API RESTful,
pois ela contempla todos os padrões arquiteturais REST definidos por Leonard Richardson.

69
Versionamento da API RESTful

Uma API RESTful completa e madura em um ambiente de produção poderá mudar com o tempo,
incluindo novas regras e funcionalidades, isso geralmente ocorre quando uma API possui vários clientes
ou quando novas funcionalidades são adicionadas com um pacote de versão incremental.

Muitas vezes, é necessário que um cliente atualize o contrato com a API, para que as
características da nova versão possam ser utilizadas, mantendo versões antigas em funcionamento para
outros clientes, para isso faz-se necessário a utilização de mecanismos para manter recursos em versões
diferentes para não quebrar contratos com outros clientes que consomem a API.

70
Versionamento da API RESTful

Uma das práticas adotadas para versionamento de serviços REST é incluir a versão nas URIs dos
serviços, de forma que todos os recursos estejam disponíveis a partir de uma versão, conforme o exemplo
abaixo:

http://localhost:8080/VendaRapidaRestAPI/api/rest/v1 (Acesso aos recursos da versão 1)

http://localhost:8080/VendaRapidaRestAPI/api/rest/v2 (Acesso aos recursos da versão 2)

71
Versionamento da API RESTful

Na API PedidoVendaRestAPI o versionamento é controlado pelo ApplicationPath da classe


ApplicationConfig, desta forma, todos os recursos registrados nesta configuração serão registrado na
versão definida no ApplicationPath.

Para configurar uma segunda versão (v2) sem quebrar o contrato com a primeira (v1), uma
segunda classe de configuração deverá ser criada, informando em seu ApplicationPath a versão v2, onde
cada configuração deverá registrar os seus resources.

72
Versionamento da API RESTful

Ao adotar a prática de versionamento a partir do ApplicationPath de uma API, deve-se evitar o uso
de muitas versões, isso irá complicar na manutenibilidade da API tornando-a complexa para o
desenvolvedor e para o cliente.

Desta forma, ao versionar uma API, versões mais antigas deverão ser removidas com o tempo,
informando aos clientes da API que uma nova versão da API deverá ser utilizada, em muitos casos, uma
versão mais atual poderá quebrar uma versão mais antiga, obrigado o cliente da API a realizar a migração
para uma nova versão.

73
Providers JAX-RS

Os providers são implementações utilizadas para customizar ou incluir características na API REST
em tempo de execução. As implementações podem controlar a serialização e desserialização de
entidades, mapeamento de exceções, interceptadores e controles de fluxos de entrada e saída, conforme
as necessidades da API.

Os providers devem ser implementados a partir de interfaces definidas na especificação JAX-RS, e


devem ser anotados com @Provider para que sejam registrado como provedores no container da
aplicação.

74
Providers JAX-RS

A maioria das implementações da especificação JAX-RS possuem providers padrões


implementados, como conversores de leitura e escrita de objetos para hipermídia JSON ou XML,
especificados pelas interfaces MessageBodyWriter<T> e MessageBodyReader<T>.

Outro provider comum encontrado em containers Java é mapeamento de exceções, especificado


pela interface ExceptionMapper<E>, a qual possui a responsabilidade de converter exceções Java em
respostas HTTP 5xx ou 4xx.

Os providers padrões podem ser customizados ou podem ser incluídos novos providers para
atender uma necessidade da API de forma global.

75
Mapeamento de Exceções de Negócio.

Ao construir uma API REST, as exceções devem ser de fácil compreensão ao cliente da API, de
forma que possa ser identificada as possíveis causas das exceções lançadas pela aplicação a partir de
mensagens bem definidas.

A partir desta premissa, a aplicação PedidoVendaRestAPI terá suas próprias exceções de negócio,
controladas por um provider que irá mapear as exceções e convertê-las em respostas amigáveis aos
clientes da API.

76
Mapeamento de Exceções de Negócio.

O provider padrão para mapeamento de exceções do container de aplicação Java irá converter
qualquer exceção java para um response 500 - Internal Server Error, este tipo de status HTTP deverá ser
retornado ao cliente somente quando um erro desconhecido ou não tratado pelo sistema ocorrer.

As exceções de regras de negócio deverão ser retornadas com o status 400 - Bad Request,
informando ao cliente da API que a requisição foi processada mas uma exceção foi lançada por uma
validação de negócio, ou quando uma chamada for executada em um momento incorreto pelo usuário a
partir do estado do recurso solicitado.

Desta forma, será desenvolvido um provider para mapear as exceções lançadas pela aplicação
originadas por chamadas JAX-RS.

77
Mapeamento de Exceções de Negócio

Ao criar um provider de mapeamento de exceções, é necessário definir quais tipos de exceções


deverão ser mapeadas pelo provider, para isso, será implementado uma exceção específica para as as
validações e regras de negócio da aplicação, conforme a imagem abaixo:

78
Mapeamento de Exceções de Negócio

Quando uma exceção ocorrer no sistema, independente do tipo, o provider de exceções irá mapear
e converter a exceção e uma mensagem para o cliente, controlando os status de resposta 400, 401 ou
500.

A classe ExceptionDTO será utilizada para representar o JSON de exceções da aplicação para o
cliente da API, conforme a imagem abaixo:

79
Mapeamento de Exceções de Negócio

A classe ExceptionMapperProvider deverá implementar a interface ExceptionMapper<E> do JAX-RS,


o parâmetro genérico E deverá receber o tipo de exceção que deverá ser mapeada, a classe Exception
informa que todas as exceções do tipo Exception ou que herdam de Exception serão mapeadas pelo
provider.

O provider deverá implementar o método toResponse(E exception), que irá converter a exceção
mapeada pelo provider em um Response HTTP do JAX-RS.

80
Mapeamento de Exceções de Negócio

O Response do método será composto pela entidade de ExceptionDTO, contendo a mensagem da


exceção mapeada pelo provider, onde o status 400 - Bad Request é definido quando a exceção for uma
instância de BusinessException, quando for NotAuthorizedException será 401 - Unauthorized, caso contrário
será 500 - Internal Server Error.

81
Mapeamento de Exceções de Negócio

Para ativar o provider na API REST, é necessário registrá-lo na classe de configuração


ApplicationConfig, desta forma todas as exceções lançadas pela aplicação irão passar pelo filtro de
exceções ExceptionMapperProvider.

82
Mapeamento de Exceções de Negócio

As exceções de regras de negócio da aplicação PedidoVendaRestAPI estão sendo lançadas com


RuntimeException, estas validações estão implementadas nas classes Repository de cada entidade, as
quais simulam um repositório de dados para exemplo de utilização da API.

Todas as exceções de validações e regras de negócio deverão ser alteradas para o tipo
BusinessException, neste exemplo, estamos considerando que todas as exceções diferentes de
BusinessException e NotAuthorizedException são exceções inesperadas da aplicação e são classificadas
como erros internos do sistema.

83
Mapeamento de Exceções de Negócio

A classe abstrata AbstractRepository possui um método padrão buscarPorId utilizado em todas as


Repository API REST, quando um DTO não é encontrado com o ID especificado, o método irá lançar uma
exceção do tipo BusinessException, resultando em 400 - Bad Request ao cliente da API.

84
Mapeamento de Exceções de Negócio

Ao requisitar a consulta de um usuário com ID inexistente, a API REST irá retornar para o cliente o
status 400 - Bad Request com a mensagem da exceção lançada pela aplicação.

O JSON do retorno é o ExceptionDTO criado automaticamente pelo ExceptionMapperProvider.

85
Segurança e Autenticação com JWT (Json Web Token)

Ao tornar uma API REST pública, devemos ter uma preocupação especial em relação a segurança,
onde os recursos expostos na rede estão suscetíveis a usos indevidos, especialmente quando é exposto
informações de domínio privado.

Uma forma de controlar o acesso aos recursos da API, é a utilização de login e senha a partir de um
usuário cadastrado no sistema, onde o login irá retornar um token de acesso ao cliente, liberando os
demais recursos da API REST ao usuário credenciado.

Uma das bibliotecas utilizadas para controles de autenticação em aplicações distribuídas é o JWT
(Json Web Token) a qual possibilita realizar o controle do token de forma robusta e segura compatível
com o padrão Auth0.

86
Segurança e Autenticação com JWT (Json Web Token)

O token JWT é dividido em três partes:

● Header: O header normalmente consiste em dois atributos: o tipo do token, que é JWT, e o
algoritmo de assinatura que está sendo usado, como HMAC SHA256 ou RSA, o header encontra-se
na primeira parte do token assinado.

● Payload: Define os metadados e Claims referente ao login efetuado, o payload encontra-se na


segunda parte do token assinado.

● Signature: Assinatura do token, esta informação é gerada com o algoritmo de assinatura definido
no header do token partir de uma chave privada definida pela aplicação, a assinatura é utilizada
para validar o token, garantindo que nenhuma informação do token seja alterada, assegurando a
autenticidade do usuário na API com um token válido.

87
Segurança e Autenticação com JWT (Json Web Token)

Exemplo de estrutura do token JWT.

88
Segurança e Autenticação com JWT (Json Web Token)

Fluxo de autenticação e acesso a recursos privados com JWT.

89
Segurança e Autenticação com JWT (Json Web Token)

Para utilizar a biblioteca JWT, é necessário a adição da dependência Maven no arquivo de


configuração pom.xml, essa dependência irá disponibilizar as classes de implementação do JWT para
auxiliar no gerenciamento de tokens na aplicação.

<dependencies>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>

90
Segurança e Autenticação com JWT (Json Web Token)
Após termos o acesso às classes da biblioteca JWT, iremos criar uma classe utilitária chamada
JWTUtil, esta classe irá auxiliar na criação do token no login do usuário para o cliente da API e será
utilizada para validar um token enviado do usuário ao acessar um recurso privado.

91
Segurança e Autenticação com JWT (Json Web Token)

O payload do token JWT é representado por um objeto JSON definido pela aplicação, este objeto
deve conter informações contextuais, metadados e Claims do login efetuado, estas informações são
criptografadas no token para acessá-las posteriormente em um recurso autenticado.

O payload do token não pode conter informações sensíveis, como senhas e dados bancários ou
informações pessoais, estas informações podem ser decodificadas por qualquer cliente JWT, obtendo
acesso a informações privilegiadas do usuário autenticado.

A partir de um token válido enviado pelo cabeçalho da requisição, pode-se obter informações do
usuário logado pelo payload descriptografado para o objeto JSON.

92
Segurança e Autenticação com JWT (Json Web Token)

O payload do token será representado pelo objeto LoginContext, esta classe terá informações sobre
o login efetuado na API, como usuário e data de login, outras informações refente ao contexto de login
poderão ser incluídas conforme a necessidade do desenvolvedor.

93
Segurança e Autenticação com JWT (Json Web Token)

Ao realizar o login, a API REST deverá retornar um JSON com o token válido, este token deverá
mantido e enviado pelo cliente da API para cada requisição a um recurso privado.

O token é representado pelo TokenDTO, que será criado quando o login for efetuado.

94
Segurança e Autenticação com JWT (Json Web Token)

O método login do UsuarioResource recebe um UsuarioDTO com o login e senha, o usuário é


consultado na classe UsuarioRepository para verificar a existência do usuário na aplicação, caso o usuário
existir será retornado um objeto de LoginContext com as informações do login do usuário, este objeto será
o payload do token criado pela classe JWTUtil.

A anotação PermitAll indica que o método será ignorado pelo provider de autenticação, tornando o
método de login público na API REST.

95
Segurança e Autenticação com JWT (Json Web Token)

A classe AuthenticationFilterProvider será o provider de validação de autenticação da API, este


provider irá lançar uma exceção NotAuthorizedException caso o token não for informado ou for inválido,
logo, esta exceção será mapeada pelo provider ExceptionMapperProvider que irá converter a exceção em
uma resposta 401 - Unauthorized para o cliente da API.

O provider AuthenticationFilterProvider deverá implementar a interface ContainerRequestFilter, que


irá disponibilizar o método filter, para aplicar os filtros de autenticação.

96
Segurança e Autenticação com JWT (Json Web Token)
Implementação do provider de autenticação, esta classe deverá ser registrada no ApplicationConfig.

97
Segurança e Autenticação com JWT (Json Web Token)

Ao acessar um recurso da API REST sem o token de autenticação, a API irá retornar o status 401 -
Unauthorized.

98
Segurança e Autenticação com JWT (Json Web Token)

Ao realizar o login com um usuário e senha válidos, a API irá retornar o token de acesso aos
recursos privados.

99
Segurança e Autenticação com JWT (Json Web Token)

Para acessar um recurso privado, o token deverá ser adicionado no cabeçalho da requisição API,
com o esquema Authorization: Bearer + “ “ + token.

100
Segurança e Autenticação com JWT (Json Web Token)

Em alguns casos, a regra de negócio necessita saber o usuário que está executando a requisição,
esta informação encontra-se no payload do token enviado pelo cliente da API, o qual poderá ser
convertido de JSON para um objeto LoginContext.

O provider AuthenticationFilterProvider possui a responsabilidade de obter o token do cabeçalho da


requisição para validá-lo com a classe JWTUtil, além de validar o token, o provider irá converter o payload
do token para um objeto LoginContext para que possamos ter acesso às informações do usuário logado em
cada requisição.

O LoginContext deverá ser armazenado em tempo de execução em um espaço de memória durante


a requisição para que os resources possam obter a instância do contexto criada pelo provider, para isso,
será utilizado uma ThreadLocal para armazenar o contexto.

101
Segurança e Autenticação com JWT (Json Web Token)

Cada requisição HTTP está vinculada a uma thread do container, onde a thread nunca possui duas
requisições ao mesmo tempo.

As threads possuem um espaço de memória que pode ser utilizado para armazenamento de
informações para utilização de escopo global ou local.

102
Segurança e Autenticação com JWT (Json Web Token)

Utilizaremos uma classe que fornece variáveis locais de threads do Java chamada ThreadLocal, ao
iniciar uma instância de ThreadLocal na aplicação a mesma estará vinculada a thread em que foi criada.

A instância da ThreadLocal irá guardar em memória de escopo local o contexto do usuário que
executou a requisição HTTP para a API REST, o controle das threads locais é implementado na classe
ContextRequestCache abaixo:

103
Segurança e Autenticação com JWT (Json Web Token)

O método validateToken implementado no provider AuthenticationFilterProvider irá chamar o


método startContextRequestCache que irá converter o payload do Claim para uma instância de
LoginContext, esta instância será mantida em cache por uma ThreadLocal da classe ContextRequestCache
enquanto a requisição estiver ativa.

104
Segurança e Autenticação com JWT (Json Web Token)

Para concluir o desenvolvimento da autenticação e controles de sessão de login na API RESTful,


será alterado o cadastro de Pedido de Venda no PedidoVendaResource para vincular o usuário logado
(UsuarioDTO) ao novo Pedido de Venda cadastrado no sistema.

105
Customização de Hypermedia JSON (Serialização e Desserialização)

O Provider de serialização e desserialização JSON possui formatações padrões para cada tipo de
dados, em alguns casos, a API REST necessita customizar a formatação de representação dos dados,
como datas, valores e enums.

A biblioteca Jackson é responsável pela conversão de objetos Java para JSON, esta biblioteca já
está como dependência transitiva da biblioteca JWT, portanto não será necessário declará-la
explicitamente no pom.xml.

A partir da classe ObjectMapper da biblioteca Jackson, podemos customizar a representação do


JSON e disponibilizá-las a partir de um provider.

106
Customização de Hypermedia JSON (Serialização e Desserialização)

A classe ObjectMapperFactory será uma fábrica de ObjectMapper, esta classe terá todas as
configurações da customização do JSON da API REST.

107
Customização de Hypermedia JSON (Serialização e Desserialização)

Para demonstrar um exemplo de customização JSON, será demonstrada a implementação de


serialização e desserialização do tipo Date do Java com um formato de data padrão definido pela API
REST.

A classe DateSerializer é implementada abaixo será responsável em converter todos os atributos do


tipo Date com um SimpleDateFormat, o resultado da formatação será escrito no JSON retornado ao
cliente da API.

108
Customização de Hypermedia JSON (Serialização e Desserialização)

A classe DateDesserializer é responsável em converter os valores que correspondem aos campos


Date dos DTOs para uma instância Date, o qual será atribuída ao DTO.

Caso o formato da data do JSON for inválido, a conversão irá retornar uma exceção ao cliente da
API.

109
Customização de Hypermedia JSON (Serialização e Desserialização)
A fábrica de ObjectMapper deverá registrar um módulo de customização, este módulo é criado a
partir da classe SimpleModule, adicionando as classes de serialização e desserialização do tipo Date do
Java.

A configuração atribuída ao método setSerializationInclusion indica para o ObjectMapper ignorar a


escrita de atributos nulos no JSON.

110
Customização de Hypermedia JSON (Serialização e Desserialização)

Após concluir a implementação do ObjectMapper customizado, o mesmo deverá ser registrado para
para o JAX-RS via provider, desta forma, a classe ObjectMapperProvider implementa a classe
ContextResolver do JAX-RS informando que um ObjectMapper customizado deverá ser utilizado para a
serialização e desserialização JSON dos DTOs da API REST.

111
Customização de Hypermedia JSON (Serialização e Desserialização)

Ao consultar um DTO com um atributo do tipo Date, a conversão da data para JSON será realizada
pelo ObjectMapper customizado, conforme a imagem abaixo:

112
Customização de Hypermedia JSON (Serialização e Desserialização)

A partir do exemplo de serialização e desserialização de atributos Java, outras customizações


poderão ser aplicadas para atender as necessidades da API REST, tornando a API altamente customizável
e adaptável para a leitura e escrita de tipos de dados de vários formatos enviados e recebidos pelo cliente
da API REST.

113
Disponibilizando a API RESTful para clientes Java

Ao disponibilizar uma API para que outras aplicações possam utilizá-la, faz-se necessário o
desenvolvimento de uma documentação da utilização dos recursos da API, para isso pode-se utilizar
algumas ferramentas de documentação de APIs, uma delas é o Swagger, que possui recursos avançados e
completos para a documentação de serviços REST.

Além da utilização de ferramentas de documentação UI, um documento poderá ser formulado e


entregue aos clientes descrevendo os recursos da API.

Ao disponibilizar uma API desenvolvida em JAX-RS para outro cliente Java EE, é possível
disponibilizar um artefato contendo as interfaces e DTOs para que o cliente da API possa consumir a API
de forma mais objetiva.

114
Disponibilizando a API RESTful para clientes Java

Em Java, existem duas formas de consumir uma API REST, de forma manual utilizando a classe
WebTarget identificada por uma URI de um recurso da rede, esta classe possibilita o consumo de recursos
HTTP utilizando os verbos.

Ao consumir as serviços com WebTarget, o cliente da API deverá realizar as tratativas de conversão
de JSON e XML manualmente para cada requisição ou resposta, tornando o uso da API onerosa.

A outra forma de consumir uma API é a utilização de Client Proxy, onde a API REST disponibiliza as
interfaces dos resources para que o cliente possa criar Proxies, realizando chamadas aos recursos da API
diretamente pelas interfaces da API de forma objetiva e transparente, desenvolvendo diretamente com
os objetos DTOs, sem a necessidade de se preocupar com a serialização e deserialização de objetos e
chamadas manuais com a utilização do WebTarget.

115
Disponibilizando a API RESTful para clientes Java

O exemplo de consumo da API RESTful será demonstrada a partir de uma aplicação Java Web
chamada VendaRapidaWeb, esta aplicação utiliza a tecnologia JSF(Java Server Faces) em conjunto com a
biblioteca Primefaces no desenvolvimento das páginas da aplicação.

Como o objetivo deste curso não é o desenvolvimento de páginas Web, o desenvolvimento do


front-end não será abordado no curso, focando somente no consumo da API RESTful em uma aplicação
Java EE.

A aplicação de exemplo poderá ser baixada do repositório BitBucket deste curso no link
disponibilizado no slide 5.

116
Disponibilizando a API RESTful para clientes Java

Os resources desenvolvidos no projeto VendaRapidaRestAPI estão implementados diretamente


em classes concretas, isso impossibilita a geração de um artefato da API com as interfaces e DTOs para
que possamos entregar ao cliente Java da API.

Para que possamos gerar o artefato entregável, o nosso projeto será separado por outro projeto
que irá compor as interfaces resources e DTOs.

117
Disponibilizando a API RESTful para clientes Java

Um novo projeto Maven será criado para gerar o artefato com as interfaces e resource e DTOs.

118
Disponibilizando a API RESTful para clientes Java

A opção maven-archetype-quickstart deverá ser selecionada para gerar um novo projeto com o
empacotamento jar.

119
Disponibilizando a API RESTful para clientes Java

O projeto será comum entre todos os projetos envolvidos com a API, desta forma, o nome do
projeto será VendaRapidaRestAPICommon.

120
Disponibilizando a API RESTful para clientes Java

Após criar o novo projeto Maven, o plugin de compilação deverá ser adicionado ao projeto no
pom.xml para que o maven possa compilar e empacotar o artefato com a versão 8 do Java.

<build>
<finalName>VendaRapidaRestAPICommon</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

121
Disponibilizando a API RESTful para clientes Java

A dependência da API do Java EE 8 deverá ser adicionada no pom.xml para que o projeto possa ter
acesso às anotações JAX-RS.

<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

122
Disponibilizando a API RESTful para clientes Java

Ao concluir a construção do projeto VendaRapidaRestAPICommon com o Maven, o workspace de


desenvolvimento do Eclipse IDE conterá três projetos, VendaRapidaRestAPI que implementa a API, o
VendaRapidaRestAPICommon que irá conter as interfaces e DTOs, e o VendaRapidaWeb que irá
consumir a API via interfaces resources do projeto Common.

123
Disponibilizando a API RESTful para clientes Java

Os projetos VendaRapidaRestAPI e VendaRapidaWeb deverão conter a dependência do projeto


VendaRapidaRestAPICommon, desta forma o VendaRapidaRestAPI poderá implementar as interfaces do
Common e o projeto Web poderá utilizar as interfaces da API para comunicação via REST.

Assim utilizamos o conceito de API (Application Programming Interface), onde o projeto Web
visualiza as interfaces da API sem ter acesso as implementações da API, conforme o diagrama de
dependências abaixo.

124
Disponibilizando a API RESTful para clientes Java

As dependências são configuradas pelo pom.xml do Maven, onde a tag <dependencies > dos
projetos VendaRapidaRestAPI e VendaRapidaWeb deverão conter a dependência Maven do projeto
VendaRapidaRestAPICommon, assim, ambos os projetos irão visualizar as interfaces e classes do
Common.

<dependencies>
<dependency>
<groupId>com.vendarapida.rest.api</groupId>
<artifactId>VendaRapidaRestAPICommon</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

125
Disponibilizando a API RESTful para clientes Java

Todos os DTOs do projeto VendaRapidaRestAPI deverão ser movidos para o projeto


VendaRapidaRestAPICommon, para que os clientes que irão consumir a API pelo artefato possam ter
acesso aos DTOs.

126
Disponibilizando a API RESTful para clientes Java

Os resources desenvolvidos no projeto VendaRapidaRestAPI deverão declarados como interfaces


no projeto VendaRapidaRestAPICommon, contendo somente a assinatura dos métodos e as anotações
do JAX-RS, a imagem abaixo demonstra o exemplo da interface do resource do Cliente.

127
Disponibilizando a API RESTful para clientes Java

O projeto VendaRapiraRestAPI deverá implementar as interfaces resources do projeto Common,


as implementações de resource poderão chamar classes de serviços de regras de negócio, realizar
consultas no banco de dados dentre outros processos necessários nas operações da API, sempre
realizando a conversão dos objetos trafegados para DTOs.

No exemplo de implementação das interfaces resources, será utilizado a anotação @ManagedBean,


tornando a implementação gerenciada pelo CDI (Context Dependency Injection) para realizar a injeção
da dependência do Repository.

128
Disponibilizando a API RESTful para clientes Java

A imagem abaixo demonstra a implementação da interface resource do Cliente. O restante das


implementações poderão ser visualizadas com mais detalhes no repositório do BitBucket disponibilizado
no slide 5.

129
Disponibilizando a API RESTful para clientes Java

A partir das interfaces resources, o projeto web poderá se comunicar com a API utilizando um
cliente REST Proxy.

A maioria das implementações JAX-RS disponibilizam implementações para realizar a


comunicação REST via interfaces resources, onde o proxy retorna uma instância da interface para
realizar a comunicação HTTP a partir das anotações contidas no resource.

Como estamos utilizando o servidor Jboss WildFly para rodar as aplicações, iremos utilizar a
implementação RESTEasy da Jboss para consumir a API.

Para rodar a aplicação com o Glassfish, WebLogic ou Payara a implementação Jersey JAX-RS,
deverá ser utilizada.

130
Disponibilizando a API RESTful para clientes Java

Para ter acesso a implementação do cliente RESTEasy, precisamos incluir a dependência da


biblioteca no pom.xml do projeto VendaRapidaWeb.

<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.6.3.Final</version>
</dependency>
</dependencies>

131
Disponibilizando a API RESTful para clientes Java

A classe ClientRestProxyService será o serviço responsável por criar e configurar o cliente a partir da
implementação RESTEasy, esta classe de serviço será utilizada pelos controllers das páginas JSF para
realizar a comunicação com a API RESTful.

132
Disponibilizando a API RESTful para clientes Java

Ao consumir uma API REST com customizações de Hypermedia, o cliente REST Java também
deverá conter as customizações do server para que a conversão de DTOs possa ser realizada
corretamente.

As customizações de Hypermedia da API estão implementadas no provider ObjectMapperProvider,


este provider deve estar disponível para o cliente para que o mesmo possa registrá-lo, compatibilizando a
serialização e desserialização de DTOs para JSON entre o cliente e o servidor.

133
Disponibilizando a API RESTful para clientes Java

Quando uma exceção é lançada pela API o provider ExceptionMapperProvider irá converter a
exceção em uma resposta com o status e mensagem correspondente a exceção lançada pela aplicação.

Para que o cliente REST possa obter as exceções lançadas no servidor, um provider deverá ser
implementado no lado do cliente, mapeando os status de respostas das requisições HTTP,
convertendo-as em exceções quando os códigos 4xx e 5xx retornarem como resposta.

O provider de exceções do cliente deverá implementar a interface ClientResponseFilter, esta


interface disponibiliza um método filter que permite realizar operações na requisição e resposta HTTP.

A partir do método filter os dados do Response poderão ser obtidos para implementar os
tratamentos de exceções no cliente da API.

134
Disponibilizando a API RESTful para clientes Java

Classe ClientResponseExceptionProvider que lança as exceções quando o Response for 4xx ou 5xx.

135
Disponibilizando a API RESTful para clientes Java

A classe ClientResponseExceptionProvider deverá ser registrada no cliente ResteasyClient para que o


provider de exceções possa ser executado nas requisições executadas pelo proxy gerenciado pelo
ResteasyWebTarget.

136
Disponibilizando a API RESTful para clientes Java
A tela de login é gerenciada pela classe FormLoginManager, o botão Entrar executa o método
efetuarLogin(), realizando uma chamada para a API RESTful enviando os dados de login pelo UsuarioDTO.

O token retornado pela API é adicionado em um atributo chamado “token” na sessão web para que
possa ser utilizado posteriormente nas chamadas aos recursos autenticados.

137
Disponibilizando a API RESTful para clientes Java

Após adicionar o token de autenticação da API na sessão web, um provider deverá ser
implementado para interceptar a requisição HTTP e adicionar no Header da requisição o token da sessão
do usuário.

A classe ClientAuthorizationHeaderProvider implementa a interface ClientRequestFilter que


disponibiliza o método filter para manipular a requisição REST, adicionando o Header Authorization com o
token obtido no login do usuário.

138
Disponibilizando a API RESTful para clientes Java

Por fim, o provider ClientAuthorizationHeaderProvider é registrado no cliente ResteasyClient, para


ser executado em cada chamada realizada pelo proxy do ResteasyWebTarget.

139
Disponibilizando a API RESTful para clientes Java

A tela de Clientes está implementada no projeto Web para exemplo de utilização da API RESTful
utilizando a comunicação com a API RESTful a partir das interfaces resources disponibilizadas ao cliente
Java EE.

140
Conclusão

A partir dos exemplos demonstrados neste curso, as aplicações em Java EE poderão implementar
APIs RESTful de forma completa e robusta, utilizando todos os recursos e práticas arquiteturais dos
níveis de maturidade REST utilizando os recursos que a especificação JAX-RS disponibiliza.

O projeto Web desenvolvido em Java EE é um exemplo prático da comunicação com uma API REST
desenvolvida com JAX-RS de forma descomplicada, utilizando os recursos de Client Proxy, realizando
chamadas para a API diretamente pelos métodos das interfaces resources.

Devemos prezar pelas boas práticas no desenvolvimento do código, deixando-o mais simples
possível, facilitando na manutenibilidade e entendimento das regras de negócio, uma API bem projetada
e objetiva terá um baixo custo em grandes alterações e manutenções, além de facilitar na utilização da
mesma.

141
Fontes:

● Livro RESTful Java with JAX-RS 2.0, 2nd Edition (OReilly):


http://shop.oreilly.com/product/0636920028925.do
● Nivelando sua Rest API:
https://www.infoq.com/br/articles/nivelando-sua-rest-api?fbclid=IwAR0yWC53Ac2etiG2thryyw
kseGrITuDxy8gkKg0avwLbEuvwQIOYoSudycY
● REST: Princípios e boas práticas: http://blog.caelum.com.br/rest-principios-e-boas-praticas/
● HTTP Status Code: https://www.restapitutorial.com/httpstatuscodes.html
● Java Community Process: https://download.oracle.com/otndocs/jcp/jaxrs-2_0-fr-eval-spec/
● Java EE 8 Deployment Descriptors:
https://medium.com/@swhp/javaee-8-deployment-descriptor-ad451485fb30
● Eclipse IDE: https://www.eclipse.org/downloads/packages/
● WildFly: http://wildfly.org/downloads/
● Modelo de Maturidade de Richardson:
http://www.nessauepa.com.br/blog/2013/07/traducao-modelo-de-maturidade-de-richardson/
142
Fontes:

● History of REST, SOAP, POX and JSON Web Services:


https://github.com/ServiceStackV3/mythz_blog/blob/master/pages/154.md
● SOAP vs. POX vs. REST: https://www.innoq.com/blog/st/2006/11/soap-vs.-pox-vs.-rest/
● REST vs HTTP + POX vs SOAP:
http://www.trachtenberg.com/blog/2006/11/06/rest-vs-httppox-vs-soap/
● Richardson Maturity Model: https://restfulapi.net/richardson-maturity-model/
● Entendendo HATEOAS: http://www.semeru.com.br/blog/en/
● Criando, evoluindo e fazendo o controle de versão de APIs e de contratos de microsserviços
https://docs.microsoft.com/pt-br/dotnet/standard/microservices-architecture/architect-microser
vice-container-applications/maintain-microservice-apis
● Understanding JAX-RS Providers
https://www.logicbig.com/tutorials/java-ee-tutorial/jax-rs/providers.html
● JSON Web Token – Conhecendo o JWT na teoria e na prática
https://imasters.com.br/desenvolvimento/json-web-token-conhecendo-o-jwt-na-teoria-e-na-prat
ica

143
Fontes:

● RESTFul API – usando JWT para autenticação


https://imasters.com.br/apis-microsservicos/restful-api-jwt-para-autenticacao
● JWT Introduction: https://jwt.io/introduction/
● Aprendendo a usar o escopo Thread-Local Java
https://imasters.com.br/back-end/aprendendo-usar-o-escopo-thread-local-java
● Customizing ObjectMapper in a JAX-RS application
https://cassiomolin.com/2017/11/21/customizing-objectmapper-in-a-jaxrs-application/

144

Você também pode gostar