Spring Cloud Stream / Spring Integration

Diese Seite bleibt auch ohne JavaScript lesbar. Suche und Buttons sind Zusatzkomfort.

Spring Cloud Stream und Spring Integration

Events, Binder, Enterprise Integration Patterns, Idempotenz und Dead Letter.

Event-driven Flow: Domain Event über Binder zu Consumer Group Order Serviceproduziert Event Bindingout-0 BrokerKafka/Rabbit Consumer GroupBilling/Shipping Fachlich: Ereignisse bedeuten etwas. Technisch: At-least-once, Idempotenz und Dead Letter sind Pflicht.
1. Event-driven heißt fachlich denken

Ein Event ist nicht nur eine technische Nachricht. Es beschreibt eine fachliche Tatsache: OrderSubmitted, PaymentCaptured, ShipmentPrepared. Wenn Events nur als technische DTOs ohne Bedeutung gebaut werden, entstehen schwer wartbare Integrationsketten.

Spring Cloud Stream abstrahiert Broker über Binder. Dadurch kann Anwendungscode stärker auf Funktionen und Nachrichten fokussieren, während Kafka, RabbitMQ oder andere Systeme über Konfiguration eingebunden werden.

Funktionaler Consumer
@Configuration
class OrderEventHandlers {
    @Bean
    Consumer<OrderSubmittedEvent> reserveStock(InventoryService inventory) {
        return event -> inventory.reserve(event.orderId(), event.lines());
    }
}
Binding Konfiguration
spring:
  cloud:
    function:
      definition: reserveStock
    stream:
      bindings:
        reserveStock-in-0:
          destination: order-submitted
          group: inventory-service
      kafka:
        bindings:
          reserveStock-in-0:
            consumer:
              enableDlq: true
2. Idempotenz und At-least-once

Viele Broker liefern praktisch mindestens einmal. Das heißt: ein Consumer muss Duplikate verkraften. Eine fachliche Operation wie Reservierung, Buchung oder Benachrichtigung braucht einen Idempotenzschlüssel und eine klare Wiederholungsstrategie.

Idempotenz anhand Event-ID
@Transactional
public void reserve(OrderSubmittedEvent event) {
    if (processedEvents.existsById(event.eventId())) {
        return;
    }
    inventory.reserve(event.orderId(), event.lines());
    processedEvents.save(new ProcessedEvent(event.eventId(), Instant.now()));
}
3. Spring Integration und EIP

Spring Integration ist stark, wenn Nachrichten zwischen Systemen transformiert, geroutet, gesplittet, aggregiert oder über Adapter mit Dateien, Mail, FTP, JMS, JDBC oder anderen Kanälen verbunden werden. Es ist besonders für Integrationslandschaften nützlich, nicht für jede kleine interne Methode.

IntegrationFlow als technischer Adapter
@Bean
IntegrationFlow inboundFileFlow(OrderImportService importer) {
    return IntegrationFlow
        .from(Files.inboundAdapter(new File("/imports/orders")), e -> e.poller(Pollers.fixedDelay(5000)))
        .filter(file -> ((File) file).getName().endsWith(".csv"))
        .transform(new CsvToOrderCommandTransformer())
        .handle(importer, "importOrder")
        .get();
}

Enterprise-Prüffragen

  • Events fachlich benannt?
  • Idempotenz pro Consumer geklärt?
  • DLQ und Retry bewusst konfiguriert?
  • IntegrationFlow als Adapter statt Fachlogik-Monster?