Zweite und dritte Erweiterung aus M6 - beide schliessen einen in fruehen M6-Vorgaenger-Phasen bewusst offen gelassenen Punkt, deshalb hier gemeinsam dokumentiert.
ClaimIntakeKafkaListenerDas Legacy-ClaimIntakeMDB verliess sich auf JMSXDeliveryCount: nach einer konfigurierten
Zahl fehlgeschlagener Zustellversuche verschob der MQ-Broker eine Nachricht automatisch in
eine Backout-Queue. Kafka kennt dieses Konzept nicht (Nachrichten werden per Offset, nicht per
Zustellversuch verwaltet) - ohne Gegenmassnahme haette ein dauerhaft fehlschlagender Consumer
(z. B. weil PolicyManagementService.registerClaim eine Exception wirft) entweder endlos
denselben Offset wiederholt (Consumer haengt) oder die Nachricht stillschweigend uebersprungen
(Datenverlust).
KafkaConsumerConfig.claimIntakeContainerFactory(...): DefaultErrorHandler mit
FixedBackOff(1_000L, 2) (zwei Wiederholungsversuche im Sekundenabstand) und
DeadLetterPublishingRecoverer als Recovery-Strategie - nach Erschoepfen der
Wiederholungen wird die Nachricht auf novaris.claims.submitted.DLT veroeffentlicht statt
verworfen.deadLetterKafkaTemplate (@Bean): eigenes KafkaTemplate<Object, Object>, das der
DeadLetterPublishingRecoverer fuer die Veroeffentlichung nutzt.ClaimIntakeKafkaListener nutzt containerFactory = "claimIntakeContainerFactory" statt
der Default-Factory.ClaimIntakeDeadLetterTest (@SpringBootTest + @EmbeddedKafka, echter eingebetteter
Kafka-Broker, kein Mock): PolicyManagementService wird per @MockBean so praepariert, dass
sie fuer die Policennummer NOV-BOOM-1 eine RuntimeException wirft. Ein
raw-KafkaProducer sendet diese "Giftnachricht" auf novaris.claims.submitted; ein
raw-KafkaConsumer liest anschliessend novaris.claims.submitted.DLT und bestaetigt, dass
genau die Giftnachricht dort ankommt - nach den zwei konfigurierten Wiederholungsversuchen
(Testlaufzeit dadurch real ca. 100-160s, kein beschleunigtes Zeit-Mocking). Verifiziert damit
den kompletten Pfad Produzent -> Consumer-Fehlschlag -> Retry -> Dead-Letter-Publish
gegen einen echten Broker, nicht nur die Konfiguration selbst.
Db2LegacyBenchmarkPortLegacyBenchmarkPort (Ersatz fuer die DB2-Benchmark-Abfrage in
PremiumCalculationBean.averagePremium) hatte bislang nur eine NoOpLegacyBenchmarkPort-
Platzhalterimplementierung (immer Optional.empty()) - der Adapter selbst war nie gebaut,
nur die Portschnittstelle. Damit war die DB2-Anbindung staerker unvollstaendig als etwa die
SOAP- oder Kafka-Anbindung, die von Anfang an echte Adapter hatten.
Db2DataSourceConfig: zweite DataSource (db2DataSource, HikariCP,
com.ibm.db2.jcc.DB2Driver, initializationFailTimeout(-1) fuer lazy-fehlschlagende
Verbindungen statt eines harten Boot-Fehlers) neben der primaeren
Anwendungs-Datenquelle.Db2LegacyBenchmarkPort: echter JDBC-Zugriff (PreparedStatement +
SELECT AVG(CTR_PREM_AMT) ... WHERE CTR_PROD_CD = ? AND CTR_MIGR_FL = 'N' AND
CTR_STAT_CD = 'A') statt der entfernten No-Op-Implementierung. SQL-Fehler werden in
UpstreamSystemUnavailableException gewrappt (Aufrufer entscheidet, wie im
Legacy-Original ein DB2-Ausfall kein harter Fehler, sondern eine tolerierbare
fehlende historische Korrektur ist).DataSource-BeanNach Hinzufuegen der zweiten DataSource-Bean schlug die gesamte Testsuite
(ClaimIntakeDeadLetterTest) mit "Unable to determine Dialect without JDBC metadata" fehl -
Spring konnte nicht mehr eindeutig ermitteln, welche der beiden DataSource-Bohnen in die
JPA-Autokonfiguration einfliessen soll. Behoben durch explizites @Primary auf einer
redeklarierten Standard-Datenquelle (DataSourceProperties.initializeDataSourceBuilder())
sowie @Qualifier("db2DataSource") am Db2LegacyBenchmarkPort-Konstruktor, damit dieser
garantiert nicht versehentlich die primaere Datenquelle erhaelt.
Db2LegacyBenchmarkPortTest: nutzt org.h2.jdbcx.JdbcDataSource
(jdbc:h2:mem:ctrmaster;DB_CLOSE_DELAY=-1) mit einer zur DB2-Tabelle
strukturgleichen CTR_MASTER-Tabelle. Drei Tests - korrekte Durchschnittsberechnung ueber
mehrere Zeilen, leeres Ergebnis (Optional.empty()) bei keiner passenden Zeile,
SQL-Fehler wird korrekt in UpstreamSystemUnavailableException gewrappt (erzwungen per
vorzeitig geschlossener Datenquelle).
Wie im Legacy-Reactor unter docs/40-persistence-oracle-db2/02-db2-nur-dokumentiert.md
bereits fuer die Legacy-Seite begruendet: eine echte DB2-Instanz stand in dieser
Entwicklungsumgebung nicht zur Verfuegung, IBM stellt kein leichtgewichtiges
offizielles Docker-Testimage bereit. Verifiziert wurde deshalb die komplette
JDBC-Zugriffslogik (SQL, Mapping, Exception-Handling) gegen eine strukturell identische
H2-Tabelle - real getestet, aber nicht gegen den tatsaechlichen DB2-JCC-Treiber/-Server.
Die Kafka-Dead-Letter-Anbindung hingegen wurde vollstaendig real verifiziert (siehe oben),
weil dafuer ein eingebetteter Broker verfuegbar ist.