Escolar Documentos
Profissional Documentos
Cultura Documentos
● Web Service.
● Estrutura do protocolo HTTP.
● Verbos HTTP.
● API - Application Programming Interface (Interface de Programação de Aplicações).
● REST - Representational State Transfer (Transferência de Estado Representacional).
● Diferença entre REST e RESTful.
● Implementações da Especificação JAX-RS.
● Convenção de URIs REST amigáveis.
● Modelagem de dados.
● DTO - Data Transfer Object (Objeto de Transferência de Dados).
● Aplicação Web Java EE com Maven.
● Repositório de dados da API REST.
● Configuração JAX-RS e o primeiro serviço REST.
● Parâmetros de URIs @PathParam e @QueryParam
2
Tópicos abordados:
3
Introdução
Este curso tem como objetivo demonstrar o desenvolvimento de uma API RESTful com Java EE
iniciando pelos conceitos do protocolo HTTP. Após a apresentação básica da estrutura HTTP será
demonstrado os padrões utilizados no desenvolvimento de uma API RESTful.
Além da API RESTful, serão apresentados algumas funcionalidades do JAX-RS, como tratamento
de exceções com a utilização de Providers, customização de Hypermedia, autenticação com JWT (Json
Web Token) e a exportação das interfaces da API RESTful para que outras aplicações java possam
consumir a API via cliente proxy.
Bons estudos!
4
Requisitos
● Java JDK 8.
● Eclipse IDE.
● JBoss WildFly Server versão 14 ou superior.
● Git.
● Postman
5
Web Service:
Com a evolução dos sistemas computacionais, a integração entre sistemas diferentes vem
crescendo cada vez mais.
A comunicação entre os sistemas via Web Services normalmente é realizada a partir do protocolo
HTTP, onde dados são trafegados entre um cliente e um servidor, com serviços expostos na rede.
6
Estrutura do Protocolo HTTP
O protocolo HTTP (Hypertext Transport Protocol) é uma forma padronizada de tráfego de informações
na Web, onde que o cliente envia uma requisição (Request) e o servidor retorna um uma resposta (Response).
7
Estrutura do Protocolo HTTP
● Headers: Os Headers são uma coleção de metadados que trafegam entre o cliente e o servidor por
chave e valor, estes metadados possuem informações referente ao servidor que a requisição está sendo
executada, tipos de Hypermedia que está sendo trafegado, controles de acesso, autenticação, controles
de cache, tamanho do dado trafegado, entre outras informações que podem ser repassadas para o
cliente e para o servidor. Os headers podem ser customizados conforme a necessidade pelo
desenvolvedor e são informações transitivas em cada requisição / resposta.
● Cookie: Esta estrutura também possui informações de metadados, no entanto os cookies são utilizados
para manter informações no cliente, como uma sessão de login. Os cookies são registrados no cliente
com o nome de domínio, chave e valor, versão e data de expiração. Os cookies são informações não
transitivas, ou seja, não se perdem a cada requisição / resposta. Na maioria dos casos, um cookie é criado
com um token de autenticação quando um usuário realiza o login em um sistema, e este token é enviado
via Header na requisição para poder acessar recursos restritos.
8
Estrutura do Protocolo HTTP
● Status Code: O Status Code é a forma utilizada pelo protocolo HTTP para informar ao cliente o estado
da resposta, se houve erros de negócio, se a requisição foi processada com sucesso ou se ocorreu um
erro interno no sistema, os Status Codes são divididos por famílias e possuem três atributos:
○ Code: Código em formato numérico do tipo inteiro.
○ Reason: Razão do Status Code, descrição do código.
○ Family: Família a qual o Status Code pertence.
9
Estrutura do Protocolo HTTP
● Body: O corpo do protocolo HTTP possui as informações que de fato interessam ao negócio entre o
cliente e o servidor, estes dados são transportados em formato de texto e binário, no caso dos dados em
formato textual, geralmente é utilizado criptografia HTTPS onde os dados são criptografados para
trafegar com segurança, esta criptografia necessita de um certificado digital instalado no servidor da
aplicação.
No corpo da requisição o cliente pode enviar dados para o servidor processar e o servidor poderá
retornar informações na resposta para o cliente processar.
10
Verbos HTTP
O protocolo HTTP possui um conjunto de verbos para indicar ao servidor quais ações devem ser
executadas. Na tabela abaixo estão listados apenas alguns verbos utilizados em aplicações REST.
Verbo: Ação:
11
API - Application Programming Interface
Uma API após ser modelada não pode sofrer grandes mudanças, para não impactar os sistemas que
a utilizam, desta forma, ela deve ser bem projetada.
12
REST - Representational State Transfer
REST (Transferência de Estado Representacional) é um estilo arquitetural que define um conjunto
de serviços de uma aplicação Web, esses serviços oferecem a outras aplicações a representação de dados
que definem o estado do recurso solicitado, geralmente é utilizado os formatos HTML, JSON e XML ou
binário.
Para que um Web Service seja considerado REST, o mesmo deve utilizar o protocolo HTTP, os
serviços devem ser stateless, utilizar URIs amigáveis, utilizar os verbos HTTP para definição das
operações executadas e os componentes do sistema não podem visualizar além da sua camada da API.
Requisição Requisição
POST http:localhost:8080/MinhaAplicacao/cliente GET http:localhost:8080/MinhaAplicacao/cliente/1
{ Resposta 200 - OK:
“nome”: “João”, {
“aniversario”: “16/10/1993” “idCliente”: 1,
} “nome”: “João”,
Resposta 201 - Created: “aniversario”: “16/10/1993”
{ }
“idCliente”: 1
} 13
Diferenças entre REST e RESTful.
O RESTful é normalmente usado para se referir a serviços da Web que implementam essa
arquitetura, utilizando os quatro níveis de maturidade REST.
Desta forma, um conjunto de serviços REST somente podem ser considerados uma API RESTful
somente se atender ao modelo arquitetural REST de forma completa.
14
Implementação da Especificação JAX-RS
A especificação JAX-RS (JSR339) desenvolvida pela JCP (Java Community Process) documenta
como os desenvolvedores da comunidade Java e empresas de tecnologia devem implementar a
especificação, estas implementações são distribuídas em containers Java EE, bibliotecas e frameworks.
Atualmente as implementações mais utilizadas são Jersey da Sun (Glassfish, Payara e WebLogic),
RestEasy da JBoss (WildFly), Apache CXF (Tomcat).
15
Convenção de URIs REST amigáveis.
As URIs de acesso aos recursos REST devem ser amigáveis para que o cliente possa compreender o
uso da API, as URIs devem conter nomes descritivos, facilitando o entendimento das funcionalidades dos
recursos expostos.
As URIs amigáveis não utilizam CamelCase em sua definição, em caso de separação de palavras, deve-se
utilizar o hífen, exemplo: http://localhost:8080/MinhaAplicacao/api/rest/v1/cliente/buscar-por-codigo
16
Modelagem de dados
Durante o curso, será desenvolvido uma aplicação RESTful a partir de um modelo de dados, esta
aplicação consiste em uma API para cadastrar Usuários, Clientes, Produtos e Pedidos de Venda.
Após o desenvolvimento da API RESTful será disponibilizado uma aplicação pronta em Java EE
com JSF (Java Server Faces) para que possamos implementar um cliente que irá comunicar com a API de
Pedidos de Venda.
17
Modelagem de dados
Este tópico demonstra a modelagem de dados que será utilizada como exemplo para o
desenvolvimento da API RESTful, segue abaixo o diagrama de entidades e relacionamento a qual irá
representar uma API de cadastro de Pedidos de Venda.
18
DTO - Data Transfer Object
A utilização de DTOs para trafegar dados é necessária para não expor dados sensíveis da aplicação
externamente, desta forma, um DTO pode representar uma entidade do banco de dados, mas ela não
precisa ter necessariamente todos os atributos da entidade, outro detalhe a ser levado em consideração
é que um DTO poderá conter atributos customizados sem impactar diretamente em sua entidade.
19
Aplicação Web Java EE com Maven
Inicialmente será criado uma aplicação Java EE pelo Maven conforme a imagem abaixo:
20
Aplicação Web Java EE com Maven
Selecione a pasta no workspace que deverá ser criado o projeto, após este passo, selecionar o
Archetype maven-archetype-webapp para o Maven criar a estrutura e arquivos de um projeto Java EE.
21
Aplicação Web Java EE com Maven
Por fim, deverá ser informado o Group Id (grupo em que a aplicação pertence), Artifact Id (Nome
do projeto), Version (versão do projeto) e o Package (pacote de classes do projeto) .
Após esta etapa o Maven irá criar os arquivos e pastas necessárias para um projeto Java EE.
22
Aplicação Web Java EE com Maven
Por padrão, o Maven não cria o arquivo web.xml com as configurações necessárias para rodar o
projeto corretamente, desta forma, é necessário obter o xml de exemplo no site da Oracle para incluir no
projeto no link: http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/index.html#1 ou o
exemplo do web.xml poderá ser copiado no próximo slide.
23
Aplicação Web Java EE com Maven
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee webapp_4_0.xsd"
version="4.0">
<display-name>VendaRapidaRestAPI</display-name>
</web-app>
24
Aplicação Web Java EE com Maven
Após incluir as configurações básicas no projeto Java EE, é necessário informar o Maven a versão
do Java em que o projeto será compilado. Esta configuração deverá ser incluída no pom.xml. Neste caso
será utilizado a versão 8 do Java, conforme a configuração abaixo:
<build>
<finalName>VendaRapidaRestAPI</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
25
Aplicação Web Java EE com Maven
26
Aplicação Web Java EE com Maven
Para que a aplicação possa utilizar os recursos do JAX-RS é necessário incluir a dependência da API
do Java EE, desta forma teremos acesso às classes, interfaces e anotações para poder utilizar todos os
recursos disponíveis da plataforma Java EE.
Neste caso, será utilizado a versão 8 do Java EE com escopo provided, desta forma o Maven não irá
empacotar a dependência do Java EE no projeto, pois a mesma será disponibilizada pelo servidor de
aplicação.
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
27
Aplicação Web Java EE com Maven
Após configurar a aplicação Java Web, é necessário executar o Maven Update no projeto para que
as configurações realizadas sejam efetivadas.
O Eclipse IDE utiliza os Facets para definir características e requisitos do projeto, além de auxiliar a
IDE em conjunto com o Maven na compilação e empacotamento da aplicação. A configuração do plugin
maven-war-plugin no pom.xml informa ao Maven que a versão 4.0 será utilizada para o empacotamento
WAR, desta forma, é necessário alterar o Facet Dynamic Web Module do eclipse para a versão 4.0 nas
propriedades do projeto conforme a imagem abaixo:
28
Aplicação Web Java EE com Maven
29
Repositório de dados da API REST.
Durante o desenvolvimento da API REST, vamos precisar de um repositório de dados para que
possamos realizar simulações na utilização da API, as aplicações reais utilizam um banco de dados e um
framework para acessar a base de dados.
Para simplificar o desenvolvimento do projeto, iremos simular os repositórios dados com Managed
Bean de escopo de aplicação, cada entidade do modelo de dados terá a sua classe Repository que irá
simular um DAO (Data Access Object), a partir destas classes os nossos serviços REST irão obter
informações para disponibilizar aos clientes que irão consumir a API.
As classes de repositório de dados irão manter os dados em memória enquanto a aplicação estiver
sendo executada.
30
Configuração JAX-RS e o primeiro serviço REST.
Os serviços REST são representados por classes Java, essas classes devem ser configuradas com
anotações para informar ao servidor de aplicação a URI de acesso aos serviços.
A partir dos conceitos apresentados até agora, será criado uma classe ClienteDTO que irá
representar entidade Cliente do nosso modelo, e uma classe ClienteResource que irá representar a classe
de serviços REST para realizar operações com o Cliente.
31
Configuração JAX-RS e o primeiro serviço REST.
Para criar uma classe de Resource, algumas anotações deverão ser utilizadas para compor o
serviço, sendo elas:
@Path: Utilizado para informar o caminho de acesso ao resource ou método do resource, esta
anotação deverá ser informada na classe resource e nos métodos da classe, compondo a URI de acesso
aos serviços.
@Consumes: Utilizado para informar o tipo de Hypermedia que o serviço irá aceitar, geralmente é
utilizado JSON ou XML.
@Produces: Utilizado para informar o tipo de Hypermedia que o serviço irá produzir, geralmente é
utilizado JSON ou XML.
Os verbos HTTP são definidos pelas anotações @GET, @POST, @PUT, @DELETE, @PATCH e
@OPTIONS.
32
Configuração JAX-RS e o primeiro serviço REST.
Segue abaixo a classe ClienteResource configurada com as anotações JAX-RS para acessar os seus
serviços REST, o método buscarClientes() foi implementado para retornar uma lista de ClienteDTO.
33
Configuração JAX-RS e o primeiro serviço REST.
Para que os Resources estejam disponíveis para o acesso via URI REST, é necessário informar ao
servidor de aplicação quais classes deverão ser registradas como serviço web.
Essa configuração é realizada a partir da classe javax.ws.rs.core.Application, para isso, será criado
uma classe chamada ApplicationConfig que irá extender da classe javax.ws.rs.core.Application
sobrescrevendo o método getClasses(), este método deverá retornar uma coleção de classes de todos os
resources REST. A anotação @ApplicationPath é utilizada para informar o caminho URL que os recursos
serão registrados.
34
Configuração JAX-RS e o primeiro serviço REST.
Por padrão o navegador utiliza o verbo GET do HTTP para acessar recursos da web.
35
Parâmetros de URIs @PathParam e @QueryParam
Em algumas requisições REST é necessário enviar parâmetros pela URI para realizar uma operação
ou acessar um recurso específico, os parâmetros mais utilizados são os parâmetros de caminho e
parâmetros de operações arbitrárias, sendo eles:
@PathParam: Utilizado para compor o caminho de um recurso em uma URI, este tipo de parâmetro
também é utilizado para acessar sub recursos de um recurso. Exemplo:
36
Parâmetros de URL @PathParam e @QueryParam
O parâmetro deve estar identificado com chaves {nomeParametro} no Path do método para que o
JAX-RS possa identificar que esta parte da URI pertence a um PathParam.
37
Parâmetros de URL @PathParam e @QueryParam
38
Parâmetros de URL @PathParam e @QueryParam
O serviços compostos pelo QueryParam deverão ser repassados após o ponto de interrogação da URI do
método.
39
Níveis de Maturidade REST.
Os níveis de maturidade REST propostos por Leonard Richardson definem o modelo arquitetural
REST em níveis de implementação, onde cada nível propõem padrões para solução de problemas.
40
Implementação do Nível 0 de Maturidade - POX.
Este nível de implementação não utilizam resources, verbos HTTP e HATEOAS, e são
disponibilizados em uma única URI e um único verbo HTTP, geralmente POST, para trafegar dados em
XML.
41
Implementação do Nível 0 de Maturidade - POX.
O exemplo de um serviço REST em nível zero pode ser identificado pelas chamadas URI, onde
somente o nome do método está exposto para o cliente com a utilização do verbo POST sem a
identificação do recurso que está sendo acessado. Com exemplo do serviço abaixo, o ApplicationPath e o
Path do resource ficariam com uma String vazia, e a URI ficaria da seguinte forma:
POST http://localhost:8080/VendaRapidaRestAPI/buscar-clientes
42
Implementação do Nível 1 de Maturidade - Recursos
A implementação no nível 1 de maturidade REST faz o uso de URIs sobre uma URI, ou seja, o acesso
a um recurso é identificado por uma URI. Quando queremos realizar operações sobre uma entidade ou
processo, esta entidade ou processo é identificado em uma URI, para então termos acesso às URIs
disponíveis, exemplo:
http://localhost:8080/VendaRapidaRestAPI/cliente/cadastrar
http://localhost:8080/VendaRapidaRestAPI/cliente/excluir/1
43
Implementação do Nível 2 de Maturidade - Verbos HTTP
O nível de maturidade 2 contempla a utilização dos verbos HTTP para realizar operações na API
REST, todas as operações de CRUD (Create, Read, Update, Delete) são realizadas pelo verbo HTTP.
O nível de maturidade 1 não utiliza os verbos HTTP, necessitando a identificação das operações de
CRUD por URI, exemplo:
http://localhost:8080/VendaRapidaRestAPI/cliente/buscar/1
http://localhost:8080/VendaRapidaRestAPI/cliente/cadastrar
http://localhost:8080/VendaRapidaRestAPI/cliente/atualizar/1
http://localhost:8080/VendaRapidaRestAPI/cliente/excluir/1
44
Implementação do Nível 2 de Maturidade - Verbos HTTP
No nível de maturidade 2 fica mais simples de realizar as operações de CRUD, utilizando o que o
HTTP oferece de melhor para identificar o que está sendo realizado no recurso acessado, os verbos!
45
Implementação do Nível 2 de Maturidade - Verbos HTTP
Avançamos bastante com os padrões REST apresentados até agora, a partir do nível 2 de
maturidade, podemos dar continuidade no desenvolvimento da API REST de cadastros de Pedidos de
Venda.
A partir do modelo de dados apresentado no slide 18 (Modelagem de dados), será criado os DTOs,
Resources e Repository de cada entidade representada no modelo nossa aplicação.
Cada resource irá contemplar as operações de CRUD seguindo os padrões REST do nível de
maturidade 2.
Mão na massa!
46
Implementação da API REST
Para iniciar a implementação da API REST, os DTOs deverão herdar da classe abstrata
AbstractDTO, essa classe abstrata possui um método getId() que os DTOs deverão implementar, este
método deverá retornar o ID do DTO, esta abstração tem como objetivo padronizar métodos e atributos
genéricos dos DTOs da API.
47
Implementação da API REST
48
Implementação da API REST
49
Implementação da API REST
50
Implementação da API REST
51
Implementação da API REST
52
Implementação da API REST
Por padrão, todos os sub resources devem conter em seu Path o ID do resource pai, onde
cada método do resource deverá conter um PathParam para mapear o ID do registro pai.
No exemplo abaixo, o Path é definido por pedidovenda/{idPedidoVenda}/itempedidovenda e
todos os métodos do resource devem ter como precedência o PathParam de {idPedidoVenda}.
53
Implementação da API REST
54
Implementação da API REST
Após deixar a API REST com todas as funcionalidades que um cliente da API necessita para
utilizá-la, não podemos classificar a API como RESTful, pois estamos utilizando recursos de nível de
maturidade 2.
Para torná-la uma API RESTful é necessário a implementação do nível de maturidade 3, que utiliza
o mecanismo de HATEOAS na representação dos estados das entidades trafegadas na API REST.
55
Implementação do Nível 3 de Maturidade - HATEOAS
Quando navegamos em um site, ele nos oferece opções de ações e navegação entre as páginas
disponíveis na web, isso facilita a ergonomia do site para o usuário.
Da mesma forma que um site dispões de links de ações e navegação, uma API RESTful deve
disponibilizar ao cliente da API as ações que podem ser executadas a partir do recurso solicitado, estas
ações são disponibilizadas por links URIs, desta forma facilitamos a navegação entre os recursos da API
além das opções que podem ser tomadas a partir do estado do recurso requisitado.
56
Implementação do Nível 3 de Maturidade - HATEOAS
Quando requisitamos um usuário na API REST, o HATEOAS poderá retornar na lista de links com
as ações possíveis que podem ser tomadas a partir do estado do usuário requisitado.
No exemplo abaixo, as ações disponíveis são repassadas para o cliente da API REST em uma lista de
links, informando que a ação de bloquear está disponível para ser executada com o usuário retornado.
Requisição
GET http://localhost:8080/VendaRapidaRestAPI/api/rest/v1/usuario/1
Resposta 200 - OK:
{
“idUsuario”: 1,
“login”: “joao”,
“links”:[ {
“rel”: “bloquear”
“href”: “http://localhost:8080/VendaRapidaRestAPI/api/rest/v1/usuario/bloquear/1 ”
}]
}
57
Implementação do Nível 3 de Maturidade - HATEOAS
58
Implementação do Nível 3 de Maturidade - HATEOAS
Um DTO poderá conter uma lista de links HATEOAS, considerando que todos os DTOs da
aplicação herdam da classe abstrata AbstractDTO, a lista de links será adicionada na classe AbstractDTO,
desta forma todos os DTOs irão herdar a lista de links do tipo LinkDTO.
59
Implementação do Nível 3 de Maturidade - HATEOAS
A especificação JAX-RS não dispões de uma implementação pronta para disponibilizar HATEOAS
em uma API REST, desta forma, será necessário implementar uma classe que irá nos auxiliar na
construção das URIs HATEOAS em nossos resources REST.
Para isso será desenvolvido uma classe abstrata chamada HateoasResolver, essa classe irá conter os
métodos que irão auxiliar na construção das URIs de cada DTO da API REST, onde cada resource da API
REST irá conter uma implementação de HateoasResolver.
60
Implementação do Nível 3 de Maturidade - HATEOAS
Para isso, será criado um atributo booleano bloqueado no UsuarioDTO para identificar se um
usuário está bloqueado ou não.
61
Implementação do Nível 3 de Maturidade - HATEOAS
No UsuarioResource será criado dois métodos que serão utilizados para bloquear e desbloquear um
usuário, estes métodos serão disponibilizados via HATEOAS quando um usuário for requisitado a API
REST.
62
Implementação do Nível 3 de Maturidade - HATEOAS
A classe UsuarioHateoas tem como responsabilidade controlar a criação das URIs dos usuários
requisitados na API REST.
63
Implementação do Nível 3 de Maturidade - HATEOAS
A classe UsuarioHateoas irá conter as regras de criação de cada link HATEOAS do usuário, quando o
método buildHateoasLink for chamado o link será criado e adicionado ao objeto UsuarioDTO, passando a
UriInfo, UsuarioDTO, o nome do método do resource e o nome do relacionamento (atributo rel do link
HATEOAS).
64
Implementação do Nível 3 de Maturidade - HATEOAS
Para utilizar a classe UsuarioHateoas no resource UsuarioResouce, é necessário injetar uma instância
do UriInfo com a anotação @Context, esta instância possui todas as informações da URI do resource do
usuário que o HateoasResolver necessita para criar os links.
Uma instância do UsuarioHateoas deverá ser criada no resource para utilizarmos dos seus recursos.
65
Implementação do Nível 3 de Maturidade - HATEOAS
Na classe UsuarioResource criamos dois métodos que irão auxiliar na chamada do método
buildHateoas da classe UsuarioHateoas, um método para receber uma coleção de UsuarioDTO e outro
método que irá receber um UsuarioDTO.
Estes métodos serão chamados em todos os métodos do resource que retornam usuários ao
cliente da API REST.
66
Implementação do Nível 3 de Maturidade - HATEOAS
Atualmente temos somente dois métodos que retornam usuários, estes métodos deverão chamar
o método criarHateoas antes de retornar as informações para o cliente da API REST, conforme a imagem
abaixo.
67
Implementação do Nível 3 de Maturidade - HATEOAS
Ao executar a chamada de da URI para buscar um usuário os links HATEOAS serão adicionados
automaticamente conforme as regras de negócio definidas na classe UsuarioHateoas.
68
Implementação do Nível 3 de Maturidade - HATEOAS
Ao implementar o nível 3 de maturidade REST podemos chamar a nossa API REST de API RESTful,
pois ela contempla todos os padrões arquiteturais REST definidos por Leonard Richardson.
69
Versionamento da API RESTful
Uma API RESTful completa e madura em um ambiente de produção poderá mudar com o tempo,
incluindo novas regras e funcionalidades, isso geralmente ocorre quando uma API possui vários clientes
ou quando novas funcionalidades são adicionadas com um pacote de versão incremental.
Muitas vezes, é necessário que um cliente atualize o contrato com a API, para que as
características da nova versão possam ser utilizadas, mantendo versões antigas em funcionamento para
outros clientes, para isso faz-se necessário a utilização de mecanismos para manter recursos em versões
diferentes para não quebrar contratos com outros clientes que consomem a API.
70
Versionamento da API RESTful
Uma das práticas adotadas para versionamento de serviços REST é incluir a versão nas URIs dos
serviços, de forma que todos os recursos estejam disponíveis a partir de uma versão, conforme o exemplo
abaixo:
71
Versionamento da API RESTful
Para configurar uma segunda versão (v2) sem quebrar o contrato com a primeira (v1), uma
segunda classe de configuração deverá ser criada, informando em seu ApplicationPath a versão v2, onde
cada configuração deverá registrar os seus resources.
72
Versionamento da API RESTful
Ao adotar a prática de versionamento a partir do ApplicationPath de uma API, deve-se evitar o uso
de muitas versões, isso irá complicar na manutenibilidade da API tornando-a complexa para o
desenvolvedor e para o cliente.
Desta forma, ao versionar uma API, versões mais antigas deverão ser removidas com o tempo,
informando aos clientes da API que uma nova versão da API deverá ser utilizada, em muitos casos, uma
versão mais atual poderá quebrar uma versão mais antiga, obrigado o cliente da API a realizar a migração
para uma nova versão.
73
Providers JAX-RS
Os providers são implementações utilizadas para customizar ou incluir características na API REST
em tempo de execução. As implementações podem controlar a serialização e desserialização de
entidades, mapeamento de exceções, interceptadores e controles de fluxos de entrada e saída, conforme
as necessidades da API.
74
Providers JAX-RS
Os providers padrões podem ser customizados ou podem ser incluídos novos providers para
atender uma necessidade da API de forma global.
75
Mapeamento de Exceções de Negócio.
Ao construir uma API REST, as exceções devem ser de fácil compreensão ao cliente da API, de
forma que possa ser identificada as possíveis causas das exceções lançadas pela aplicação a partir de
mensagens bem definidas.
A partir desta premissa, a aplicação PedidoVendaRestAPI terá suas próprias exceções de negócio,
controladas por um provider que irá mapear as exceções e convertê-las em respostas amigáveis aos
clientes da API.
76
Mapeamento de Exceções de Negócio.
O provider padrão para mapeamento de exceções do container de aplicação Java irá converter
qualquer exceção java para um response 500 - Internal Server Error, este tipo de status HTTP deverá ser
retornado ao cliente somente quando um erro desconhecido ou não tratado pelo sistema ocorrer.
As exceções de regras de negócio deverão ser retornadas com o status 400 - Bad Request,
informando ao cliente da API que a requisição foi processada mas uma exceção foi lançada por uma
validação de negócio, ou quando uma chamada for executada em um momento incorreto pelo usuário a
partir do estado do recurso solicitado.
Desta forma, será desenvolvido um provider para mapear as exceções lançadas pela aplicação
originadas por chamadas JAX-RS.
77
Mapeamento de Exceções de Negócio
78
Mapeamento de Exceções de Negócio
Quando uma exceção ocorrer no sistema, independente do tipo, o provider de exceções irá mapear
e converter a exceção e uma mensagem para o cliente, controlando os status de resposta 400, 401 ou
500.
A classe ExceptionDTO será utilizada para representar o JSON de exceções da aplicação para o
cliente da API, conforme a imagem abaixo:
79
Mapeamento de Exceções de Negócio
O provider deverá implementar o método toResponse(E exception), que irá converter a exceção
mapeada pelo provider em um Response HTTP do JAX-RS.
80
Mapeamento de Exceções de Negócio
81
Mapeamento de Exceções de Negócio
82
Mapeamento de Exceções de Negócio
Todas as exceções de validações e regras de negócio deverão ser alteradas para o tipo
BusinessException, neste exemplo, estamos considerando que todas as exceções diferentes de
BusinessException e NotAuthorizedException são exceções inesperadas da aplicação e são classificadas
como erros internos do sistema.
83
Mapeamento de Exceções de Negócio
84
Mapeamento de Exceções de Negócio
Ao requisitar a consulta de um usuário com ID inexistente, a API REST irá retornar para o cliente o
status 400 - Bad Request com a mensagem da exceção lançada pela aplicação.
85
Segurança e Autenticação com JWT (Json Web Token)
Ao tornar uma API REST pública, devemos ter uma preocupação especial em relação a segurança,
onde os recursos expostos na rede estão suscetíveis a usos indevidos, especialmente quando é exposto
informações de domínio privado.
Uma forma de controlar o acesso aos recursos da API, é a utilização de login e senha a partir de um
usuário cadastrado no sistema, onde o login irá retornar um token de acesso ao cliente, liberando os
demais recursos da API REST ao usuário credenciado.
Uma das bibliotecas utilizadas para controles de autenticação em aplicações distribuídas é o JWT
(Json Web Token) a qual possibilita realizar o controle do token de forma robusta e segura compatível
com o padrão Auth0.
86
Segurança e Autenticação com JWT (Json Web Token)
● 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.
● Signature: Assinatura do token, esta informação é gerada com o algoritmo de assinatura definido
no header do token partir de uma chave privada definida pela aplicação, a assinatura é utilizada
para validar o token, garantindo que nenhuma informação do token seja alterada, assegurando a
autenticidade do usuário na API com um token válido.
87
Segurança e Autenticação com JWT (Json Web Token)
88
Segurança e Autenticação com JWT (Json Web Token)
89
Segurança e Autenticação com JWT (Json Web Token)
<dependencies>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
90
Segurança e Autenticação com JWT (Json Web Token)
Após termos o acesso às classes da biblioteca JWT, iremos criar uma classe utilitária chamada
JWTUtil, esta classe irá auxiliar na criação do token no login do usuário para o cliente da API e será
utilizada para validar um token enviado do usuário ao acessar um recurso privado.
91
Segurança e Autenticação com JWT (Json Web Token)
O payload do token JWT é representado por um objeto JSON definido pela aplicação, este objeto
deve conter informações contextuais, metadados e Claims do login efetuado, estas informações são
criptografadas no token para acessá-las posteriormente em um recurso autenticado.
O payload do token não pode conter informações sensíveis, como senhas e dados bancários ou
informações pessoais, estas informações podem ser decodificadas por qualquer cliente JWT, obtendo
acesso a informações privilegiadas do usuário autenticado.
A partir de um token válido enviado pelo cabeçalho da requisição, pode-se obter informações do
usuário logado pelo payload descriptografado para o objeto JSON.
92
Segurança e Autenticação com JWT (Json Web Token)
O payload do token será representado pelo objeto LoginContext, esta classe terá informações sobre
o login efetuado na API, como usuário e data de login, outras informações refente ao contexto de login
poderão ser incluídas conforme a necessidade do desenvolvedor.
93
Segurança e Autenticação com JWT (Json Web Token)
Ao realizar o login, a API REST deverá retornar um JSON com o token válido, este token deverá
mantido e enviado pelo cliente da API para cada requisição a um recurso privado.
O token é representado pelo TokenDTO, que será criado quando o login for efetuado.
94
Segurança e Autenticação com JWT (Json Web Token)
A anotação PermitAll indica que o método será ignorado pelo provider de autenticação, tornando o
método de login público na API REST.
95
Segurança e Autenticação com JWT (Json Web Token)
96
Segurança e Autenticação com JWT (Json Web Token)
Implementação do provider de autenticação, esta classe deverá ser registrada no ApplicationConfig.
97
Segurança e Autenticação com JWT (Json Web Token)
Ao acessar um recurso da API REST sem o token de autenticação, a API irá retornar o status 401 -
Unauthorized.
98
Segurança e Autenticação com JWT (Json Web Token)
Ao realizar o login com um usuário e senha válidos, a API irá retornar o token de acesso aos
recursos privados.
99
Segurança e Autenticação com JWT (Json Web Token)
Para acessar um recurso privado, o token deverá ser adicionado no cabeçalho da requisição API,
com o esquema Authorization: Bearer + “ “ + token.
100
Segurança e Autenticação com JWT (Json Web Token)
Em alguns casos, a regra de negócio necessita saber o usuário que está executando a requisição,
esta informação encontra-se no payload do token enviado pelo cliente da API, o qual poderá ser
convertido de JSON para um objeto LoginContext.
101
Segurança e Autenticação com JWT (Json Web Token)
Cada requisição HTTP está vinculada a uma thread do container, onde a thread nunca possui duas
requisições ao mesmo tempo.
As threads possuem um espaço de memória que pode ser utilizado para armazenamento de
informações para utilização de escopo global ou local.
102
Segurança e Autenticação com JWT (Json Web Token)
Utilizaremos uma classe que fornece variáveis locais de threads do Java chamada ThreadLocal, ao
iniciar uma instância de ThreadLocal na aplicação a mesma estará vinculada a thread em que foi criada.
A instância da ThreadLocal irá guardar em memória de escopo local o contexto do usuário que
executou a requisição HTTP para a API REST, o controle das threads locais é implementado na classe
ContextRequestCache abaixo:
103
Segurança e Autenticação com JWT (Json Web Token)
104
Segurança e Autenticação com JWT (Json Web Token)
105
Customização de Hypermedia JSON (Serialização e Desserialização)
O Provider de serialização e desserialização JSON possui formatações padrões para cada tipo de
dados, em alguns casos, a API REST necessita customizar a formatação de representação dos dados,
como datas, valores e enums.
A biblioteca Jackson é responsável pela conversão de objetos Java para JSON, esta biblioteca já
está como dependência transitiva da biblioteca JWT, portanto não será necessário declará-la
explicitamente no pom.xml.
106
Customização de Hypermedia JSON (Serialização e Desserialização)
A classe ObjectMapperFactory será uma fábrica de ObjectMapper, esta classe terá todas as
configurações da customização do JSON da API REST.
107
Customização de Hypermedia JSON (Serialização e Desserialização)
108
Customização de Hypermedia JSON (Serialização e Desserialização)
Caso o formato da data do JSON for inválido, a conversão irá retornar uma exceção ao cliente da
API.
109
Customização de Hypermedia JSON (Serialização e Desserialização)
A fábrica de ObjectMapper deverá registrar um módulo de customização, este módulo é criado a
partir da classe SimpleModule, adicionando as classes de serialização e desserialização do tipo Date do
Java.
110
Customização de Hypermedia JSON (Serialização e Desserialização)
Após concluir a implementação do ObjectMapper customizado, o mesmo deverá ser registrado para
para o JAX-RS via provider, desta forma, a classe ObjectMapperProvider implementa a classe
ContextResolver do JAX-RS informando que um ObjectMapper customizado deverá ser utilizado para a
serialização e desserialização JSON dos DTOs da API REST.
111
Customização de Hypermedia JSON (Serialização e Desserialização)
Ao consultar um DTO com um atributo do tipo Date, a conversão da data para JSON será realizada
pelo ObjectMapper customizado, conforme a imagem abaixo:
112
Customização de Hypermedia JSON (Serialização e Desserialização)
113
Disponibilizando a API RESTful para clientes Java
Ao disponibilizar uma API para que outras aplicações possam utilizá-la, faz-se necessário o
desenvolvimento de uma documentação da utilização dos recursos da API, para isso pode-se utilizar
algumas ferramentas de documentação de APIs, uma delas é o Swagger, que possui recursos avançados e
completos para a documentação de serviços REST.
Ao disponibilizar uma API desenvolvida em JAX-RS para outro cliente Java EE, é possível
disponibilizar um artefato contendo as interfaces e DTOs para que o cliente da API possa consumir a API
de forma mais objetiva.
114
Disponibilizando a API RESTful para clientes Java
Em Java, existem duas formas de consumir uma API REST, de forma manual utilizando a classe
WebTarget identificada por uma URI de um recurso da rede, esta classe possibilita o consumo de recursos
HTTP utilizando os verbos.
Ao consumir as serviços com WebTarget, o cliente da API deverá realizar as tratativas de conversão
de JSON e XML manualmente para cada requisição ou resposta, tornando o uso da API onerosa.
A outra forma de consumir uma API é a utilização de Client Proxy, onde a API REST disponibiliza as
interfaces dos resources para que o cliente possa criar Proxies, realizando chamadas aos recursos da API
diretamente pelas interfaces da API de forma objetiva e transparente, desenvolvendo diretamente com
os objetos DTOs, sem a necessidade de se preocupar com a serialização e deserialização de objetos e
chamadas manuais com a utilização do WebTarget.
115
Disponibilizando a API RESTful para clientes Java
O exemplo de consumo da API RESTful será demonstrada a partir de uma aplicação Java Web
chamada VendaRapidaWeb, esta aplicação utiliza a tecnologia JSF(Java Server Faces) em conjunto com a
biblioteca Primefaces no desenvolvimento das páginas da aplicação.
A aplicação de exemplo poderá ser baixada do repositório BitBucket deste curso no link
disponibilizado no slide 5.
116
Disponibilizando a API RESTful para clientes Java
Para que possamos gerar o artefato entregável, o nosso projeto será separado por outro projeto
que irá compor as interfaces resources e DTOs.
117
Disponibilizando a API RESTful para clientes Java
Um novo projeto Maven será criado para gerar o artefato com as interfaces e resource e DTOs.
118
Disponibilizando a API RESTful para clientes Java
A opção maven-archetype-quickstart deverá ser selecionada para gerar um novo projeto com o
empacotamento jar.
119
Disponibilizando a API RESTful para clientes Java
O projeto será comum entre todos os projetos envolvidos com a API, desta forma, o nome do
projeto será VendaRapidaRestAPICommon.
120
Disponibilizando a API RESTful para clientes Java
Após criar o novo projeto Maven, o plugin de compilação deverá ser adicionado ao projeto no
pom.xml para que o maven possa compilar e empacotar o artefato com a versão 8 do Java.
<build>
<finalName>VendaRapidaRestAPICommon</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
121
Disponibilizando a API RESTful para clientes Java
A dependência da API do Java EE 8 deverá ser adicionada no pom.xml para que o projeto possa ter
acesso às anotações JAX-RS.
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
122
Disponibilizando a API RESTful para clientes Java
123
Disponibilizando a API RESTful para clientes Java
Assim utilizamos o conceito de API (Application Programming Interface), onde o projeto Web
visualiza as interfaces da API sem ter acesso as implementações da API, conforme o diagrama de
dependências abaixo.
124
Disponibilizando a API RESTful para clientes Java
As dependências são configuradas pelo pom.xml do Maven, onde a tag <dependencies > dos
projetos VendaRapidaRestAPI e VendaRapidaWeb deverão conter a dependência Maven do projeto
VendaRapidaRestAPICommon, assim, ambos os projetos irão visualizar as interfaces e classes do
Common.
<dependencies>
<dependency>
<groupId>com.vendarapida.rest.api</groupId>
<artifactId>VendaRapidaRestAPICommon</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
125
Disponibilizando a API RESTful para clientes Java
126
Disponibilizando a API RESTful para clientes Java
127
Disponibilizando a API RESTful para clientes Java
128
Disponibilizando a API RESTful para clientes Java
129
Disponibilizando a API RESTful para clientes Java
A partir das interfaces resources, o projeto web poderá se comunicar com a API utilizando um
cliente REST Proxy.
Como estamos utilizando o servidor Jboss WildFly para rodar as aplicações, iremos utilizar a
implementação RESTEasy da Jboss para consumir a API.
Para rodar a aplicação com o Glassfish, WebLogic ou Payara a implementação Jersey JAX-RS,
deverá ser utilizada.
130
Disponibilizando a API RESTful para clientes Java
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.6.3.Final</version>
</dependency>
</dependencies>
131
Disponibilizando a API RESTful para clientes Java
A classe ClientRestProxyService será o serviço responsável por criar e configurar o cliente a partir da
implementação RESTEasy, esta classe de serviço será utilizada pelos controllers das páginas JSF para
realizar a comunicação com a API RESTful.
132
Disponibilizando a API RESTful para clientes Java
Ao consumir uma API REST com customizações de Hypermedia, o cliente REST Java também
deverá conter as customizações do server para que a conversão de DTOs possa ser realizada
corretamente.
133
Disponibilizando a API RESTful para clientes Java
Quando uma exceção é lançada pela API o provider ExceptionMapperProvider irá converter a
exceção em uma resposta com o status e mensagem correspondente a exceção lançada pela aplicação.
Para que o cliente REST possa obter as exceções lançadas no servidor, um provider deverá ser
implementado no lado do cliente, mapeando os status de respostas das requisições HTTP,
convertendo-as em exceções quando os códigos 4xx e 5xx retornarem como resposta.
A partir do método filter os dados do Response poderão ser obtidos para implementar os
tratamentos de exceções no cliente da API.
134
Disponibilizando a API RESTful para clientes Java
Classe ClientResponseExceptionProvider que lança as exceções quando o Response for 4xx ou 5xx.
135
Disponibilizando a API RESTful para clientes Java
136
Disponibilizando a API RESTful para clientes Java
A tela de login é gerenciada pela classe FormLoginManager, o botão Entrar executa o método
efetuarLogin(), realizando uma chamada para a API RESTful enviando os dados de login pelo UsuarioDTO.
O token retornado pela API é adicionado em um atributo chamado “token” na sessão web para que
possa ser utilizado posteriormente nas chamadas aos recursos autenticados.
137
Disponibilizando a API RESTful para clientes Java
Após adicionar o token de autenticação da API na sessão web, um provider deverá ser
implementado para interceptar a requisição HTTP e adicionar no Header da requisição o token da sessão
do usuário.
138
Disponibilizando a API RESTful para clientes Java
139
Disponibilizando a API RESTful para clientes Java
A tela de Clientes está implementada no projeto Web para exemplo de utilização da API RESTful
utilizando a comunicação com a API RESTful a partir das interfaces resources disponibilizadas ao cliente
Java EE.
140
Conclusão
A partir dos exemplos demonstrados neste curso, as aplicações em Java EE poderão implementar
APIs RESTful de forma completa e robusta, utilizando todos os recursos e práticas arquiteturais dos
níveis de maturidade REST utilizando os recursos que a especificação JAX-RS disponibiliza.
O projeto Web desenvolvido em Java EE é um exemplo prático da comunicação com uma API REST
desenvolvida com JAX-RS de forma descomplicada, utilizando os recursos de Client Proxy, realizando
chamadas para a API diretamente pelos métodos das interfaces resources.
Devemos prezar pelas boas práticas no desenvolvimento do código, deixando-o mais simples
possível, facilitando na manutenibilidade e entendimento das regras de negócio, uma API bem projetada
e objetiva terá um baixo custo em grandes alterações e manutenções, além de facilitar na utilização da
mesma.
141
Fontes:
143
Fontes:
144