---
title: Processando mensagens com Spring Cloud Stream e Kafka
description: Djan Castro explica o que vem a seguir na indústria automobilística nesta edição especial de Leaders in Studio.
image: https://blog.avenuecode.com/hubfs/joanna-kosinska-uGcDWKN91Fs-unsplash-2.jpg
---

[Avenuecode.com](https://avenuecode.com.br) [Notícias](https://avenuecode.com.br/news) [Contato](https://avenuecode.com.br/contact)

[![Avenue Code Snippets Logo](https://blog.avenuecode.com/hubfs/Images/Blog/LogoAvenueCodeSnippets.png?t=1486469863776)](https://blog.avenuecode.com/pt) [*menu*](https://blog.avenuecode.com/pt)

- Tecnologias
  
  [Nuvem e DevOps](https://blog.avenuecode.com/blog/pt/topic/cloud_and_devops_pt?hsLang=pt) [Delivery Infrastructure](https://blog.avenuecode.com/blog/pt/topic/delivery_infrastructure_pt?hsLang=pt) [Web Experience](https://blog.avenuecode.com/blog/pt/topic/web_experience_pt?hsLang=pt) [Metodologias ágeis](https://blog.avenuecode.com/blog/pt/topic/agile_mindset_pt?hsLang=pt) [Quality Assurance](https://blog.avenuecode.com/blog/pt/topic/quality_assurance_pt?hsLang=pt) [Integrações](https://blog.avenuecode.com/blog/pt/topic/integration_pt?hsLang=pt)
  
  [Design e UX](https://blog.avenuecode.com/blog/pt/topic/design_and_ux_pt?hsLang=pt) [Arquitetura de Soluções](https://blog.avenuecode.com/blog/pt/topic/solution_architecture_pt?hsLang=pt) [Data e Machine Learning](https://blog.avenuecode.com/blog/pt/topic/data_and_machine_learning_pt?hsLang=pt) [Mobile Experience](https://blog.avenuecode.com/blog/pt/topic/mobile_experience_pt?hsLang=pt) [Microsserviços](https://blog.avenuecode.com/blog/pt/topic/microservices_pt?hsLang=pt)
- [Whitepapers](https://blog.avenuecode.com/blog/pt/topic/whitepapers_pt?hsLang=pt)
- [Spotlight](https://blog.avenuecode.com/blog/pt/topic/spotlight_pt?hsLang=pt)
- [Extraordinary Women in Tech](https://blog.avenuecode.com/blog/pt/topic/extraordinary_women_in_tech_pt?hsLang=pt)
- [Cultura Avenue Code](https://blog.avenuecode.com/blog/pt/topic/avenue_code_culture_pt?hsLang=pt)

- [Nuvem e DevOps](https://blog.avenuecode.com/blog/pt/topic/cloud_and_devops_pt?hsLang=pt)
- [Design e UX](https://blog.avenuecode.com/blog/pt/topic/design_and_ux_pt?hsLang=pt)
- [Delivery Infrastructure](https://blog.avenuecode.com/blog/pt/topic/delivery_infrastructure_pt?hsLang=pt)
- [Arquitetura de Soluções](https://blog.avenuecode.com/blog/pt/topic/solution_architecture_pt?hsLang=pt)
- [Web Experience](https://blog.avenuecode.com/blog/pt/topic/web_experience_pt?hsLang=pt)
- [Data e Machine Learning](https://blog.avenuecode.com/blog/pt/topic/data_and_machine_learning_pt?hsLang=pt)
- [Metodologias Ágeis](https://blog.avenuecode.com/blog/pt/topic/agile_mindset_pt?hsLang=pt)
- [Mobile Experience](https://blog.avenuecode.com/blog/pt/topic/mobile_experience_pt?hsLang=pt)
- [Microsserviços](https://blog.avenuecode.com/blog/pt/topic/microservices_pt?hsLang=pt)
- [Quality Assurance](https://blog.avenuecode.com/blog/pt/topic/quality_assurance_pt?hsLang=pt)
- [Integrações](https://blog.avenuecode.com/blog/pt/topic/integration_pt?hsLang=pt)
- [Whitepapers](https://blog.avenuecode.com/blog/pt/topic/whitepapers_pt?hsLang=pt)
- [Spotlight](https://blog.avenuecode.com/blog/pt/topic/spotlight_pt?hsLang=pt)
- [Extraordinary Women in Tech](https://blog.avenuecode.com/blog/pt/topic/extraordinary_women_in_tech_pt?hsLang=pt)
- [Cultura Avenue Code](https://blog.avenuecode.com/blog/pt/topic/avenue_code_culture_pt?hsLang=pt)

# [Processando mensagens com Spring Cloud Stream e Kafka](https://blog.avenuecode.com/pt/processando-mensagens-com-spring-cloud-stream-e-kafka)

- [Tweet](https://twitter.com/share)

*perm\_identity* [Henrique Schmidt](https://blog.avenuecode.com/pt/processando-mensagens-com-spring-cloud-stream-e-kafka/author/henrique-schmidt?hsLang=pt)

*schedule* 1/nov/2022 12:08:14

Spring Cloud Stream é um framework que auxilia desenvolvedores com problemas de integração de dados, especialmente em aplicações orientadas a eventos. O objetivo da estrutura é facilitar a aplicação de padrões modernos de arquitetura de microsserviços, dissociar as responsabilidades do aplicativo e portar a lógica de negócios para os agentes de mensagens.

Neste artigo, mostrarei como é fácil implementar o Spring Cloud Stream e como ele pode ser não invasivo no código do aplicativo. Esses benefícios permitem que os desenvolvedores se concentrem no que importa: o negócio.

Abordaremos os seguintes tópicos:

1. Ligações
2. Um modelo de programação funcional
3. Um caso de negócios (uma API de voo)
4. Implementando a API de voo com Spring Cloud Stream e Kafka
5. Manipulação de erros

Ligações

Uma ligação (binding) é uma ponte entre o aplicativo e os sistemas de mensagens externos (Kafka, RabbitMQ, etc). A ligação envia e recebe mensagens.

Uma ligação é abstrata e o aplicativo não deve saber ou se importar se é uma implementação Kafka ou RabbitMQ.

![](https://blog.avenuecode.com/hubfs/Spring%20Cloud-png.png)*Imagem cortesia de [docs.spring.io.](https://docs.spring.io/spring-cloud-stream/docs/current/reference/html/spring-cloud-stream.html#spring-cloud-stream-reference)*

Na imagem acima, você pode ver que o núcleo da aplicação depende apenas do binder (ligação) e que o middleware é responsável pelos detalhes específicos do broker (Kafka, RabbitMQ, etc).

Para saber mais sobre isso, leia a seção [Bindings](https://docs.spring.io/spring-cloud-stream/docs/current/reference/html/spring-cloud-stream.html#_bindings) na documentação do projeto.

Modelo de Programação Funcional

Desde Spring Cloud Stream v2.1, é possível definir ligações criando beans dos tipos:

java.util.function.\[Supplier/Function/Consumer\].

Abaixo você pode ver uma ligação que recebe uma String de um canal (tópico, fila), a transforma em maiúscula e a envia para outro canal:

![](https://lh6.googleusercontent.com/3TOUJgwRT3V1SAD8T1uterSF2SMY-y-92Ln8EW-Qre9Y9KdR6_5TWt1Rd271Jlx8LNhKRuDCW6KHxWi6QIUp560c_kznUr92P-1366NZmVTEzFD9RSrD_2Ms-0TFTL8t2su-GyHGFTauF5usx_ed2OscxQEYmAXS5zeDfxFC9VTZo4kZ-yDXFvCJEg)

Há também a forma de definição de vínculos baseada em anotações, que é considerada uma forma herdada e não é recomendada para novos aplicativos. Para saber mais sobre isso, você pode ler [esta seção na documentação.](https://docs.spring.io/spring-cloud-stream/docs/current/reference/html/spring-cloud-stream.html#_annotation_based_binding_names_legacy)

Um caso de negócios: API de voo

Para ter uma implementação de exemplo neste post, usaremos o seguinte caso de negócios:

Há a necessidade de um aplicativo que possa gerenciar voos.

Este aplicativo armazenará todas as informações do voo, incluindo o avião, o ponto de partida do voo e o destino. O programa receberá uma mensagem toda vez que um avião chegar a um aeroporto. Assim que um avião chega ao seu destino, o aplicativo deve alterar o status do voo para "chegou".

Mais especificamente, o serviço receberá um evento de avião em um tópico do Kafka chamado plane-events-v1, então ele deverá converter o evento de avião em um evento de voo, enviando-o para o tópico flight-events-v1. Conforme mostrado abaixo, o microsserviço também deve consumir informações do flight-events-v1, alterando o status do voo para "chegou" caso o voo tenha chegado ao seu destino.

![](https://lh4.googleusercontent.com/4AjC9LEg2wOF3fHENGRnSZ45OEKFil0rg2meFXY2Wfh99oh41SaAx3GZmU3aXu6w5DcMN7ueu5UW6AlcWc9wemVXGC3Oc0UcCYEkqX0JoFiLYh9QRJt_SfLfztDIb2NVzkSiqn7qtKJTwEmIrp5NiDXmrcw3WYvVU3uCaLQ7GePy9dHERuH-Pc0poA)

Implementando a API Flight com Spring Cloud Stream e Kafka

Para implementar a API de voo, usaremos o Spring Cloud Stream com Kafka e MongoDB.

Em um aplicativo Spring Boot, você pode adicionar o iniciador spring-cloud-starter-stream-kafka para trabalhar com Kafka e Spring Cloud Stream.

Se você usa o Gradle, pode utilizar a seguinte dependência:

Implementação

'org.springframework.cloud:spring-cloud-starter-stream-kafka'

Todo o código-fonte mostrado neste artigo está disponível no GitHub [aqui](https://github.com/henriquels25/spring-cloud-stream-sample).

Na seção de implementação abaixo, abordaremos cada uma das seguintes áreas:

1. Processador de eventos de avião;
2. Consumo de eventos de voo;
3. Manipulação de erros.

Processador de eventos de avião

Para começar a nossa implementação, iniciaremos com a vinculação responsável por converter um evento de avião em um evento de voo. Os dois eventos são definidos em classes Java conforme mostrado abaixo:

![](https://lh5.googleusercontent.com/fIgNrA0mLZOMmXz-zEkY0IZyb0PxuzYmZeQua8uydTwYGwbZoTXwvo0hya17yGPHPhWGtAeWWaa6jqo8IVcBJv9HAV7MeG39VH7QAzaTlLhg5hfDyioNJamYJvpeKKIJ6AIkVxWwQUJKehIYtn-I1s7JN0Q5aoDmf78IhmvxU0qkvrgyi7F2BcR_RA)(Veja o código completo do GitHub [aqui.](https://github.com/henriquels25/spring-cloud-stream-sample))

![](https://lh3.googleusercontent.com/Xp_CBgNd2XRV_iztAQuVA6Cem-hstr1gml9CEeQo0GSgWkEdURFRyVyDTlmJVsJO45NFBd7w8ufeo6dKFIhK1U-ZzfZlphhQ0L9EEjucSORp3eIGZMIcZOrGJZhXp_NBhrqUXisXmmXcItk6Z0d4ZWWppt6eW0gs0NBK9ditOYBUi19EsMb2dnRCWQ)(Veja o código completo do GitHub [aqui.](https://github.com/henriquels25/spring-cloud-stream-sample))

Com ambos os eventos definidos, podemos criar a vinculação. Como queremos converter um evento em outro, usamos um tipo de bean java.util.function.Function. Abaixo você pode ver a implementação do processador de mensagens:

![](https://lh5.googleusercontent.com/ducRdfOexVc07FPsDI5XWrZSQdCgVdukr_xRJOX6GujvimDqHLMeFvmjUSfurZpyV4BG-1thCuCeJrVcoXk45gxWoiMkBlK8Qi6m5x2L7X3jAv0PPcK4HkyixkxTJ2U9_w-xODO6EVFA1DrO8kTSy8jVbGI7e6lyAXlAdXws_0RAHc-XIhXGBDg56Q)(Veja o código completo do GitHub [aqui.](https://github.com/henriquels25/spring-cloud-stream-sample))

O bean do processador delega a lógica de negócios ao FlightOperationsFacade. Se a lógica de negócios não encontrar o voo, uma exceção será gerada.

Para configurar este bean para funcionar, precisamos definir as seguintes propriedades prefixadas com spring.cloud.stream.bindings:

planeEventProcessor-in-0.destination: O tópico que o bean consumirá.

planeEventProcessor-in-0.group: O ID do grupo do consumidor Kafka.

planeEventProcessor-out-0.group: O tópico de destino para o qual os eventos de voo serão enviados.

Abaixo você pode ver a configuração da aplicação para este bean:

![](https://lh3.googleusercontent.com/31StD9BCFEppVhDJwEhOEzNqwtXTUBeYOhoUul7F9iAtYZ3u2JXcsOkeMa6l2vCVKcKrrPZfSQmhvUO1e1o64zDkA3sXJIcArnIxRN2N2LC-t6JVTj7VEAlkt5NP0i1GWM4TQLgA89rvUokcHz1MagH-dWVN-g0KiK57wNO8OBuNBwaH3H6vfUhb6Q)(Veja o código completo do GitHub [aqui.](https://github.com/henriquels25/spring-cloud-stream-sample))

Consumo de eventos de voo

Para consumir uma mensagem do tópico flight-events-v1, criaremos um bean java.util.function.Consumer conforme mostrado abaixo:

![](https://lh3.googleusercontent.com/oElkIbIHTpthLeYnehkMPRgG8utK3kQ-GqNzUbqdxGxavfS5T-TmeRd3tmQbIvuAeaCwRPsxOhfIsl4mI_KIVYQ_d-2CRzMx_JXQZL-ktuUpZk13a2Zy5cFPgDY29ACUYFN4GQ2tcHZEWBp2YJUGJCCenMQ2LLHZnlYkOo03l-uNBMMsOiv4Be5Qww)

Esse consumidor receberá a mensagem e chamará o módulo de lógica de negócios para cuidar dela.

Quando há mais de um bean de ligação funcional em um projeto, precisamos definir a propriedade spring.cloud.stream.function.definition com uma lista contendo cada bean. Abaixo podemos ver esta configuração na API de voo:

![](https://lh5.googleusercontent.com/11c5z1q5mYGlohVk4Iyx2Vr-W2_2Twd53rqLmLuessl8_22_15OVTfoUUi-JRhK9ItoKN8lmFIIh5QTPKAvtSsWkr38mMgNSWPBsUyuCbAU0kgzQArX3BNPmb2IAWWmE5zw9Ovj2W8veVarLiGqOVyoWphqUYdfZb8Kra-_-Ahp_XR7UtvMvJ6bnPQ)

Ao trabalhar com um consumidor, você deverá definir o tópico que ele ouvirá e o grupo ao qual ele pertence. Você pode vê-lo configurado abaixo:

![](https://lh5.googleusercontent.com/J24iUERVBM82547aY6dGQoYwTmfGbGpnxyXLTX7AJuQd8_RP8yz6po5L6eEpd2wl9KqcUm5wbvwSRZACHcdONykqxioY0RSP7U5LYV5TeANffrLW-3pof7FD7CeddGP5HDu1yyUgnxCcLaL-WV2zEV0ukWayJvB0e1R4bEeqNEn8yw2E5BOhZ1QtDw)

Manipulação de erros

O Spring Cloud Stream facilita a configuração e implementação do processamento de mensagens mortas e novas tentativas.

Processamento de cartas mortas

Muitas vezes, é útil enviar uma mensagem para um tópico especial quando ocorre uma exceção. Depois disso, as mensagens podem ser reprocessadas ou auditadas, dependendo do cenário de negócios.

Com o Spring Cloud Stream, precisamos apenas adicionar duas propriedades prefixadas com spring.cloud.stream.kafka.bindings.<binding-name>.consumer. Estes estão listados abaixo:

enableDlq: Propriedade que habilita o processamento de mensagens mortas. Quando ocorrer uma exceção e não houver mais tentativas configuradas, a mensagem será enviada para o tópico de mensagens mortas dessa ligação.  
dlqName: Nome do tópico de mensagens mortas.  
Na API de voo, em consumidores de eventos de avião e voo, o processamento de mensagens mortas será ativado. O tópico de mensagens mortas do evento de voo será flight-events-dlq-v1, e o tópico de mensagens mortas do avião será plane-events-dlq-v1.

Abaixo você pode ver o arquivo de configuração do aplicativo para este comportamento:

![](https://lh5.googleusercontent.com/LqoPl1v8LevNvRwB5-WKuatrSSmNOBBX6jdQVzaJpFgI3HodFBkcQvKdlbCPXZAKrqozI4GLCnNsqgaT7QtIdqQQtDT6sheZmpwcV4JZtBGuazGhGC3YZ_UBkSQtqG-FqpcrFMy7k-Ytvy6myfWH6ZWFXPgJ-2CLus7HBv3AX-s1TCzJtj_gPmICow)

Novas tentativas

Outro recurso interessante do Spring Cloud Stream é que você pode configurar o número de vezes que uma mensagem será reprocessada. Isso é muito útil para erros transitórios.

Por padrão, todas as mensagens são processadas três vezes, sendo eventualmente processadas com sucesso, enviadas para um tópico de mensagens mortas, se configurado, ou simplesmente descartadas.

Para permitir que você altere o número de tentativas, a propriedade spring.cloud.stream.bindings.<binding-name>.consumer.maxAttempts está disponível.

Você também terá a opção de configurar o tempo máximo de repetição e o tempo decorrido entre as tentativas de processamento. Para saber mais sobre isso, leia a seção de documentação intitulada [Retry Template.](https://docs.spring.io/spring-cloud-stream/docs/current/reference/html/spring-cloud-stream.html#_retry_template)

Na API de voo, manteremos o comportamento padrão de novas tentativas. No entanto, no caso do processador de eventos de avião, não queremos tentar novamente se a exceção for uma NoFlightFoundException. Como esse erro não é transitório, ele continuará a ocorrer, não importa quantas tentativas sejam feitas.

Para configurar isso, usamos a propriedade spring.cloud.stream.bindings.<binding-name>.consumer.retryable-exceptions. Abaixo você pode ver como ele está configurado na API de voo:

![](https://lh3.googleusercontent.com/vcGRljsHV0e787tN80RjmjKTOcHrwCOizruxAJ9cxFRcjP7nCS7deQbvlrTTZMg726UQlUkygMJPtxYlYD7p92aHAuC8dkRAOJP6zKtnH6tkcRJ1Gbe_wCwUA3ip7xXWHhsAgL_F0coZAmh8cX0VI4wsdmQbwsxXLNFBUMQVwXl3ubXUT0s5sAw0WA)

Conclusão

Este artigo mostra como pode ser fácil desenvolver microsserviços orientados a mensagens usando Spring Boot, e como podemos desenvolver código de negócios com interferência mínima em código de estrutura.

Há muito mais sobre o que falar com o Spring Cloud Stream, então recomendo que você leia a [documentação](https://docs.spring.io/spring-cloud-stream/docs/current/reference/html/index.html) e também confira o exemplo de caso de negócios completo no [repositório do GitHub.](https://github.com/henriquels25/spring-cloud-stream-sample)

---

### Autor

# Henrique Schmidt

---

### Posts Relacionados

### Deixe um comentário!

### Redes Sociais

[![Facebook Icon](https://blog.avenuecode.com/hubfs/Images/Blog/facebook.png?t=1486470796564)](https://www.facebook.com/avenuecode)

[![Twitter Icon](https://blog.avenuecode.com/hubfs/Images/Blog/twitter.png?t=1486470796842)](https://twitter.com/AvenueCode)

[![LinkedIn Icon](https://blog.avenuecode.com/hubfs/Images/Blog/linkedin.png?t=1486470796556)](https://www.linkedin.com/company/avenuecode/)

### Newsletter

Quer ficar por dentro de todas as dicas e novidades da Avenida Code?

### Posts Recentes

![Avenue Code-primary versions_logo white avenue code endorsement 2](https://blog.avenuecode.com/hs-fs/hubfs/Avenue%20Code%20New%20Logos%20-%202023/Avenue%20Code-primary%20versions_logo%20white%20avenue%20code%20endorsement%202.png?width=1180&name=Avenue%20Code-primary%20versions_logo%20white%20avenue%20code%20endorsement%202.png "Avenue Code-primary versions_logo white avenue code endorsement 2")

### Sobre Nós

- [Quem Somos](https://avenuecode.com.br/who-we-are/)
- [O Que Fazemos](https://avenuecode.com.br/what-we-do/)
- [Portfólio](https://avenuecode.com.br/portfolio/)
- [Parceiros](https://avenuecode.com.br/partners/)
- [Notícias](https://www.avenuecode.com/news)
- [Eventos](https://avenuecode.com.br/events/)
- [Blog](https://blog.avenuecode.com/pt?hsLang=pt)
- [Contato](https://avenuecode.com.br/contact/)
- [Política de Privacidade](https://drive.google.com/file/d/1V4smFr1Li3eRE1W7xAxO8EQItXOo-ndi/view?usp=sharing)
-  

### Nossos Escritórios

San Francisco

[+1 415 766 4178](tel:+553125161448) [ac.inquiries@avenuecode.com](mailto:brazil.info@avenuecode.com)

Belo Horizonte

[+55 31 2516 1448](tel:+553125161448) [brazil.info@avenuecode.com](mailto:brazil.info@avenuecode.com)

São Paulo

[+55 11 3205 3232](tel:+553125161448) [brazil.info@avenuecode.com](mailto:brazil.info@avenuecode.com)

Porto Alegre

[brazil.info@avenuecode.com](mailto:brazil.info@avenuecode.com)

New York

[ac.inquiries@avenuecode.com](mailto:ac.inquiries@avenuecode.com)

Montréal

[ac.inquiries@avenuecode.com](mailto:ac.inquiries@avenuecode.com)

### Estamos Contratando!

- [Belo Horizonte](https://avenuecode.com.br/open-positions/?location=belo-horizonte)
- [New York](https://avenuecode.com.br/open-positions/?location=new-york)
- [San Francisco](https://avenuecode.com.br/open-positions/?location=san-francisco)
- [São Paulo](https://avenuecode.com.br/open-positions/?location=sao-paulo)
- [Porto Alegre](https://avenuecode.com.br/open-positions/?location=porto-alegre)
- [Montréal](https://avenuecode.com.br/open-positions/?location=montreal)
-  

---

©2015 - 2022 Avenue Code

[![Facebook Icon](https://blog.avenuecode.com/hubfs/Images/Icons/facebook-2.png)](https://www.facebook.com/avenuecode) [![Twitter Icon](https://blog.avenuecode.com/hubfs/Images/Icons/twitter-2.png)](https://twitter.com/AvenueCode) [![LinkedIn Icon](https://blog.avenuecode.com/hubfs/Images/Icons/linkedin-2.png)](https://www.linkedin.com/company/avenue-code) [![Glassdoor Icon](https://blog.avenuecode.com/hubfs/Images/Icons/glassdoor-icon-1.png)](https://www.glassdoor.com/Overview/Working-at-Avenue-Code-EI_IE456173.11,22.htm) [![YouTube Icon](https://blog.avenuecode.com/hubfs/Images/Icons/youtube-2.png)](https://www.youtube.com/user/AvenueCodePlay)

Please enable JavaScript to view the [comments powered by Disqus.](http://disqus.com/?ref_noscript)

© 2026 Avenue Code