Alura > Cursos de Programação > Cursos de Kotlin > Conteúdos de Kotlin > Primeiras aulas do curso Kotlin: aplicações resilientes e assíncronas

Kotlin: aplicações resilientes e assíncronas

Retrofit - Apresentação

Boas-vindas ao curso de Kotlin: criando aplicações resilientes e assíncronas!

João: Olá! Me chamo João Victor, sou desenvolvedor Java e Kotlin. Tenho desenvolvido trabalhos aqui na Alura sobre essa linguagem.

Paulo: Me chamo Paulo Silveira, sou CEO da Alura. Uma honra estar apresentando este curso com o João.

João Victor é uma pessoa de pele clara, olhos escuros e cabelos pretos curtos, usa bigode e cavanhaque. Veste uma camiseta azul marinho com o texto "Alura", em branco. Está sentado em uma cadeira preta e, ao fundo, há uma cortina preta do lado esquerdo e do lado direito uma estante com algumas plantas e decorações.

Paulo Silveira é uma pessoa de pele clara, olhos escuros e cabelos castanhos escuros. Usa bigode e cavanhaque, e um óculos preto. Veste uma blusa de frio preta lisa, e está sentado. Ao fundo, há uma parede azul clara na parte superior e amarela na parte mais inferior.

Paulo: Essa é uma formação que estamos abordando todos os problemas em Kotlin, com um projeto grande que envolve várias tecnologias.

Neste primeiro curso, vamos ter um enorme desafio. Isso porque, no cotidiano, trabalhamos com várias tecnologias assíncronas. Por isso, em um primeiro momento, usaremos o Retrofit para consumir o web services.

Pode até ser um web service que nós mesmos criamos, mas também pode ser um que você queira usar pronto.

Em seguida, vamos entender melhor sobre mecanismos de trabalho assíncrono, porque seja no front-end ou back-end é necessário entender essas chamadas assíncronas.

Até com rotinas, algumas pessoas se limitam a copiar e colar, usando recursos de Kotlin mais avançados para chegar em testes. Tudo isso com um projeto já iniciado em Spring. Isso torna o cenário bastante real, não é, João?

João: Sim, torna o cenário bem parecido com um corporativo. Toda essa parte de testes atualmente é um ponto fundamental para se ter um código com qualidade para ter garantia de que está funcionando. Assim, é possível verificar isso através de testes.

Sobre os mecanismos de trabalhos assíncronos, atualmente é impossível, em grandes projetos, usar requisições síncronas. Desse modo, sempre tentamos trabalhar com as requisições assíncronas.

Paulo: Às vezes acho que até nos pequenos projetos, em alguns casos as pessoas acabam não sabendo o motivo de ter feito daquela forma, como o motivo de usar promise do JavaScript ou callbacks do Kotlin.

Mas precisamos ter esse conhecimento e acredito que ficou muito legal este curso. Isso porque será útil e prático, porque vamos consumir web services, endpoints e APIs e fazemos isso o tempo todo em cenários reais.

Faremos tudo isso usando estruturas que muitas pessoas estão trabalhando a um certo tempo, como Kotlin e Spring, e ainda não dominam tudo sobre essas ferramentas.

Acredito que seja uma oportunidade para mostrar que estamos evoluindo nesse ecossistema de Kotlin, de back-end, de assíncrono e abraçando cada vez mais essa comunidade com a ajuda do João Victor.

João: As ferramentas que abordaremos ao longo deste curso, são tecnologias usadas no mercado. Caso você seja contratado por uma grande empresa e esteja trabalhando com Kotlin, muito provavelmente verá essas mesmas tecnologias que falaremos neste curso na empresa.

Para quem quer seguir a carreira em Kotlin, recomendo que conclua esse curso. Aprenderemos sobre o* Retrofit* para aplicá-lo à chamada HTTP de uma grande empresa. Os testes com Kotest também são utilizados pelas empresas para testes de unidade.

Assim como o Coroutines, que atualmente vem ganhando espaço no mercado com as questões de threads virtuais. Inclusive, o Java está trazendo isso como recurso para ele também.

Temos uma biblioteca nativa completa para chamadas síncronas com Kotlin. Este é um curso bem interessante, voltado para o mercado e recomendado para quem deseja trabalhar com Kotlin.

Paulo: Preste atenção, temos muitos links nas tarefas do curso, com o código base, para o boilerplate ("chapa de ebulição"). Nesse caso, podemos nos limitar a copiar e colar.

Principalmente nessa primeira aula, em que estarei junto com o João, vou fazer diversos questionamentos para irmos linha por linha dos códigos, mesmo que seja um código que não será usado muitas vezes, para entendermos com profundidade o que está acontecendo, já que teremos bastante código envolvendo esse projeto em Spring.

Boa aula!

Retrofit - Overview do Retrofit

Paulo: João Victor, acho que um cenário clássico quando trabalhamos com linguagem do back-end e também com mobile, é consumir muitos serviços. Acredito que seja uma realidade no cenário de arquitetura.

Em alguns momentos, sequer sabemos que estamos consumindo serviços, mas estamos chamando uma API que consome um serviço por trás, por exemplo. Logo, é um ponto que precisamos saber para aplicar no cotidiano.

O Retrofit aplica isso com muita facilidade, porque existe a API nas bibliotecas padrão do Java e do Android, para trabalhar com requisição HTTP. Mas elas costumam ser de baixo nível e é necessário escrever bastante código para executar um método get ou post.

O nosso objetivo é trabalhar com Kotlin e Retrofit para facilitar esse processo, João?

João: Exatamente.

Como você bem mencionou, atualmente temos diversas formas de fazer esse tipo de requisição. Principalmente porque hoje trabalhamos com arquiteturas de microsserviços, em que um microsserviço chama outros. Precisamos sempre trabalhar com esse tipo de requisição.

Assim, temos desde bibliotecas que fornecem isso de uma forma mais simples, e outras que o fazem de maneira mais complexa. Esta última, sempre exige que escrevamos mais código.

No desenvolvimento de software, a ideia é focar nas regras de negócio e menos em detalhes de implementação. Logo, o Retrofit chega exatamente com essa abordagem: com a biblioteca conseguimos inserir essa dependência e, com isso, diminuir a quantidade de código manual. Podemos somente incluir as configurações necessárias para conseguir consumir um serviço.

Esse é o principal objetivo do Retrofit: simplificar o código.

Paulo: João, tenho certeza que você preparou o web service que vamos consumir.

Navegando na documentação do Retrofit, li que o exemplo principal é a API padrão do GitHub. Essa API lista os repositórios de uma pessoa, analisa os amigos que estamos deixando de seguir, quem começa a nos seguir, as estáticas, e mais. Estamos mais acostumados a trabalhar com isso, que facilita a leitura da documentação da API.

Neste curso, podemos escolher a API que desejarmos consumir e gerar o código de forma automática. Cada um pode escolher o seu, mas acredito que você, João, tenha um problema para analisarmos nessa formação avançada de Kotlin.

Qual é esse problema que teremos que desenvolver ao longo deste treinamento?

João: A pessoa pode usar a sua API, mas eu trouxe um exemplo que vamos pesquisar sobre carros em estoque que serão inseridos na aplicação. Eles não serão inseridos via banco de dados, mas sim no contexto da nossa aplicação.

Deste modo, faremos uma requisição para esse microsserviço que pode retornar, por exemplo, se determinado modelo de carro está disponível em estoque. Trabalharemos dessa forma para dar o contexto da nossa aplicação e ao acrescentarmos novos recursos.

Mas nada impede de adicionar outro contexto ou criar outra aplicação, com outro contexto, e consumir a API do GitHub, por exemplo.

No Retrofit, precisamos apenas mapear os campos desejados que estarão na API pública. Queremos trazê-los para a nossa aplicação. Criamos um objeto sem muitos problemas para trazer essas informações para dentro da nossa aplicação.

Paulo: Pelo que entendi, vamos trabalhar com anotações, seja em Kotlin ou Java. Assim, conseguimos configurar de uma maneira fácil, mesmo em casos específicos?

Porque imagino que usar um método get para listar todos os carros disponíveis, deve ser simples com uma anotação que prepara um método para nós.

Porém, e se tivermos uma configuração, uma classe ou objeto mais complexo, como uma data com timestamp ou, até mesmo, ter que passar uma chave privada para exibir o token para ser autenticado para entrar na API.

Nesses casos que aparecem bastante, o Retrofit nos dá essas possibilidades?

João: Sim, e sem o uso de anotações!

No Retrofit não precisamos usar anotações, conseguimos montar uma classe de configuração da sua aplicação.

Por exemplo, sobre o token, conseguimos abrir um interceptor na classe de configuração, em que passamos para ele que ao fazer a requisição para determinada API, é necessário passar um token específico. Isso de forma declarativa no código.

Atualmente, há quem prefira ler no código o que está sendo executado. Logo, é usado o interceptor e inserido o token, e, ao realizar a requisição, o Retrofit consegue injetar todas essas informações necessárias para chamar a API e a requisição é feita com sucesso.

Paulo: É uma abordagem diferente, porque outros frameworks priorizam um monte de anotações. Com isso, ficamos com as classes com dez anotações para explicar como converter, como passar token, e assim por diante.

É uma vantagem diminuir o código. Eu vi alguns exemplos nos vídeos e me perguntei "Como ele sabe qual é o user?". Alguém escreveu o interceptor ou o objeto é tão óbvio do JSON para o objeto, que ele faz sozinho.

João: Era esse o principal problema: tínhamos muitas anotações. Por exemplo, na classe tinha dez anotações e, por mais que elas sejam práticas por trazer menos código escrito, gera um pouco de dúvida.

Isso porque não sabemos muito bem o que o código está executando. Caso seja necessário debugar, como seria feito? Logo, o uso de anotações acabou ficando complexo por isso.

Programação declarativa: escreve o suficiente.

Agora, vamos mais para a programação declarativa, em que escrevemos o suficiente para entender o que o código está executando e debugar.

Assim, o Retrofit é isso: criamos uma interface e quando for necessário, o Retrofit vai implementar essa chamada HTTP.

O Retrofit por trás, com as suas classes de configuração, vai saber que ao fazer aquela chamada para o web service ou API externa, ele vai implementar, em tempo de execução, aquela interface e trazer as informações.

Do nosso lado, precisamos ter um mapeamento dos campos que chegam da API, se não o JSON não consegue realizar o parse. Ele precisa saber que determinado objeto é o objeto que está vindo da API.

É essa abordagem que o Retrofit traz: poucas anotações de forma declarativa que nos permite debugar e conseguir visualizar o que o código está executando.

Paulo: Independente de trabalhar com smartphones ou no back-end com Spring e Kotlin, este curso é importante para entendermos como consumimos* APIs*.

Para aprendermos, também, essas vantagens do Retrofit, e encaixá-las no nosso projeto.

Vamos para a parte do código.

Espero vocês na próxima aula!

Retrofit - Consumindo uma API

Repositório no GitHub do Projeto Inicial

Paulo: Agora que o João está com um notebook, vamos conseguir analisar essa API de carros em estoque que ele preparou para nós trabalharmos ao longo deste curso.

Falando um pouco sobre o Postman, tem bastante artigo e cursos sobre essa ferramenta para explorarmos as APIs aqui na plataforma da Alura.

O Postman é mais prático do que ir à linha de comando e executar os comandos para enviar solicitações HTTP. É no Postman que acessaremos a *API *que você preparou, João?

João: Para o nosso contexto, trouxe uma aplicação em que teremos alguns carros para alugar, mas dessa aplicação precisamos consumir uma API.

A API é essa que está na tela do Postman. Se formos ver o cars-inventory, é onde teremos como buscar por modelo. Se começarmos buscando no Postman, que atualmente é a* IDE* de requisição HTTP mais usada, faremos uma requisição para essa API para nós analisarmos o retorno.

Estamos com o Postman aberto com o método get e o seguinte endereço:

http://ec2-18-215-156-13.compute-1.amazonaws.com:8080/cars-inventory?model=go

Abaixo, estamos na aba "Params" ("Parâmetros") em que temos uma tabela com uma coluna "key" com um valor "model", uma coluna "value" com "gol" e uma coluna chamada "description" vazia.

Por exemplo, no Postman, clicaremos no botão azul "Send", do lado direito do endereço para visualizarmos o que há no estoque. Note que abaixo, em "Body > Pretty", nos retornou:

[
    {
    "id": 158,
    "make": "VW",
    "model": "Gol",
    "year": 2008,
    "fuelType": "Gas"
    },

//retorno omitido

Paulo: Já enviamos um ?model=go, logo pela carry string já é possível indicar que essa API funciona mais ou menos assim.

Mas é assim que funciona no cotidiano: recebemos uma API com uma documentação, se vier. Majoritariamente recebemos o exemplo e precisamos investigar o que enviar de requisição e qual o retorno.

Esse endereço poderia ser acessado pelo navegador, João?

João: Sim! Quando estamos nos referindo a uma requisição get, podemos acessar via browser. Porém, acredito que o Postman seja mais interativo para fazermos isso.

Por exemplo, você mencionou que estamos usando um query params ("parâmetros de consulta"), em que inserimos uma interrogação e tudo que colocamos depois dela, no caso model, podemos mudar o valor: ?model=go.

Note que no caso é o modelo é "Gol", mas podemos alterar para outro modelo de carro.

Perceba que abaixo do endereço, na aba "Params", ele nos retorna na coluna "Value" o modelo gol. O Postman nos traz essa facilidade, ao invés de trocarmos pela query conseguimos pelo value (valor).

Podemos dar um duplo clique em "gol" e digitar "ferrari". Note que, na URL, agora, temos:

http://ec2-18-215-156-13.compute-1.amazonaws.com:8080/cars-inventory?model=ferrari

Ao clicarmos novamente no botão "Send", o retorno é somente []. Isso significa que não temos na nossa API nenhum carro do modelo Ferrari.

Isso é significativo, dado que, ao trabalharmos com parâmetros e buscarmos por algum que não temos em estoque, nos retorna vazio e não uma exceção. Foi feita uma requisição com sucesso, com o status: 200 OK, mas que nos devolve um valor vazio, o que não é um erro.

Paulo: Muitas vezes retornar vazio não significa um erro. Há muitas APIs que até fazem sentido isso, inclusive, nesse caso de buscar em estoque por determinado modelo de carro.

João: Pode ser que depois de um tempo, em um cenário de expansão da empresa, tenha um modelo de carro da Ferrari. É uma forma flexível de aplicar, pois permite que a aplicação retorne caso tenha esse modelo.

Por exemplo, podemos alterar novamente para "gol" na URL:

http://ec2-18-215-156-13.compute-1.amazonaws.com:8080/cars-inventory?model=go

Em seguida, clicamos no botão "Send" mais uma vez.

[
    {
    "id": 1757,
    "make": "VW",
    "model": "Gol",
    "year": 2008,
    "fuelType": "Gas"
    },
    {
    "id": 557,
    "make": "VW",
    "model": "Gol",
    "year": 2017,
    "fuelType": "Gas"
    }
[

Assim, temos as informações desse carro, como o ID, a marca, o modelo, o ano e o tipo do combustível.

Paulo: Há mais de um carro do modelo gol no estoque?

João: Isso, há mais de um modelo gol no estoque.

Podemos procurar por outro modelo, por exemplo, o Cruze: ?model=cruze. Após alterar na URL, clicamos no botão "Send" novamente, para visualizarmos as opções em estoque do modelo Cruze.

[
    {
    "id": 1146,
    "make": "GM",
    "model": "Cruze",
    "year": 2014,
    "fuelType": "Gas"
    }
]

Nesse caso temos somente um carro. Isso quer dizer que se for alugado, será retirado do estoque e não teremos mais carros desse modelo.

Essa é a ideia de consumir essa API, passando os parâmetros para pesquisar pelos carros que desejo alugar. Vamos supor que somos o cliente e queremos alugar um carro do modelo Cruze, ao visualizarmos haver esse modelo no estoque, alugamos o carro.

É essa a ideia da API de trazer quais modelos temos disponíveis no estoque.

Paulo: Cada vez que digitarmos um modelo, estamos acessando o endpoint (um dos pontos da API)?

Essas palavras confundem e tratamos tudo como sinônimo: web service, API e endpoint, mas cada um possui um significado específico.

Enfim, o endpoint é um dos pontos do nosso serviço de aluguel de carros. Estamos acessando esse modelo Cruze passando os parâmetros necessários.

Inclusive, se clicarmos na aba "Raw", conseguimos visualizar o que a requisição HTTP retornou.

[{"id":1146,"make":"GM","model":"Cruze","year":2014,"fuelType":"Gas"}]

João: Isso mesmo.

Paulo: Note que devolveu todos os campos na mesma linha. Em algum lugar do Postman também conseguimos visualizar o body ("corpo"), no menu superior após a aba "Headers".

Body

none: marcado

Não era isso que eu queria no retorno, queria visualizar o* body completo, com o *response ("resposta") e outras informações. Conseguimos visualizar essas informações no Postman?

João: Nesse caso, no body, vamos visualizar mais quando queremos enviar a requisição.

Paulo: Aquele body era para fazer a requisição, certo?

João: Isso mesmo.

Para visualizarmos a informação completa, vamos clicar na aba "Headers" no menu mais abaixo, não no "Headers" abaixo da URL.

Headers:

KEYVALUE
Content-Typeapplication/json
Transfer-Encodingchunked
DateThu, 29 Sep 2022 17:02:54 GMT
Keep-Alivetimeout=60
Connectionkeep-alive

Paulo: Perfeito.

João: Na aba "Headers" conseguimos visualizar o tipo do conteúdo, o content type. É comum nesses endpoints que ao consumirmos alguns serviços, retorne no formato JSON. É possível retornar outro formato, porém, o normal é o JSON e é o que a nossa API está devolvendo.

Perceba que do lado superior direito da aba "Headers", temos o status 200 OK. Isso é um ponto legal do Postman, se colocarmos o mouse sobre "Status: 200 OK", aparece uma mensagem explicando o que significa esse status.

Muitas pessoas que estão começando não conhecem ainda o que significa o status 200 OK. Se fizermos uma requisição da API pelo navegador, teremos o mesmo resultado do endpoint retornando um payload. Mas e o 200 OK?

Na mensagem informa que é um retorno de sucesso para requisições HTTP.

Vamos forçar um erro para analisarmos juntos. No endereço, removeremos a parte do parâmetro, ?model=cruze, e clicaremos no botão "Send", do lado direito.

Repare que agora o status está como 400 Request, na cor verde. Isso significa que faltou informação, não conseguimos acessar a API sem nenhum parâmetro no endereço.

Caso desejarmos saber o que é esse status, basta colocar o mouse por cima de "Status: 400 Request". Será exibida a seguinte mensagem:

400 Bad Request: The request cannot be fulfilled due to bad syntax ("A solicitação não pode ser atendida devido à sintaxe incorreta").

Desse modo, conseguimos identificar o motivo do problema.

Paulo: Perfeito.

Isso nós descobrimos, em muitos casos, na documentação ou vamos testando para analisar no próprio Postman. O JSON é flexível, mas também é um pouco trabalhoso por termos que realizar alguns testes para verificar se determinado parâmetro é obrigatório ou não, etc.

Essa palavra "payload" que você mencionou, é a parte do body (sem os headers) que chega no formato JSON?

João: Exatamente.

Para visualizarmos esse payload, vamos voltar com o endereço com o modelo "gOL", clicar no botão "Send" e depois na aba "Body", mais abaixo.

[
    {
    "id": 25,
    "make": "VW",
    "model": "Gol",
    "year": 2008,
    "fuelType": "Gas"
    },
    {
    "id": 840,
    "make": "VW",
    "model": "Gol",
    "year": 2017,
    "fuelType": "Gas"
    }
[

O retorno da API é esse payload.

Têm pessoas que chamam de payload, outras de body ou resultado/retorno da API. Todos esses termos se referem a mesma coisa: os campos que mostram as informações mais necessárias do endpoint que estamos chamando.

Paulo: Agora, para pegarmos isso no código Java e Kotlin, usaremos o Retrofit porque é uma biblioteca muito usada. Assim como é comum em JavaScript as pessoas usarem a fetch API, padrão nos navegadores.

Mas para várias plataformas existem várias bibliotecas. De novo, caso você prefira usar outra plataforma, fique à vontade.

Este treinamento é legal porque, independente de utilizar o Retrofit ou não, apesar de aconselharmos, fica o conhecimento sobre consumo e uso de serviços, de payloads, dos headers e a transformação do JSON. Correto?

João: Isso mesmo.

Nós recomendamos o uso do Retrofit, mas nada impede você de usar outras plataformas para realizar este treinamento.

Paulo: Vamos configurar o Retrofit no projeto Kotlin para consumir esse serviço?

João: Vamos, sim, na próxima aula.

Te espero lá!

Sobre o curso Kotlin: aplicações resilientes e assíncronas

O curso Kotlin: aplicações resilientes e assíncronas possui 148 minutos de vídeos, em um total de 38 atividades. Gostou? Conheça nossos outros cursos de Kotlin em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Kotlin acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas