Modul 321 Alle Aufgaben

Aufgabe 9: Kafka mit Spring Boot

Ausgangslage

In Aufgabe 8 haben Sie die Kafka-Begriffe geklärt. Jetzt setzen Sie sie um: Eine Spring-Boot-Anwendung sendet Nachrichten über Kafka (Producer) und empfängt sie wieder (Consumer). Kafka läuft lokal in Docker.

flowchart LR
    C["Browser / Postman"] -->|"GET /send"| R["MessageController"]
    R --> P["KafkaProducer"]
    P -->|"testTopic"| K[("Kafka :9092")]
    K -->|"testTopic"| L["KafkaConsumer"]

Teil 1: Kafka starten

Erstellen Sie eine docker-compose.yml und starten Sie sie mit docker compose up:

services:
  kafka:
    image: apache/kafka:3.9.0
    ports:
      - "9092:9092"

Das Image startet einen einzelnen Broker ohne Zookeeper (KRaft-Modus), erreichbar auf localhost:9092. Prüfen Sie mit docker ps, dass der Container läuft.


Teil 2: Producer und Consumer

  1. Erstellen Sie auf start.spring.io ein Projekt mit Spring for Apache Kafka, Spring Web und Lombok.

  2. Konfiguration in application.properties:

    spring.kafka.bootstrap-servers=localhost:9092
    spring.kafka.consumer.group-id=myGroup
    spring.kafka.consumer.auto-offset-reset=earliest
  3. Implementieren Sie die drei Klassen:

    @Service
    public class KafkaProducer {
        @Autowired
        private KafkaTemplate<String, String> kafkaTemplate;
    
        public void sendMessage(String message) {
            kafkaTemplate.send("testTopic", message);
        }
    }
    @Service
    public class KafkaConsumer {
        @KafkaListener(topics = "testTopic", groupId = "myGroup")
        public void listen(String message) {
            System.out.println("Received message in group myGroup: " + message);
        }
    }
    @RestController
    public class MessageController {
        @Autowired
        private KafkaProducer producer;
    
        @GetMapping("/send")
        public String sendMessage(@RequestParam("message") String message) {
            producer.sendMessage(message);
            return "Message sent";
        }
    }
  4. Starten Sie die Anwendung und rufen Sie http://localhost:8080/send?message=Hallo auf. Die Nachricht muss in der Konsole erscheinen.


Teil 3: Strukturierte Nachrichten

Statt Strings senden Sie ein Objekt als JSON.

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class CustomMessage {
    private String id;
    private String message;
    private LocalDateTime timestamp;
}
  1. Passen Sie Producer (KafkaTemplate<String, CustomMessage>) und Consumer (listen(CustomMessage message)) an.

  2. Ergänzen Sie einen neuen Endpunkt, der eine CustomMessage mit eigener ID und aktuellem Zeitstempel versendet.

  3. Konfigurieren Sie die JSON-Serialisierung:

    spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer
    spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer
    spring.kafka.consumer.properties.spring.json.trusted.packages=*

Teil 4: Zweiter Consumer (Zusatz)

Erstellen Sie ein neues Projekt (nicht kopieren) mit nur einem Consumer, ohne Producer und ohne Controller. Starten Sie beide Anwendungen und senden Sie eine Nachricht.

Beobachten Sie, was passiert, wenn der zweite Consumer


Kontrollfragen

Beantworten Sie in ein bis zwei Sätzen:

  1. Welche Klasse sendet Nachrichten an ein Topic, und welche Annotation markiert die Empfängermethode?
  2. Wie wird die Adresse des Kafka-Servers in Spring Boot konfiguriert?
  3. Warum ist die JSON-Serialisierung für strukturierte Nachrichten nötig?
  4. Was geschah in Teil 4 bei gleicher und bei unterschiedlicher group-id? Erklären Sie den Unterschied.
  5. Welche Strategien gibt es bei Fehlern beim Senden oder Empfangen (z. B. Retry, Dead Letter Topic)?
  6. Wie lässt sich eine Kafka-Anwendung skalieren?

Abgabe

  1. Lauffähiges Projekt mit Producer, Consumer und CustomMessage (Git-Repository oder ZIP).
  2. Screenshot der Konsole mit der empfangenen Nachricht.
  3. Beantwortete Kontrollfragen.