You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fixes: #4328
Extract the DLT record header-building logic into a new DeadLetterRecordManager
class so it can be used outside of DeadLetterPublishingRecoverer.
Add two new handlers, RecoveringProcessingExceptionHandler and
RecoveringProductionExceptionHandler, to handle processing and production errors, respectively.
Add a common AbstractRecoveringExceptionHandler that centralizes
the shared error-handling logic for all provided recovering exception handlers.
Add a KafkaStreamsDeadLetterDestinationResolver to allow users to define
dead-letter routing logic used by the Kafka Streams native DLQ in the provided
exception handler implementations.
Update StreamsBuilderFactoryBean to expose a dead-letter queue topic name
as a possible destination for all provided recovering exception handler implementations.
Signed-off-by: Loïc Greffier <loic.greffier@michelin.com>
The recovery strategies are as follows, by priority order:
310
+
311
+
- If a xref:streams.adoc#dead-letter-destination-resolver[`KafkaStreamsDeadLetterDestinationResolver`] is defined, resume the stream and forward the failed record to the resolved topic-partition using the native Kafka Streams DLQ.
312
+
- If xref:streams.adoc#dead-letter-queue-topic-name-property[`errors.dead.letter.queue.topic.name`] is defined and set to a topic name, resume the stream and forward the failed record to that topic using the native Kafka Streams DLQ.
313
+
- If a `ConsumerRecordRecoverer` implementation is defined, invoke it and resume the stream without producing dead-letter records, as handling is delegated to the `ConsumerRecordRecoverer`. For example, the provided xref:streams.adoc#dead-letter-publishing-recoverer[`DeadLetterPublishingRecoverer`] implementation can be used.
314
+
- Fail the stream without producing dead-letter records.
315
+
316
+
When a dead-letter record is published to a dead-letter topic, whether through the native Kafka Streams DLQ or via a `ConsumerRecordRecoverer` implementation, the record is enriched with the xref:kafka/annotation-error-handling.adoc#dead-letters[Spring for Apache Kafka DLT headers].
317
+
300
318
[[streams-deser-recovery]]
301
319
== Recovery from Deserialization Exceptions
302
320
303
-
Version 2.3 introduced the `RecoveringDeserializationExceptionHandler` which can take some action when a deserialization exception occurs.
304
-
Refer to the Kafka documentation about `DeserializationExceptionHandler`, of which the `RecoveringDeserializationExceptionHandler` is an implementation.
305
-
The `RecoveringDeserializationExceptionHandler` is configured with a `ConsumerRecordRecoverer` implementation.
306
-
The framework provides the `DeadLetterPublishingRecoverer` which sends the failed record to a dead-letter topic.
307
-
See xref:kafka/annotation-error-handling.adoc#dead-letters[Publishing Dead-letter Records] for more information about this recoverer.
321
+
Version 2.3 introduced the `RecoveringDeserializationExceptionHandler`, which can take some action when a deserialization exception occurs.
322
+
It implements the `DeserializationExceptionHandler` interface (refer to the Kafka documentation for details) and follows the xref:streams.adoc#recovery-strategies[Spring for Apache Kafka recovery strategies].
323
+
324
+
To configure the `RecoveringDeserializationExceptionHandler`, add the following property to your streams configuration:
Version 4.1 introduces the `RecoveringProcessingExceptionHandler`, which can take some action when an exception occurs during stream processing.
343
+
It implements the `ProcessingExceptionHandler` interface (refer to the Kafka documentation for details), introduced by https://cwiki.apache.org/confluence/display/KAFKA/KIP-1033%3A+Add+Kafka+Streams+exception+handler+for+exceptions+occurring+during+processing[KIP-1033]
344
+
and follows the xref:streams.adoc#recovery-strategies[Spring for Apache Kafka recovery strategies].
345
+
346
+
To enable the `RecoveringProcessingExceptionHandler`, add the following property to your streams configuration:
Version 4.1 introduces the `RecoveringProductionExceptionHandler`, which can take some action when an exception occurs during record production or serialization.
364
+
It implements the `ProductionExceptionHandler` interface (refer to the Kafka documentation for details) and follows the xref:streams.adoc#recovery-strategies[Spring for Apache Kafka recovery strategies].
365
+
366
+
To configure the `RecoveringProductionExceptionHandler`, add the following property to your streams configuration:
@@ -330,6 +407,60 @@ public DeadLetterPublishingRecoverer recoverer() {
330
407
331
408
Of course, the `recoverer()` bean can be your own implementation of `ConsumerRecordRecoverer`.
332
409
410
+
[[dead-letter-destination-resolver]]
411
+
== Dead Letter Destination Resolver
412
+
413
+
A bean of type `KafkaStreamsDeadLetterDestinationResolver` can be defined to activate native DLQ routing in the exception handlers.
414
+
415
+
It determines the DLQ topic name and partition resolution logic to use, based on the error handler context, the input record of the failed processor, and the exception thrown:
416
+
417
+
[source, java]
418
+
----
419
+
@Bean
420
+
public KafkaStreamsDeadLetterDestinationResolver resolver() {
421
+
return (context, record, ex) -> {
422
+
if (ex instanceof FooException) return new TopicPartition("dlqTopic1", -1);
423
+
if (record instanceof Foo) return new TopicPartition("dlqTopic2", -1);
424
+
if (context.processorNodeId().equals("processor-1")) return new TopicPartition("dlqTopic3", -1);
425
+
return new TopicPartition("defaultDlqTopic", -1);
426
+
};
427
+
}
428
+
----
429
+
430
+
A negative partition number indicates that the partition will be determined by the default partitioner.
431
+
432
+
The `KafkaStreamsDeadLetterDestinationResolver` can then be injected into the exception handlers as follows:
The Kafka Streams property `errors.dead.letter.queue.topic.name` can be defined and set to a topic name to activate native DLQ routing in the exception handlers.
452
+
This directly specifies the DLQ topic to which the enabled exception handlers will route all failed records.
453
+
454
+
Alternatively, this can be set programmatically through the `StreamsBuilderFactoryBean`:
455
+
456
+
[source, java]
457
+
----
458
+
@Bean
459
+
public StreamsBuilderFactoryBeanConfigurer streamsBuilderFactoryBeanConfigurer() {
Copy file name to clipboardExpand all lines: spring-kafka-docs/src/main/antora/modules/ROOT/pages/whats-new.adoc
+17Lines changed: 17 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,3 +36,20 @@ See xref:kafka/kafka-queues.adoc#share-acknowledgment-api[ShareAcknowledgment AP
36
36
37
37
The default value of `sameIntervalTopicReuseStrategy` in `RetryTopicConfigurationBuilder` has been changed from `MULTIPLE_TOPICS` to `SINGLE_TOPIC` to align with the `@RetryableTopic` annotation default.
38
38
See xref:retrytopic/topic-naming.adoc[Topic Naming] for more information.
39
+
40
+
[[x41-kafka-streams-native-dlq]]
41
+
=== Kafka Streams Native DLQ Support
42
+
43
+
Spring for Apache Kafka now provides exception handlers that support Kafka Streams DLQ (KIP-1034, Kafka 4.2):
The provided exception handlers support multiple Kafka Streams DLQ enabling strategies and dead-letter topic resolution options:
50
+
51
+
- The Kafka Streams property xref:streams.adoc#dead-letter-queue-topic-name-property[`errors.dead.letter.queue.topic.name`].
52
+
- An implementation of the new xref:streams.adoc#dead-letter-destination-resolver[`KafkaStreamsDeadLetterDestinationResolver`] functional interface for dynamic resolution.
53
+
- The `setDeadLetterTopicName()` method of the xref:streams.adoc#dead-letter-queue-topic-name-property[`StreamsBuilderFactoryBean`].
54
+
55
+
`RecoveringDeserializationExceptionHandler.KSTREAM_DESERIALIZATION_RECOVERER` has been deprecated in favor of `RecoveringDeserializationExceptionHandler.RECOVERER` to align with the new handlers properties.
0 commit comments