Você meu caro desenvolvedor, já pegou uma demanda onde precisa efetuar uma chamada ao backend porém já sabe com antecedência que essa requisição pode demorar muito, o que fazer nesse caso?
Fazer a chamada normalmente, colocar um “loading” na tela do cliente e deixar lá até que aconteça a resposta do servidor e mostrar o resultado? Não é uma boa alternativa pois diversos problemas podem acontecer no intervalo entre a chamada da API e seu retorno.
Uma solução é o cliente simplesmente avisar o backend que precisa efetuar um processamento e quando esse processamento estiver pronto ser avisado que está ok. Ou seja o cliente pode fazer uma requisição simples receber um 202 (solicitação aceita) e depois receber um status que o processamento solicitado está finalizado? um bom cenário hein.
Existem algumas formas de fazer esse processo, uma forma comum encontrada no mercado é o HTTP Polling uma técnica que a grosso modo força o client a ficar “batendo” no backend a todo momento para verificar se o processamento foi efetuado.
O padrão async-request-reply é uma forma “mais bonita” de utilizar o http polling, vou no futuro escrever sobre ele aqui no blog.
Temos também como alternativa trabalhar com WebSockets que é um protocolo de comunicação bidirecional, full-duplex, que permite a comunicação em tempo real entre um navegador da web (cliente) e um servidor da web.
E ainda temos outra opção que é o Server Sent Events (SSE) principal ator deste artigo.
Navegue pelo conteúdo deste artigo
Definição de SSE
Server Sent Events (SSE) é uma tecnologia de comunicação de dados que permite que um servidor envie atualizações assíncronas para um cliente web em tempo real, sem que o cliente precise solicitar essas atualizações constantemente. Ele funciona através da criação de uma conexão persistente entre o cliente e o servidor, permitindo que o servidor envie dados ao cliente sempre que houver atualizações disponíveis.
SSEs são baseados em um protocolo HTTP e usam eventos de fluxo para enviar dados do servidor ao cliente. Os dados são enviados em um formato de texto simples (por exemplo, JSON, XML ou CSV) e o cliente pode interpretar esses dados e atualizar dinamicamente a página sem a necessidade de atualização completa da página.
Vantagens em utilizar o SSE
- Comunicação em tempo real: permitem a comunicação em tempo real entre o servidor e o cliente, tornando possível atualizar informações em uma página web sem a necessidade de recarregar a página ou enviar solicitações repetidas ao servidor.
- Redução de carga no servidor: são unidirecionais, ou seja, somente o servidor envia informações para o cliente. Isso significa que não há necessidade de o cliente enviar solicitações repetidas ao servidor, reduzindo assim a carga do servidor. Diferente do websocket que é bidirecional.
- Fácil implementação: é fácil de implementar, pois é baseado em um protocolo HTTP simples e não requer nenhuma biblioteca ou ferramenta de terceiros para funcionar.
- Suporte a diversos navegadores: é suportado pela maioria dos navegadores modernos, incluindo Chrome, Firefox, Safari e Edge
- Conexões persistentes: permitem que a conexão entre o cliente e o servidor seja mantida aberta, permitindo a transmissão contínua de dados do servidor para o cliente.
Cénário proposto para nosso estudo
Vamos imaginar para exemplificar o uso de SSE que temos uma situação onde precisamos gerar um relatório porém esse relatório tem um processamento bem alto e pode demorar até alguns minutos para ser gerado. A principio fizemos a chamada a API de backend e simplesmente colocamos um “loading” para que o usuário espere a finalização e veja o seu relatório.

Vamos pensar nos problemas dessa abordagem:
- Tempo de espera prolongado;
- Bloqueio da thread do cliente, ou seja o cliente não poderá fazer mais nada enquanto aguarda a resposta da API;
- Consumo excessivo de recursos;
- Falhas de integração;
- Problemas de escalabilidade;
- Problemas de conexão;
- Problemas de rede…
Emfim podemos ter vários problemas nesta abordagem. Vamos implementar agora pensando em SSE:

Explicando a imagem:
- Passo 1 – o front abre um canal de comunicação se registrando na api de SSE para ser avisado quando o processamento for finalizado
- Passo 2 – o front solicita o processamento do relatório na API de relatório e pode receber aqui um HTTP 202 (Accepted) por exemplo liberando o usuário para fazer outras coisas no site enquanto seu relatório não fica pronto;
- Passo 3 – a API do relatório notifica a API de SSE que o relatorio está finalizado;
- Passo 4 – O front recebe notificação no canal aberto via SSE que o report está finalizado;
- Passo 5 – O front pode agora recuperar os dados do report processado, sem se preocupar em tempo de processamento, muito mais rápido.
Com o cenário definido vamos ao código
Basicamente teremos uma API feita usando o Spring Boot com o seguinte código:

Essa API está configurada para rodar na porta 6033, o importante nesse código é a classe SseEmitter que é disponibilizada pelo Spring. Minha idéia aqui não é explicar linha por linha de código e sim tentar montar a idéia do SSE.
Vamos agora criar uma página HTML muito simples, aqui o importante é saber que o SSE é uma feature do HTML5 portanto deve funcionar com qualquer tecnologia de front (Angular, React, Vue, ou no nosso caso HTML puro com JQUERY) não tenho certeza se todos os browsers aceitam essa feature, antes de implementar tenha certeza disso ok?

Informações sobre a página html:
- A primeira coisa que será feita ao subir a página é fazer a subscrição na API do SSE, essa configuração está na linha 48 onde definimos o endpoint da API do SSE e na linha 49 onde definimos o eventSource;
- temos dois “listeners” ou seja eventos que ficarão “ouvindo”, um para o caso de erro na linha 61 e o evento que ficará ouvindo uma notificação do server na linha 55
- Na linha 69 temos o evento de click de um botão, aqui por exemplo poderia ser chamada a API de geração do relatorio (Não implementei isso por não fazer parte do escopo desse artigo) trata-se apenas de uma simulação
Depois de subir a API Spring Boot, vamos chamar a página em um browser:

Note que na aba “Network” da ferramenta do desenvolvedor temos uma chamada ao endpoint “subscribe” e que foi aberto um canal “EventStream” ou seja agora temos um canal de comunicação direta com o server onde somente o server pode enviar notificações ao client.
Vamos clicar agora no botão “Gerar” para simular a requisição ao backend para geração do relatório:

Agora para simular a api do relatório vamos criar uma chamada ao endpoint dispatchEvent da API de SSE via Postman informando que o processamento terminou e que ele pode visualizar o relatório em uma URL definida;

Note que estou enviando uma notificação já com uma url para que o cliente possa ver o relatório: “Seu relatório está pronto! <a href=”report.html”>clique aqui</a> para acessa-lo”.
Essa página report.html está no mesmo nível da index.html (somente para demonstração):

Quando enviar o request pelo Postman devemos ter a seguinte saida:

Olha que bacana, avisamos o front que o processamento foi finalizado e ainda conseguimos enviar pra ele a URL que deve encaminhar o cliente para a visualização do relatório.

Neste momento temos ainda um problema pois todos os clients que estiverem “inscritos” no canal irão receber a mesma mensagem, em um próximo artigo vamos ver como enviar notificações para um determinado cliente e fechamos esse problema.
Por enquanto é isso, espero ter ajudado, dúvidas, comentários positivos ou negativos, opiniões e etc estou aqui para ouvir!
Até o próximo artigo!