SlideShare uma empresa Scribd logo
1 de 144
Baixar para ler offline
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
● 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.
Tópicos abordados:
3
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!
Introdução
4
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
Requisitos
5
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.
Web Service:
6
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.
Estrutura do Protocolo HTTP
7
● 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.
Estrutura do Protocolo HTTP
8
● 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.
Estrutura do Protocolo HTTP
9
● 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.
Estrutura do Protocolo HTTP
10
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.
Verbos HTTP
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
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.
API - Application Programming Interface
12
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.
REST - Representational State Transfer
Requisição
POST http:localhost:8080/MinhaAplicacao/cliente
{
“nome”: “João”,
“aniversario”: “16/10/1993”
}
Resposta 201 - Created:
{
“idCliente”: 1
}
Requisição
GET http:localhost:8080/MinhaAplicacao/cliente/1
Resposta 200 - OK:
{
“idCliente”: 1,
“nome”: “João”,
“aniversario”: “16/10/1993”
}
13
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.
Diferenças entre REST e RESTful.
14
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.
Implementação da Especificação JAX-RS
15
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
Convenção de URIs REST amigáveis.
16
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.
Modelagem de dados
17
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.
Modelagem de dados
18
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.
DTO - Data Transfer Object
19
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:
Aplicação Web Java EE com Maven
20
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.
Aplicação Web Java EE com Maven
21
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.
Aplicação Web Java EE com Maven
22
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.
Aplicação Web Java EE com Maven
23
<?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>
Aplicação Web Java EE com Maven
24
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:
Aplicação Web Java EE com Maven
<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
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.
Aplicação Web Java EE com Maven
<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
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.
Aplicação Web Java EE com Maven
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
27
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:
Aplicação Web Java EE com Maven
28
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.
Aplicação Web Java EE com Maven
29
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.
Repositório de dados da API REST.
30
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.
Configuração JAX-RS e o primeiro serviço REST.
31
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.
Configuração JAX-RS e o primeiro serviço REST.
32
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.
Configuração JAX-RS e o primeiro serviço REST.
33
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.
Configuração JAX-RS e o primeiro serviço REST.
34
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.
Configuração JAX-RS e o primeiro serviço REST.
35
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.
Parâmetros de URIs @PathParam e @QueryParam
36
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.
Parâmetros de URL @PathParam e @QueryParam
37
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.
Parâmetros de URL @PathParam e @QueryParam
38
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
Parâmetros de URL @PathParam e @QueryParam
39
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.
Níveis de Maturidade REST.
40
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.
Implementação do Nível 0 de Maturidade - POX.
41
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
Implementação do Nível 0 de Maturidade - POX.
42
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
Implementação do Nível 1 de Maturidade - Recursos
43
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
Implementação do Nível 2 de Maturidade - Verbos HTTP
44
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)
Implementação do Nível 2 de Maturidade - Verbos HTTP
45
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!
Implementação do Nível 2 de Maturidade - Verbos HTTP
46
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.
Implementação da API REST
47
Implementação da API REST
48
Implementação do resource do Cliente com as operações de CRUD com verbos HTTP
Implementação da API REST
49
Implementação do resource do Usuário com as operações de CRUD com verbos HTTP
Implementação da API REST
50
Implementação do resource do Produto com as operações de CRUD com verbos HTTP
Implementação da API REST
51
Implementação do resource do PedidoVenda com as operações de CRUD com verbos HTTP
Implementação da API REST
52
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.
Implementação da API REST
53
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}.
Implementação do Resource do ItemPedidoVenda com as operações de CRUD com verbos HTTP
Implementação da API REST
54
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.
Implementação da API REST
55
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.
Implementação do Nível 3 de Maturidade - HATEOAS
56
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.
Implementação do Nível 3 de Maturidade - HATEOAS
57
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 ”
}]
}
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.
Implementação do Nível 3 de Maturidade - HATEOAS
58
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.
Implementação do Nível 3 de Maturidade - HATEOAS
59
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.
Implementação do Nível 3 de Maturidade - HATEOAS
60
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.
Implementação do Nível 3 de Maturidade - HATEOAS
61
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.
Implementação do Nível 3 de Maturidade - HATEOAS
62
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.
Implementação do Nível 3 de Maturidade - HATEOAS
63
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).
Implementação do Nível 3 de Maturidade - HATEOAS
64
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.
Implementação do Nível 3 de Maturidade - HATEOAS
65
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.
Implementação do Nível 3 de Maturidade - HATEOAS
66
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.
Implementação do Nível 3 de Maturidade - HATEOAS
67
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.
Implementação do Nível 3 de Maturidade - HATEOAS
68
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.
Implementação do Nível 3 de Maturidade - HATEOAS
69
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.
Versionamento da API RESTful
70
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)
Versionamento da API RESTful
71
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.
Versionamento da API RESTful
72
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.
Versionamento da API RESTful
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
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.
Providers JAX-RS
75
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.
Mapeamento de Exceções de Negócio.
76
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.
Mapeamento de Exceções de Negócio.
77
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:
Mapeamento de Exceções de Negócio
78
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:
Mapeamento de Exceções de Negócio
79
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.
Mapeamento de Exceções de Negócio
80
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.
Mapeamento de Exceções de Negócio
81
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.
Mapeamento de Exceções de Negócio
82
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.
Mapeamento de Exceções de Negócio
83
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.
Mapeamento de Exceções de Negócio
84
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.
Mapeamento de Exceções de Negócio
85
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.
Segurança e Autenticação com JWT (Json Web Token)
86
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.
Segurança e Autenticação com JWT (Json Web Token)
87
Exemplo de estrutura do token JWT.
Segurança e Autenticação com JWT (Json Web Token)
88
Fluxo de autenticação e acesso a recursos privados com JWT.
Segurança e Autenticação com JWT (Json Web Token)
89
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.
Segurança e Autenticação com JWT (Json Web Token)
90
<dependencies>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
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.
Segurança e Autenticação com JWT (Json Web Token)
91
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.
Segurança e Autenticação com JWT (Json Web Token)
92
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.
Segurança e Autenticação com JWT (Json Web Token)
93
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.
Segurança e Autenticação com JWT (Json Web Token)
94
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.
Segurança e Autenticação com JWT (Json Web Token)
95
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.
Segurança e Autenticação com JWT (Json Web Token)
96
Implementação do provider de autenticação, esta classe deverá ser registrada no ApplicationConfig.
Segurança e Autenticação com JWT (Json Web Token)
97
Ao acessar um recurso da API REST sem o token de autenticação, a API irá retornar o status 401 -
Unauthorized.
Segurança e Autenticação com JWT (Json Web Token)
98
Ao realizar o login com um usuário e senha válidos, a API irá retornar o token de acesso aos
recursos privados.
Segurança e Autenticação com JWT (Json Web Token)
99
Para acessar um recurso privado, o token deverá ser adicionado no cabeçalho da requisição API,
com o esquema Authorization: Bearer + “ “ + token.
Segurança e Autenticação com JWT (Json Web Token)
100
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.
Segurança e Autenticação com JWT (Json Web Token)
101
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.
Segurança e Autenticação com JWT (Json Web Token)
102
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:
Segurança e Autenticação com JWT (Json Web Token)
103
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.
Segurança e Autenticação com JWT (Json Web Token)
104
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.
Segurança e Autenticação com JWT (Json Web Token)
105
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.
Customização de Hypermedia JSON (Serialização e Desserialização)
106
A classe ObjectMapperFactory será uma fábrica de ObjectMapper, esta classe terá todas as
configurações da customização do JSON da API REST.
Customização de Hypermedia JSON (Serialização e Desserialização)
107
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.
Customização de Hypermedia JSON (Serialização e Desserialização)
108
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.
Customização de Hypermedia JSON (Serialização e Desserialização)
109
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.
Customização de Hypermedia JSON (Serialização e Desserialização)
110
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.
Customização de Hypermedia JSON (Serialização e Desserialização)
111
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:
Customização de Hypermedia JSON (Serialização e Desserialização)
112
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.
Customização de Hypermedia JSON (Serialização e Desserialização)
113
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.
Disponibilizando a API RESTful para clientes Java
114
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.
Disponibilizando a API RESTful para clientes Java
115
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.
Disponibilizando a API RESTful para clientes Java
116
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.
Disponibilizando a API RESTful para clientes Java
117
Um novo projeto Maven será criado para gerar o artefato com as interfaces e resource e DTOs.
Disponibilizando a API RESTful para clientes Java
118
A opção maven-archetype-quickstart deverá ser selecionada para gerar um novo projeto com o
empacotamento jar.
Disponibilizando a API RESTful para clientes Java
119
O projeto será comum entre todos os projetos envolvidos com a API, desta forma, o nome do
projeto será VendaRapidaRestAPICommon.
Disponibilizando a API RESTful para clientes Java
120
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.
Disponibilizando a API RESTful para clientes Java
121
<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>
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.
Disponibilizando a API RESTful para clientes Java
122
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
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.
Disponibilizando a API RESTful para clientes Java
123
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.
Disponibilizando a API RESTful para clientes Java
124
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.
Disponibilizando a API RESTful para clientes Java
125
<dependencies>
<dependency>
<groupId>com.vendarapida.rest.api</groupId>
<artifactId>VendaRapidaRestAPICommon</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
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.
Disponibilizando a API RESTful para clientes Java
126
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.
Disponibilizando a API RESTful para clientes Java
127
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.
Disponibilizando a API RESTful para clientes Java
128
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.
Disponibilizando a API RESTful para clientes Java
129
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.
Disponibilizando a API RESTful para clientes Java
130
Para ter acesso a implementação do cliente RESTEasy, precisamos incluir a dependência da
biblioteca no pom.xml do projeto VendaRapidaWeb.
Disponibilizando a API RESTful para clientes Java
131
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.6.3.Final</version>
</dependency>
</dependencies>
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.
Disponibilizando a API RESTful para clientes Java
132
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.
Disponibilizando a API RESTful para clientes Java
133
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.
Disponibilizando a API RESTful para clientes Java
134
Classe ClientResponseExceptionProvider que lança as exceções quando o Response for 4xx ou 5xx.
Disponibilizando a API RESTful para clientes Java
135
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.
Disponibilizando a API RESTful para clientes Java
136
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.
Disponibilizando a API RESTful para clientes Java
137
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.
Disponibilizando a API RESTful para clientes Java
138
Por fim, o provider ClientAuthorizationHeaderProvider é registrado no cliente ResteasyClient, para
ser executado em cada chamada realizada pelo proxy do ResteasyWebTarget.
Disponibilizando a API RESTful para clientes Java
139
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.
Disponibilizando a API RESTful para clientes Java
140
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.
Conclusão
141
● 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/
Fontes:
142
● 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
Fontes:
143
● 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/
Fontes:
144

Mais conteúdo relacionado

Mais procurados

Curso de Java Persistence API (JPA) (Java EE 7)
Curso de Java Persistence API (JPA) (Java EE 7)Curso de Java Persistence API (JPA) (Java EE 7)
Curso de Java Persistence API (JPA) (Java EE 7)Helder da Rocha
 
Using cookies and sessions
Using cookies and sessionsUsing cookies and sessions
Using cookies and sessionsNuha Noor
 
APIs, REST e RESTful: O que os programadores precisam saber? - Marcos Echevar...
APIs, REST e RESTful: O que os programadores precisam saber? - Marcos Echevar...APIs, REST e RESTful: O que os programadores precisam saber? - Marcos Echevar...
APIs, REST e RESTful: O que os programadores precisam saber? - Marcos Echevar...Tchelinux
 
Curso de WebServlets (Java EE 7)
Curso de WebServlets (Java EE 7)Curso de WebServlets (Java EE 7)
Curso de WebServlets (Java EE 7)Helder da Rocha
 
What is REST API? REST API Concepts and Examples | Edureka
What is REST API? REST API Concepts and Examples | EdurekaWhat is REST API? REST API Concepts and Examples | Edureka
What is REST API? REST API Concepts and Examples | EdurekaEdureka!
 
Exemplo especificacaoderequisitos(locadora)
Exemplo especificacaoderequisitos(locadora)Exemplo especificacaoderequisitos(locadora)
Exemplo especificacaoderequisitos(locadora)Bruno Santana
 
Using Java to implement SOAP Web Services: JAX-WS
Using Java to implement SOAP Web Services: JAX-WS�Using Java to implement SOAP Web Services: JAX-WS�
Using Java to implement SOAP Web Services: JAX-WSKatrien Verbert
 
Aula 01 - JavaScript: Introdução
Aula 01 - JavaScript: IntroduçãoAula 01 - JavaScript: Introdução
Aula 01 - JavaScript: IntroduçãoJessyka Lage
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Visual Engineering
 
1.Introdução Banco de Dados
1.Introdução Banco de Dados1.Introdução Banco de Dados
1.Introdução Banco de Dadosvini_campos
 
Curso CSS 3 - Aula Introdutória com conceitos básicos
Curso CSS 3 - Aula Introdutória com conceitos básicosCurso CSS 3 - Aula Introdutória com conceitos básicos
Curso CSS 3 - Aula Introdutória com conceitos básicosTiago Antônio da Silva
 
Herança em Banco de Dados Objeto-Relacional (BDOR)
Herança em Banco de Dados Objeto-Relacional (BDOR)Herança em Banco de Dados Objeto-Relacional (BDOR)
Herança em Banco de Dados Objeto-Relacional (BDOR)Rafael Barbolo
 

Mais procurados (20)

Curso de Java Persistence API (JPA) (Java EE 7)
Curso de Java Persistence API (JPA) (Java EE 7)Curso de Java Persistence API (JPA) (Java EE 7)
Curso de Java Persistence API (JPA) (Java EE 7)
 
Using cookies and sessions
Using cookies and sessionsUsing cookies and sessions
Using cookies and sessions
 
APIs, REST e RESTful: O que os programadores precisam saber? - Marcos Echevar...
APIs, REST e RESTful: O que os programadores precisam saber? - Marcos Echevar...APIs, REST e RESTful: O que os programadores precisam saber? - Marcos Echevar...
APIs, REST e RESTful: O que os programadores precisam saber? - Marcos Echevar...
 
Curso de WebServlets (Java EE 7)
Curso de WebServlets (Java EE 7)Curso de WebServlets (Java EE 7)
Curso de WebServlets (Java EE 7)
 
What is REST API? REST API Concepts and Examples | Edureka
What is REST API? REST API Concepts and Examples | EdurekaWhat is REST API? REST API Concepts and Examples | Edureka
What is REST API? REST API Concepts and Examples | Edureka
 
Rest API
Rest APIRest API
Rest API
 
Exemplo especificacaoderequisitos(locadora)
Exemplo especificacaoderequisitos(locadora)Exemplo especificacaoderequisitos(locadora)
Exemplo especificacaoderequisitos(locadora)
 
Using Java to implement SOAP Web Services: JAX-WS
Using Java to implement SOAP Web Services: JAX-WS�Using Java to implement SOAP Web Services: JAX-WS�
Using Java to implement SOAP Web Services: JAX-WS
 
Express js
Express jsExpress js
Express js
 
Modelagem de dados
Modelagem de dadosModelagem de dados
Modelagem de dados
 
Html Básico
Html BásicoHtml Básico
Html Básico
 
Padrão Adapter
Padrão AdapterPadrão Adapter
Padrão Adapter
 
Aula 01 - JavaScript: Introdução
Aula 01 - JavaScript: IntroduçãoAula 01 - JavaScript: Introdução
Aula 01 - JavaScript: Introdução
 
Fundamentos de arquitetura Web
Fundamentos de arquitetura WebFundamentos de arquitetura Web
Fundamentos de arquitetura Web
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.
 
1.Introdução Banco de Dados
1.Introdução Banco de Dados1.Introdução Banco de Dados
1.Introdução Banco de Dados
 
Curso CSS 3 - Aula Introdutória com conceitos básicos
Curso CSS 3 - Aula Introdutória com conceitos básicosCurso CSS 3 - Aula Introdutória com conceitos básicos
Curso CSS 3 - Aula Introdutória com conceitos básicos
 
Introducao ao C#
Introducao ao C#Introducao ao C#
Introducao ao C#
 
REST API
REST APIREST API
REST API
 
Herança em Banco de Dados Objeto-Relacional (BDOR)
Herança em Banco de Dados Objeto-Relacional (BDOR)Herança em Banco de Dados Objeto-Relacional (BDOR)
Herança em Banco de Dados Objeto-Relacional (BDOR)
 

Semelhante a Desenvolvimento de uma API REST com Java EE

Novidades do JAX-RS 2.0
Novidades do JAX-RS 2.0Novidades do JAX-RS 2.0
Novidades do JAX-RS 2.0jesuinoPower
 
REST vs GraphQL - A batalha das APIs.pdf
REST vs GraphQL - A batalha das APIs.pdfREST vs GraphQL - A batalha das APIs.pdf
REST vs GraphQL - A batalha das APIs.pdfBrunoAlbuquerque864673
 
Workshop do Bem: O mundo das APIs
Workshop do Bem: O mundo das APIsWorkshop do Bem: O mundo das APIs
Workshop do Bem: O mundo das APIsHeider Lopes
 
O MUNDO DAS APIS OTIMIZANDO A INTEGRAÇÃO DE SISTEMAS
O MUNDO DAS APIS OTIMIZANDO A INTEGRAÇÃO DE SISTEMASO MUNDO DAS APIS OTIMIZANDO A INTEGRAÇÃO DE SISTEMAS
O MUNDO DAS APIS OTIMIZANDO A INTEGRAÇÃO DE SISTEMASHeider Lopes
 
Web Sphere Application Server
Web Sphere Application ServerWeb Sphere Application Server
Web Sphere Application ServerFabricio Carvalho
 
REST vs GraphQL - A batalha das APIs.pdf
REST vs GraphQL - A batalha das APIs.pdfREST vs GraphQL - A batalha das APIs.pdf
REST vs GraphQL - A batalha das APIs.pdfBrunoAlbuquerque864673
 
Criando e consumindo webservice REST com PHP e JSON
Criando e consumindo webservice REST com PHP e JSONCriando e consumindo webservice REST com PHP e JSON
Criando e consumindo webservice REST com PHP e JSONAmbiente Livre
 
Criando e consumindo webservice REST com PHP e JSON
Criando e consumindo webservice REST com PHP e JSONCriando e consumindo webservice REST com PHP e JSON
Criando e consumindo webservice REST com PHP e JSONMarcio Junior Vieira
 
201406Carvalho
201406Carvalho201406Carvalho
201406CarvalhoAfonso Pra
 
Conhecendo o Novo REST Framework
Conhecendo o Novo REST FrameworkConhecendo o Novo REST Framework
Conhecendo o Novo REST FrameworkMario Guedes
 
Arquitetura de Serviços - SOA, REST, Microservices e a plataforma .NET
Arquitetura de Serviços - SOA, REST, Microservices e a plataforma .NETArquitetura de Serviços - SOA, REST, Microservices e a plataforma .NET
Arquitetura de Serviços - SOA, REST, Microservices e a plataforma .NETRenato Groff
 
JME Web Services API: um estudo de caso
JME Web Services API: um estudo de casoJME Web Services API: um estudo de caso
JME Web Services API: um estudo de casoLuiz Matos
 

Semelhante a Desenvolvimento de uma API REST com Java EE (20)

Palestra Sobre REST
Palestra Sobre RESTPalestra Sobre REST
Palestra Sobre REST
 
Novidades do JAX-RS 2.0
Novidades do JAX-RS 2.0Novidades do JAX-RS 2.0
Novidades do JAX-RS 2.0
 
Web Services
Web ServicesWeb Services
Web Services
 
REST vs GraphQL - A batalha das APIs.pdf
REST vs GraphQL - A batalha das APIs.pdfREST vs GraphQL - A batalha das APIs.pdf
REST vs GraphQL - A batalha das APIs.pdf
 
Workshop do Bem: O mundo das APIs
Workshop do Bem: O mundo das APIsWorkshop do Bem: O mundo das APIs
Workshop do Bem: O mundo das APIs
 
O MUNDO DAS APIS OTIMIZANDO A INTEGRAÇÃO DE SISTEMAS
O MUNDO DAS APIS OTIMIZANDO A INTEGRAÇÃO DE SISTEMASO MUNDO DAS APIS OTIMIZANDO A INTEGRAÇÃO DE SISTEMAS
O MUNDO DAS APIS OTIMIZANDO A INTEGRAÇÃO DE SISTEMAS
 
Web Sphere Application Server
Web Sphere Application ServerWeb Sphere Application Server
Web Sphere Application Server
 
REST vs GraphQL - A batalha das APIs.pdf
REST vs GraphQL - A batalha das APIs.pdfREST vs GraphQL - A batalha das APIs.pdf
REST vs GraphQL - A batalha das APIs.pdf
 
Criando e consumindo webservice REST com PHP e JSON
Criando e consumindo webservice REST com PHP e JSONCriando e consumindo webservice REST com PHP e JSON
Criando e consumindo webservice REST com PHP e JSON
 
Criando e consumindo webservice REST com PHP e JSON
Criando e consumindo webservice REST com PHP e JSONCriando e consumindo webservice REST com PHP e JSON
Criando e consumindo webservice REST com PHP e JSON
 
Web service
Web serviceWeb service
Web service
 
201406Carvalho
201406Carvalho201406Carvalho
201406Carvalho
 
Web Sphere
Web SphereWeb Sphere
Web Sphere
 
Conhecendo o Novo REST Framework
Conhecendo o Novo REST FrameworkConhecendo o Novo REST Framework
Conhecendo o Novo REST Framework
 
Arquitetura de Serviços - SOA, REST, Microservices e a plataforma .NET
Arquitetura de Serviços - SOA, REST, Microservices e a plataforma .NETArquitetura de Serviços - SOA, REST, Microservices e a plataforma .NET
Arquitetura de Serviços - SOA, REST, Microservices e a plataforma .NET
 
Rest introdução
Rest introduçãoRest introdução
Rest introdução
 
JME Web Services API: um estudo de caso
JME Web Services API: um estudo de casoJME Web Services API: um estudo de caso
JME Web Services API: um estudo de caso
 
WebServices intro
WebServices introWebServices intro
WebServices intro
 
Web Service - XML
Web Service - XMLWeb Service - XML
Web Service - XML
 
Soa Woa Rest
Soa Woa RestSoa Woa Rest
Soa Woa Rest
 

Desenvolvimento de uma API REST com Java EE

  • 1. 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
  • 2. 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
  • 3. ● 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. Tópicos abordados: 3
  • 4. 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! Introdução 4
  • 5. 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 Requisitos 5
  • 6. 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. Web Service: 6
  • 7. 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. Estrutura do Protocolo HTTP 7
  • 8. ● 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. Estrutura do Protocolo HTTP 8
  • 9. ● 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. Estrutura do Protocolo HTTP 9
  • 10. ● 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. Estrutura do Protocolo HTTP 10
  • 11. 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. Verbos HTTP 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
  • 12. 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. API - Application Programming Interface 12
  • 13. 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. REST - Representational State Transfer Requisição POST http:localhost:8080/MinhaAplicacao/cliente { “nome”: “João”, “aniversario”: “16/10/1993” } Resposta 201 - Created: { “idCliente”: 1 } Requisição GET http:localhost:8080/MinhaAplicacao/cliente/1 Resposta 200 - OK: { “idCliente”: 1, “nome”: “João”, “aniversario”: “16/10/1993” } 13
  • 14. 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. Diferenças entre REST e RESTful. 14
  • 15. 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. Implementação da Especificação JAX-RS 15
  • 16. 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 Convenção de URIs REST amigáveis. 16
  • 17. 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. Modelagem de dados 17
  • 18. 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. Modelagem de dados 18
  • 19. 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. DTO - Data Transfer Object 19
  • 20. 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: Aplicação Web Java EE com Maven 20
  • 21. 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. Aplicação Web Java EE com Maven 21
  • 22. 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. Aplicação Web Java EE com Maven 22
  • 23. 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. Aplicação Web Java EE com Maven 23
  • 24. <?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> Aplicação Web Java EE com Maven 24
  • 25. 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: Aplicação Web Java EE com Maven <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
  • 26. 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. Aplicação Web Java EE com Maven <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
  • 27. 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. Aplicação Web Java EE com Maven <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>8.0</version> <scope>provided</scope> </dependency> </dependencies> 27
  • 28. 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: Aplicação Web Java EE com Maven 28
  • 29. 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. Aplicação Web Java EE com Maven 29
  • 30. 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. Repositório de dados da API REST. 30
  • 31. 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. Configuração JAX-RS e o primeiro serviço REST. 31
  • 32. 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. Configuração JAX-RS e o primeiro serviço REST. 32
  • 33. 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. Configuração JAX-RS e o primeiro serviço REST. 33
  • 34. 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. Configuração JAX-RS e o primeiro serviço REST. 34
  • 35. 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. Configuração JAX-RS e o primeiro serviço REST. 35
  • 36. 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. Parâmetros de URIs @PathParam e @QueryParam 36
  • 37. 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. Parâmetros de URL @PathParam e @QueryParam 37
  • 38. 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. Parâmetros de URL @PathParam e @QueryParam 38
  • 39. 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 Parâmetros de URL @PathParam e @QueryParam 39
  • 40. 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. Níveis de Maturidade REST. 40
  • 41. 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. Implementação do Nível 0 de Maturidade - POX. 41
  • 42. 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 Implementação do Nível 0 de Maturidade - POX. 42
  • 43. 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 Implementação do Nível 1 de Maturidade - Recursos 43
  • 44. 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 Implementação do Nível 2 de Maturidade - Verbos HTTP 44
  • 45. 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) Implementação do Nível 2 de Maturidade - Verbos HTTP 45
  • 46. 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! Implementação do Nível 2 de Maturidade - Verbos HTTP 46
  • 47. 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. Implementação da API REST 47
  • 48. Implementação da API REST 48 Implementação do resource do Cliente com as operações de CRUD com verbos HTTP
  • 49. Implementação da API REST 49 Implementação do resource do Usuário com as operações de CRUD com verbos HTTP
  • 50. Implementação da API REST 50 Implementação do resource do Produto com as operações de CRUD com verbos HTTP
  • 51. Implementação da API REST 51 Implementação do resource do PedidoVenda com as operações de CRUD com verbos HTTP
  • 52. Implementação da API REST 52 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.
  • 53. Implementação da API REST 53 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}.
  • 54. Implementação do Resource do ItemPedidoVenda com as operações de CRUD com verbos HTTP Implementação da API REST 54
  • 55. 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. Implementação da API REST 55
  • 56. 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. Implementação do Nível 3 de Maturidade - HATEOAS 56
  • 57. 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. Implementação do Nível 3 de Maturidade - HATEOAS 57 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 ” }] }
  • 58. 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. Implementação do Nível 3 de Maturidade - HATEOAS 58
  • 59. 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. Implementação do Nível 3 de Maturidade - HATEOAS 59
  • 60. 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. Implementação do Nível 3 de Maturidade - HATEOAS 60
  • 61. 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. Implementação do Nível 3 de Maturidade - HATEOAS 61
  • 62. 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. Implementação do Nível 3 de Maturidade - HATEOAS 62
  • 63. 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. Implementação do Nível 3 de Maturidade - HATEOAS 63
  • 64. 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). Implementação do Nível 3 de Maturidade - HATEOAS 64
  • 65. 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. Implementação do Nível 3 de Maturidade - HATEOAS 65
  • 66. 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. Implementação do Nível 3 de Maturidade - HATEOAS 66
  • 67. 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. Implementação do Nível 3 de Maturidade - HATEOAS 67
  • 68. 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. Implementação do Nível 3 de Maturidade - HATEOAS 68
  • 69. 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. Implementação do Nível 3 de Maturidade - HATEOAS 69
  • 70. 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. Versionamento da API RESTful 70
  • 71. 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) Versionamento da API RESTful 71
  • 72. 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. Versionamento da API RESTful 72
  • 73. 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. Versionamento da API RESTful 73
  • 74. 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
  • 75. 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. Providers JAX-RS 75
  • 76. 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. Mapeamento de Exceções de Negócio. 76
  • 77. 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. Mapeamento de Exceções de Negócio. 77
  • 78. 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: Mapeamento de Exceções de Negócio 78
  • 79. 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: Mapeamento de Exceções de Negócio 79
  • 80. 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. Mapeamento de Exceções de Negócio 80
  • 81. 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. Mapeamento de Exceções de Negócio 81
  • 82. 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. Mapeamento de Exceções de Negócio 82
  • 83. 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. Mapeamento de Exceções de Negócio 83
  • 84. 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. Mapeamento de Exceções de Negócio 84
  • 85. 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. Mapeamento de Exceções de Negócio 85
  • 86. 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. Segurança e Autenticação com JWT (Json Web Token) 86
  • 87. 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. Segurança e Autenticação com JWT (Json Web Token) 87
  • 88. Exemplo de estrutura do token JWT. Segurança e Autenticação com JWT (Json Web Token) 88
  • 89. Fluxo de autenticação e acesso a recursos privados com JWT. Segurança e Autenticação com JWT (Json Web Token) 89
  • 90. 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. Segurança e Autenticação com JWT (Json Web Token) 90 <dependencies> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> </dependencies>
  • 91. 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. Segurança e Autenticação com JWT (Json Web Token) 91
  • 92. 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. Segurança e Autenticação com JWT (Json Web Token) 92
  • 93. 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. Segurança e Autenticação com JWT (Json Web Token) 93
  • 94. 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. Segurança e Autenticação com JWT (Json Web Token) 94
  • 95. 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. Segurança e Autenticação com JWT (Json Web Token) 95
  • 96. 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. Segurança e Autenticação com JWT (Json Web Token) 96
  • 97. Implementação do provider de autenticação, esta classe deverá ser registrada no ApplicationConfig. Segurança e Autenticação com JWT (Json Web Token) 97
  • 98. Ao acessar um recurso da API REST sem o token de autenticação, a API irá retornar o status 401 - Unauthorized. Segurança e Autenticação com JWT (Json Web Token) 98
  • 99. Ao realizar o login com um usuário e senha válidos, a API irá retornar o token de acesso aos recursos privados. Segurança e Autenticação com JWT (Json Web Token) 99
  • 100. Para acessar um recurso privado, o token deverá ser adicionado no cabeçalho da requisição API, com o esquema Authorization: Bearer + “ “ + token. Segurança e Autenticação com JWT (Json Web Token) 100
  • 101. 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. Segurança e Autenticação com JWT (Json Web Token) 101
  • 102. 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. Segurança e Autenticação com JWT (Json Web Token) 102
  • 103. 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: Segurança e Autenticação com JWT (Json Web Token) 103
  • 104. 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. Segurança e Autenticação com JWT (Json Web Token) 104
  • 105. 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. Segurança e Autenticação com JWT (Json Web Token) 105
  • 106. 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. Customização de Hypermedia JSON (Serialização e Desserialização) 106
  • 107. A classe ObjectMapperFactory será uma fábrica de ObjectMapper, esta classe terá todas as configurações da customização do JSON da API REST. Customização de Hypermedia JSON (Serialização e Desserialização) 107
  • 108. 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. Customização de Hypermedia JSON (Serialização e Desserialização) 108
  • 109. 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. Customização de Hypermedia JSON (Serialização e Desserialização) 109
  • 110. 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. Customização de Hypermedia JSON (Serialização e Desserialização) 110
  • 111. 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. Customização de Hypermedia JSON (Serialização e Desserialização) 111
  • 112. 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: Customização de Hypermedia JSON (Serialização e Desserialização) 112
  • 113. 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. Customização de Hypermedia JSON (Serialização e Desserialização) 113
  • 114. 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. Disponibilizando a API RESTful para clientes Java 114
  • 115. 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. Disponibilizando a API RESTful para clientes Java 115
  • 116. 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. Disponibilizando a API RESTful para clientes Java 116
  • 117. 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. Disponibilizando a API RESTful para clientes Java 117
  • 118. Um novo projeto Maven será criado para gerar o artefato com as interfaces e resource e DTOs. Disponibilizando a API RESTful para clientes Java 118
  • 119. A opção maven-archetype-quickstart deverá ser selecionada para gerar um novo projeto com o empacotamento jar. Disponibilizando a API RESTful para clientes Java 119
  • 120. O projeto será comum entre todos os projetos envolvidos com a API, desta forma, o nome do projeto será VendaRapidaRestAPICommon. Disponibilizando a API RESTful para clientes Java 120
  • 121. 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. Disponibilizando a API RESTful para clientes Java 121 <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>
  • 122. 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. Disponibilizando a API RESTful para clientes Java 122 <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>8.0</version> <scope>provided</scope> </dependency> </dependencies>
  • 123. 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. Disponibilizando a API RESTful para clientes Java 123
  • 124. 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. Disponibilizando a API RESTful para clientes Java 124
  • 125. 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. Disponibilizando a API RESTful para clientes Java 125 <dependencies> <dependency> <groupId>com.vendarapida.rest.api</groupId> <artifactId>VendaRapidaRestAPICommon</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
  • 126. 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. Disponibilizando a API RESTful para clientes Java 126
  • 127. 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. Disponibilizando a API RESTful para clientes Java 127
  • 128. 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. Disponibilizando a API RESTful para clientes Java 128
  • 129. 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. Disponibilizando a API RESTful para clientes Java 129
  • 130. 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. Disponibilizando a API RESTful para clientes Java 130
  • 131. Para ter acesso a implementação do cliente RESTEasy, precisamos incluir a dependência da biblioteca no pom.xml do projeto VendaRapidaWeb. Disponibilizando a API RESTful para clientes Java 131 <dependencies> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-client</artifactId> <version>3.6.3.Final</version> </dependency> </dependencies>
  • 132. 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. Disponibilizando a API RESTful para clientes Java 132
  • 133. 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. Disponibilizando a API RESTful para clientes Java 133
  • 134. 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. Disponibilizando a API RESTful para clientes Java 134
  • 135. Classe ClientResponseExceptionProvider que lança as exceções quando o Response for 4xx ou 5xx. Disponibilizando a API RESTful para clientes Java 135
  • 136. 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. Disponibilizando a API RESTful para clientes Java 136
  • 137. 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. Disponibilizando a API RESTful para clientes Java 137
  • 138. 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. Disponibilizando a API RESTful para clientes Java 138
  • 139. Por fim, o provider ClientAuthorizationHeaderProvider é registrado no cliente ResteasyClient, para ser executado em cada chamada realizada pelo proxy do ResteasyWebTarget. Disponibilizando a API RESTful para clientes Java 139
  • 140. 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. Disponibilizando a API RESTful para clientes Java 140
  • 141. 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. Conclusão 141
  • 142. ● 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/ Fontes: 142
  • 143. ● 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 Fontes: 143
  • 144. ● 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/ Fontes: 144