⌂ Index
Kapitel 19 · Messaging

Spring for Apache Kafka

Typ: LibraryVersion 2 ausführlich

Spring for Apache Kafka stellt KafkaTemplate, Listener-Container, Error Handling und Transaktionsintegration für Kafka bereit.

Fachliche Einordnung

Kafka ist mächtig, aber die betrieblichen Details sind anspruchsvoll: Consumer Groups, Offsets, Rebalancing, Schema-Evolution, Fehlerbehandlung und Exactly-once-Erwartungen.

Enterprise-Merksatz: Spring for Apache Kafka stellt KafkaTemplate, Listener-Container, Error Handling und Transaktionsintegration für Kafka bereit.

Technische Darstellung

Producer KafkaTemplate Topic Consumer Group @KafkaListener DLT
Kernkonzepte
  • KafkaTemplate für Producer.
  • @KafkaListener für Consumer.
  • ConcurrentKafkaListenerContainerFactory.
  • Deserializer, ErrorHandlingDeserializer und Dead Letter Topics.
  • Manuelles Ack und Idempotenz.
Wann einsetzen?
  • Du nutzt Kafka bewusst als Event Log oder Streaming-Plattform.
  • Du brauchst feinere Kafka-Kontrolle als Cloud Stream bietet.
  • Du willst DLT und Retry detailliert konfigurieren.
Typische Fehler und Risiken
  • Offset commit vor erfolgreicher Verarbeitung.
  • Zu große Events oder instabile Schemas.
  • Partition Key nicht fachlich gewählt.
Legacy- und Modernisierungssicht

JMS Topic/Queue-Kommunikation wird nicht automatisch Kafka. Für Kafka sollte ein Event-Modell mit Keys, Versionen und Consumer-Verantwortung definiert werden.

Ausführliches Beispiel

Das Beispiel zeigt bewusst nicht nur Annotationen, sondern auch die Verantwortung der Schicht. In echten Projekten sollte der technische Spring-Code an Adapter- oder Konfigurationsrändern bleiben, während die Fachlogik testbar und möglichst frameworkarm bleibt.

@Service
class OrderKafkaPublisher {
    private final KafkaTemplate<String, OrderCreatedEvent> kafka;

    void publish(OrderCreatedEvent event) {
        kafka.send("order.created.v1", event.orderId().toString(), event);
    }
}

@Component
class OrderCreatedConsumer {
    @KafkaListener(topics = "order.created.v1", groupId = "billing-service")
    void consume(OrderCreatedEvent event, Acknowledgment ack) {
        billingService.createInvoiceIfMissing(event.orderId());
        ack.acknowledge();
    }
}
Checkliste für Reviews
  • Ist die Verantwortung des Bausteins klar: Framework steuert Lebenszyklus, Library wird gezielt benutzt?
  • Ist die Fachlogik außerhalb von Controller, Listener, Repository-Implementierung oder Konfiguration?
  • Sind Fehlerfälle, Timeouts, Security, Monitoring und Tests sichtbar modelliert?
  • Gibt es klare Grenzen zwischen DTO, Domäne, Persistence und Infrastruktur?