Spring WebFlux: Aplicação Reativa de Ponta a Ponta

Felipe Formentin
Devspoint
Published in
5 min readNov 11, 2021
Stream da natureza :D (fonte: https://flickr.com/photos/91191952@N07/26990734700)

Falamos sobre programação reativa e o quanto ela é eficiente e agora vamos mostrar mais uma funcionalidade que projetos reativos nos oferecem:

Aplicação FrontEnd recebendo stream de dados do BackEnd

Sobre o Projeto

Arquitetura do Projeto

Pensei em qual exemplo eu poderia trazer para mostrar uma aplicação trabalhando com stream de dados e veio à mente montar uma aplicação que fornece os dados históricos do preço de uma BitCoin. Dividi o projeto em 3 aplicações para mostrar diferentes aspectos do processo de streaming. Tudo começa com a App “BitCoin Data History” que é responsável por armazenar e retornar os dados históricos da BitCoin; “BitCoin Data Provider” é uma camada de serviço adicional que eu coloquei para utilizar o WebClient e tem a responsabilidade de trazer os dados do “BitCoin Data History” para o nosso front “VueJs FrontEnd”, que por sua vez recebe os dados via streaming e atualiza dinamicamento o gráfico conforme os dados são consumidos.

BitCoin Data History

Escolhi o MongoDB como BD (banco de dados) da aplicação por causa da facilidade de trabalhar com ele e por ele possuir um driver reativo (spring-boot-starter-data-mongodb-reactive), lembrando que caso você possua uma aplicação utilizando o modelo reativo mas possui conexão com o BD que não utiliza um driver reativo vale a pena pesquisar e testar para ver se a performance/eficiência vale a pena.

Código responsável pela busca do histórico

E com esse snippet de código nós conseguimos recuperar todos os dados armazenados no BD, ordenados pelo campo “order”, e também pedi para que esperássemos 100 milissegundos entre a emissão de cada elemento emitido no fluxo de dados. Retornando um Flux<BitCoinHistoryEntity> no meu Controller, eu consigo obter o seguinte resultado ao chamar a API no meu navegador:

Stream de dados sendo consumidos pelo navegador

BitCoin Data Provider

Nessa App utilizei uma implementação básica do WebClient (responsável por realizar requisições HTTP) que vêm com o módulo WebFlux. O WebClient trabalha de maneira non-blocking para suportar o modelo reativo da aplicação, mas também é capaz de realizar chamadas bloqueantes quando necessário.

Simples configuração do WebClient
Realizando uma chamada HTTP para a API do BitCoin Data History

Como ele possui uma API fluente, fica fácil de entender o passo a passo do que está acontecendo. Primeiro uso o método get(), que é o método HTTP, depois passamos qual a uri que complementa a nossa baseUrl, utilizo o método retrieve() para disparar a requisição e peço que o body do retorno seja convertido em Flux, tendo um retorno de Flux<BitCoinHistory>.

Utilizando o wrapper ServerResponse para realizar o streaming dos dados

A chave para retornar o conteúdo em “pacotes” está no trecho contentType(MediaType.TEXT_EVENT_STREAM) onde definimos o protocolo da nossa resposta como text/event-stream, fazendo com que o consumidor dessa API receba a cada +/- 100 milisegundos uma nova informação, como mostrado no GIF anterior.

BitCoin FrontEnd

Para o framework do app frontend escolhi o VueJS para aproveitar e conhecer um pouco mais sobre ele já que estava no meu radar faz um tempo, e também vi que possuía um componente de gráficos real-time.

Minha primeira dúvida foi em como consumir os dados da stream de forma dinâmica e me baseei bastante nessa documentação. Com certeza existem implementações mais fáceis de ler, mas pela falta de experiência com JS acabei fazendo dessa forma:

Código responsável por receber dados da stream

É configurado um leitor que fica consumindo os dados da stream e para cada callback converto o pacote de dados recebido para JSON e armazeno eles em um objeto (bitcoinData) que é responsável por ir atualizando as informações do gráfico, nos trazendo o efeito mostrado no começo do artigo:

Aplicação FrontEnd recebendo stream de dados do BackEnd

Como Executar

Caso você queira testar na sua máquina, pode baixar os repositórios anotados no rodapé e subir as aplicações “BitCoin Data History” que está na porta 8082 e a “BitCoin Data Provider” que está na porta 8081, e executar o endpoint GET “http://localhost:8081/bitcoin/history “. Como o “BitCoin Data History” já possui um MongoDB embedded, não precisa configurar uma instância de Mongo. Para subir o FrontEnd podemos executar o comando “npm run serve” e acessar pela porta 8080.

Conclusão

De forma resumida quis apresentar um pouco do que é possível realizar com streaming de dados entre diferentes aplicações sem ter que escrever muito código uma vez que os frameworks estão realizando a maior parte do trabalho por nós. O conceito de streaming é longe de ser algo novo, e vemos isso em diversos modelos de negócio, como por exemplo quando você está assistindo alguma série no Netflix ou vendo uma Stream no Twitch. Existem várias formas na qual podemos utilizar esse conceito, e aproveitei pra mostrar como o Spring WebFlux nos traz isso.

Repositórios dos Projetos:

Referências:

--

--