0

I am using Spring Cloud Stream version 2.2.0 with Kafka binder and Avro. Apparently, an incorrect record has been published to one of the Kafka topics where it is causing all the consumers to return deserialization error and goes to some sort of infinite retry.

Error deserializing key/value for partition realtime-object-1 at offset 908. If needed, please seek past the record to continue consumption. Caused by: org.apache.kafka.common.errors.SerializationException: Error deserializing Avro message for id 13 Caused by: org.apache.kafka.common.errors.SerializationException: Could not find class au.com.brolly.avro.model.GenericTaskTriggerCapsule specified in writer's schema whilst finding reader's schema for a SpecificRecord.

Technically, there should be a way that I can specify the policy for deserialization exceptions. I can find some different policies like logAndContinue and sendToDlq but they are for Kafka streams which I don't use in my application. I would appreciate it if someone can help me to understand what I am missing here.

Ali
  • 1,759
  • 2
  • 32
  • 69

1 Answers1

2

See the spring-kafka documentation.

Use an ErrorHandlingDeserializer2 to wrap the avro deserializer. The exception will be sent to the error handler (which will just just log the error, by default).

You can use a ListenerContainerCustomizer bean to add a SeekToCurrentErrorHandler (optionally with a DeadLetterPublishingRecoverer) to send the record that failed deserialization to another topic.

EDIT

Here's an example to configure it with Spring Cloud Stream...

@SpringBootApplication
@EnableBinding(Sink.class)
public class So60827393Application {

    public static void main(String[] args) {
        SpringApplication.run(So60827393Application.class, args);
    }

    @StreamListener(Sink.INPUT)
    public void listen(String in) {

    }

    @Bean
    public ApplicationRunner runner(KafkaTemplate<byte[], byte[]> template) {
        return args -> template.send("foo", "foo".getBytes());
    }
}
public class MyBadDeserializer implements Deserializer {

    @Override
    public Object deserialize(String topic, byte[] data) {
        throw new RuntimeException("Always fails");
    }

}
spring.cloud.stream.bindings.input.destination=foo
spring.cloud.stream.bindings.input.group=foo
spring.cloud.stream.bindings.input.consumer.use-native-decoding=true

spring.cloud.stream.kafka.bindings.input.consumer.configuration.value.deserializer=org.springframework.kafka.support.serializer.ErrorHandlingDeserializer2
spring.cloud.stream.kafka.bindings.input.consumer.configuration.spring.deserializer.value.delegate.class=com.example.demo.MyBadDeserializer

Add any additional properties (such as the schema registry URL) to the configuration as before (the EHD2 configures it's delegate deserializer).

2020-03-24 18:18:35.633 ERROR 61822 --- [container-0-C-1] o.s.kafka.listener.LoggingErrorHandler   : Error while processing: ConsumerRecord(topic = foo, partition = 0, leaderEpoch = 0, offset = 0, CreateTime = 1585088312600, serialized key size = -1, serialized value size = 3, headers = RecordHeaders(headers = [RecordHeader(key = springDeserializerExceptionValue, value = [-84, -19, 0, 5, 115, 114, 0, 69, 111, 114, 103, 46, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 46, 107, 97, 102, 107, 97, 46, 115, 117, 112, 112, 111, 114, 116, 46, 115, 101, 114, 105, 97, 108, 105, 122, 101, 114, 46, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 97, 116, 105, 111, 110, 69, 120, 99, 101, 112, 116, 105, 111, 110, -26, -50, 105, 87, -16, 47, -111, -25, 2, 0, 2, 90, 0, 5, 105, 115, 75, 101, 121, 91, 0, 4, 100, 97, 116, 97, 116, 0, 2, 91, 66, 120, 114, 0, 40, 111, 114, 103, 46, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 46, 107, 97, 102, 107, 97, 46, 75, 97, 102, 107, 97, 69, 120, 99, 101, 112, 116, 105, 111, 110, 19, -40, -67, 105, 126, 123, 33, -76, 2, 0, 0, 120, 114, 0, 47, 111, 114, 103, 46, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 46, 99, 111, 114, 101, 46, 78, 101, 115, 116, 101, 100, 82, 117, 110, 116, 105, 109, 101, 69, 120, 99, 101, 112, 116, 105, 111, 110, 75, 126, 118, 72, -53, -113, -97, 0, 2, 0, 0, 120, 114, 0, 26, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101, 69, 120, 99, 101, 112, 116, 105, 111, 110, -98, 95, 6, 71, 10, 52, -125, -27, 2, 0, 0, 120, 114, 0, 19, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 69, 120, 99, 101, 112, 116, 105, 111, 110, -48, -3, 31, 62, 26, 59, 28, -60, 2, 0, 0, 120, 114, 0, 19, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 84, 104, 114, 111, 119, 97, 98, 108, 101, -43, -58, 53, 39, 57, 119, -72, -53, 3, 0, 4, 76, 0, 5, 99, 97, 117, 115, 101, 116, 0, 21, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 84, 104, 114, 111, 119, 97, 98, 108, 101, 59, 76, 0, 13, 100, 101, 116, 97, 105, 108, 77, 101, 115, 115, 97, 103, 101, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 91, 0, 10, 115, 116, 97, 99, 107, 84, 114, 97, 99, 101, 116, 0, 30, 91, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 59, 76, 0, 20, 115, 117, 112, 112, 114, 101, 115, 115, 101, 100, 69, 120, 99, 101, 112, 116, 105, 111, 110, 115, 116, 0, 16, 76, 106, 97, 118, 97, 47, 117, 116, 105, 108, 47, 76, 105, 115, 116, 59, 120, 112, 115, 113, 0, 126, 0, 4, 113, 0, 126, 0, 12, 116, 0, 12, 65, 108, 119, 97, 121, 115, 32, 102, 97, 105, 108, 115, 117, 114, 0, 30, 91, 76, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 59, 2, 70, 42, 60, 60, -3, 34, 57, 2, 0, 0, 120, 112, 0, 0, 0, 18, 115, 114, 0, 27, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 97, 99, 107, 84, 114, 97, 99, 101, 69, 108, 101, 109, 101, 110, 116, 97, 9, -59, -102, 38, 54, -35, -123, 2, 0, 4, 73, 0, 10, 108, 105, 110, 101, 78, 117, 109, 98, 101, 114, 76, 0, 14, 100, 101, 99, 108, 97, 114, 105, 110, 103, 67, 108, 97, 115, 115, 113, 0, 126, 0, 8, 76, 0, 8, 102, 105, 108, 101, 78, 97, 109, 101, 113, 0, 126, 0, 8, 76, 0, 10, 109, 101, 116, 104, 111, 100, 78, 97, 109, 101, 113, 0, 126, 0, 8, 120, 112, 0, 0, 0, 31, 116, 0, 34, 99, 111, 109, 46, 101, 120, 97, 109, 112, 108, 101, 46, 100, 101, 109, 111, 46, 77, 121, 66, 97, 100, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 114, 116, 0, 22, 77, 121, 66, 97, 100, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 114, 46, 106, 97, 118, 97, 116, 0, 11, 100, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 115, 113, 0, 126, 0, 16, 0, 0, 0, 60, 116, 0, 50, 111, 114, 103, 46, 97, 112, 97, 99, 104, 101, 46, 107, 97, 102, 107, 97, 46, 99, 111, 109, 109, 111, 110, 46, 115, 101, 114, 105, 97, 108, 105, 122, 97, 116, 105, 111, 110, 46, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 114, 116, 0, 17, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 114, 46, 106, 97, 118, 97, 113, 0, 126, 0, 20, 115, 113, 0, 126, 0, 16, 0, 0, 0, -56, 116, 0, 71, 111, 114, 103, 46, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 46, 107, 97, 102, 107, 97, 46, 115, 117, 112, 112, 111, 114, 116, 46, 115, 101, 114, 105, 97, 108, 105, 122, 101, 114, 46, 69, 114, 114, 111, 114, 72, 97, 110, 100, 108, 105, 110, 103, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 114, 50, 116, 0, 31, 69, 114, 114, 111, 114, 72, 97, 110, 100, 108, 105, 110, 103, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 114, 50, 46, 106, 97, 118, 97, 113, 0, 126, 0, 20, 115, 113, 0, 126, 0, 16, 0, 0, 4, -12, 116, 0, 51, 111, 114, 103, 46, 97, 112, 97, 99, 104, 101, 46, 107, 97, 102, 107, 97, 46, 99, 108, 105, 101, 110, 116, 115, 46, 99, 111, 110, 115, 117, 109, 101, 114, 46, 105, 110, 116, 101, 114, 110, 97, 108, 115, 46, 70, 101, 116, 99, 104, 101, 114, 116, 0, 12, 70, 101, 116, 99, 104, 101, 114, 46, 106, 97, 118, 97, 116, 0, 11, 112, 97, 114, 115, 101, 82, 101, 99, 111, 114, 100, 115, 113, 0, 126, 0, 16, 0, 0, 0, 124, 113, 0, 126, 0, 28, 113, 0, 126, 0, 29, 116, 0, 11, 97, 99, 99, 101, 115, 115, 36, 51, 54, 48, 48, 115, 113, 0, 126, 0, 16, 0, 0, 5, -44, 116, 0, 68, 111, 114, 103, 46, 97, 112, 97, 99, 104, 101, 46, 107, 97, 102, 107, 97, 46, 99, 108, 105, 101, 110, 116, 115, 46, 99, 111, 110, 115, 117, 109, 101, 114, 46, 105, 110, 116, 101, 114, 110, 97, 108, 115, 46, 70, 101, 116, 99, 104, 101, 114, 36, 80, 97, 114, 116, 105, 116, 105, 111, 110, 82, 101, 99, 111, 114, 100, 115, 113, 0, 126, 0, 29, 116, 0, 12, 102, 101, 116, 99, 104, 82, 101, 99, 111, 114, 100, 115, 115, 113, 0, 126, 0, 16, 0, 0, 5, 52, 113, 0, 126, 0, 34, 113, 0, 126, 0, 29, 116, 0, 11, 97, 99, 99, 101, 115, 115, 36, 49, 54, 48, 48, 115, 113, 0, 126, 0, 16, 0, 0, 2, -123, 113, 0, 126, 0, 28, 113, 0, 126, 0, 29, 113, 0, 126, 0, 35, 115, 113, 0, 126, 0, 16, 0, 0, 2, 94, 113, 0, 126, 0, 28, 113, 0, 126, 0, 29, 116, 0, 14, 102, 101, 116, 99, 104, 101, 100, 82, 101, 99, 111, 114, 100, 115, 115, 113, 0, 126, 0, 16, 0, 0, 5, 14, 116, 0, 47, 111, 114, 103, 46, 97, 112, 97, 99, 104, 101, 46, 107, 97, 102, 107, 97, 46, 99, 108, 105, 101, 110, 116, 115, 46, 99, 111, 110, 115, 117, 109, 101, 114, 46, 75, 97, 102, 107, 97, 67, 111, 110, 115, 117, 109, 101, 114, 116, 0, 18, 75, 97, 102, 107, 97, 67, 111, 110, 115, 117, 109, 101, 114, 46, 106, 97, 118, 97, 116, 0, 14, 112, 111, 108, 108, 70, 111, 114, 70, 101, 116, 99, 104, 101, 115, 115, 113, 0, 126, 0, 16, 0, 0, 4, -55, 113, 0, 126, 0, 42, 113, 0, 126, 0, 43, 116, 0, 4, 112, 111, 108, 108, 115, 113, 0, 126, 0, 16, 0, 0, 4, -79, 113, 0, 126, 0, 42, 113, 0, 126, 0, 43, 113, 0, 126, 0, 46, 115, 113, 0, 126, 0, 16, 0, 0, 4, 10, 116, 0, 81, 111, 114, 103, 46, 115, 112, 114, 105, 110, 103, 102, 114, 97, 109, 101, 119, 111, 114, 107, 46, 107, 97, 102, 107, 97, 46, 108, 105, 115, 116, 101, 110, 101, 114, 46, 75, 97, 102, 107, 97, 77, 101, 115, 115, 97, 103, 101, 76, 105, 115, 116, 101, 110, 101, 114, 67, 111, 110, 116, 97, 105, 110, 101, 114, 36, 76, 105, 115, 116, 101, 110, 101, 114, 67, 111, 110, 115, 117, 109, 101, 114, 116, 0, 34, 75, 97, 102, 107, 97, 77, 101, 115, 115, 97, 103, 101, 76, 105, 115, 116, 101, 110, 101, 114, 67, 111, 110, 116, 97, 105, 110, 101, 114, 46, 106, 97, 118, 97, 116, 0, 6, 100, 111, 80, 111, 108, 108, 115, 113, 0, 126, 0, 16, 0, 0, 3, -34, 113, 0, 126, 0, 49, 113, 0, 126, 0, 50, 116, 0, 13, 112, 111, 108, 108, 65, 110, 100, 73, 110, 118, 111, 107, 101, 115, 113, 0, 126, 0, 16, 0, 0, 3, -97, 113, 0, 126, 0, 49, 113, 0, 126, 0, 50, 116, 0, 3, 114, 117, 110, 115, 113, 0, 126, 0, 16, 0, 0, 1, -1, 116, 0, 46, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 99, 111, 110, 99, 117, 114, 114, 101, 110, 116, 46, 69, 120, 101, 99, 117, 116, 111, 114, 115, 36, 82, 117, 110, 110, 97, 98, 108, 101, 65, 100, 97, 112, 116, 101, 114, 116, 0, 14, 69, 120, 101, 99, 117, 116, 111, 114, 115, 46, 106, 97, 118, 97, 116, 0, 4, 99, 97, 108, 108, 115, 113, 0, 126, 0, 16, 0, 0, 1, 10, 116, 0, 31, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 99, 111, 110, 99, 117, 114, 114, 101, 110, 116, 46, 70, 117, 116, 117, 114, 101, 84, 97, 115, 107, 116, 0, 15, 70, 117, 116, 117, 114, 101, 84, 97, 115, 107, 46, 106, 97, 118, 97, 113, 0, 126, 0, 55, 115, 113, 0, 126, 0, 16, 0, 0, 2, -20, 116, 0, 16, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 84, 104, 114, 101, 97, 100, 116, 0, 11, 84, 104, 114, 101, 97, 100, 46, 106, 97, 118, 97, 113, 0, 126, 0, 55, 115, 114, 0, 38, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 67, 111, 108, 108, 101, 99, 116, 105, 111, 110, 115, 36, 85, 110, 109, 111, 100, 105, 102, 105, 97, 98, 108, 101, 76, 105, 115, 116, -4, 15, 37, 49, -75, -20, -114, 16, 2, 0, 1, 76, 0, 4, 108, 105, 115, 116, 113, 0, 126, 0, 10, 120, 114, 0, 44, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 67, 111, 108, 108, 101, 99, 116, 105, 111, 110, 115, 36, 85, 110, 109, 111, 100, 105, 102, 105, 97, 98, 108, 101, 67, 111, 108, 108, 101, 99, 116, 105, 111, 110, 25, 66, 0, -128, -53, 94, -9, 30, 2, 0, 1, 76, 0, 1, 99, 116, 0, 22, 76, 106, 97, 118, 97, 47, 117, 116, 105, 108, 47, 67, 111, 108, 108, 101, 99, 116, 105, 111, 110, 59, 120, 112, 115, 114, 0, 19, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 65, 114, 114, 97, 121, 76, 105, 115, 116, 120, -127, -46, 29, -103, -57, 97, -99, 3, 0, 1, 73, 0, 4, 115, 105, 122, 101, 120, 112, 0, 0, 0, 0, 119, 4, 0, 0, 0, 0, 120, 113, 0, 126, 0, 71, 120, 116, 0, 21, 102, 97, 105, 108, 101, 100, 32, 116, 111, 32, 100, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 117, 113, 0, 126, 0, 14, 0, 0, 0, 17, 115, 113, 0, 126, 0, 16, 0, 0, 0, -28, 113, 0, 126, 0, 25, 113, 0, 126, 0, 26, 116, 0, 24, 100, 101, 115, 101, 114, 105, 97, 108, 105, 122, 97, 116, 105, 111, 110, 69, 120, 99, 101, 112, 116, 105, 111, 110, 115, 113, 0, 126, 0, 16, 0, 0, 0, -53, 113, 0, 126, 0, 25, 113, 0, 126, 0, 26, 113, 0, 126, 0, 20, 115, 113, 0, 126, 0, 16, 0, 0, 4, -12, 113, 0, 126, 0, 28, 113, 0, 126, 0, 29, 113, 0, 126, 0, 30, 115, 113, 0, 126, 0, 16, 0, 0, 0, 124, 113, 0, 126, 0, 28, 113, 0, 126, 0, 29, 113, 0, 126, 0, 32, 115, 113, 0, 126, 0, 16, 0, 0, 5, -44, 113, 0, 126, 0, 34, 113, 0, 126, 0, 29, 113, 0, 126, 0, 35, 115, 113, 0, 126, 0, 16, 0, 0, 5, 52, 113, 0, 126, 0, 34, 113, 0, 126, 0, 29, 113, 0, 126, 0, 37, 115, 113, 0, 126, 0, 16, 0, 0, 2, -123, 113, 0, 126, 0, 28, 113, 0, 126, 0, 29, 113, 0, 126, 0, 35, 115, 113, 0, 126, 0, 16, 0, 0, 2, 94, 113, 0, 126, 0, 28, 113, 0, 126, 0, 29, 113, 0, 126, 0, 40, 115, 113, 0, 126, 0, 16, 0, 0, 5, 14, 113, 0, 126, 0, 42, 113, 0, 126, 0, 43, 113, 0, 126, 0, 44, 115, 113, 0, 126, 0, 16, 0, 0, 4, -55, 113, 0, 126, 0, 42, 113, 0, 126, 0, 43, 113, 0, 126, 0, 46, 115, 113, 0, 126, 0, 16, 0, 0, 4, -79, 113, 0, 126, 0, 42, 113, 0, 126, 0, 43, 113, 0, 126, 0, 46, 115, 113, 0, 126, 0, 16, 0, 0, 4, 10, 113, 0, 126, 0, 49, 113, 0, 126, 0, 50, 113, 0, 126, 0, 51, 115, 113, 0, 126, 0, 16, 0, 0, 3, -34, 113, 0, 126, 0, 49, 113, 0, 126, 0, 50, 113, 0, 126, 0, 53, 115, 113, 0, 126, 0, 16, 0, 0, 3, -97, 113, 0, 126, 0, 49, 113, 0, 126, 0, 50, 113, 0, 126, 0, 55, 115, 113, 0, 126, 0, 16, 0, 0, 1, -1, 113, 0, 126, 0, 57, 113, 0, 126, 0, 58, 113, 0, 126, 0, 59, 115, 113, 0, 126, 0, 16, 0, 0, 1, 10, 113, 0, 126, 0, 61, 113, 0, 126, 0, 62, 113, 0, 126, 0, 55, 115, 113, 0, 126, 0, 16, 0, 0, 2, -20, 113, 0, 126, 0, 64, 113, 0, 126, 0, 65, 113, 0, 126, 0, 55, 113, 0, 126, 0, 69, 120, 0, 117, 114, 0, 2, 91, 66, -84, -13, 23, -8, 6, 8, 84, -32, 2, 0, 0, 120, 112, 0, 0, 0, 3, 102, 111, 111])], isReadOnly = false), key = null, value = null)

org.springframework.kafka.listener.ListenerExecutionFailedException: Listener failed; nested exception is org.springframework.kafka.support.serializer.DeserializationException: failed to deserialize; nested exception is java.lang.RuntimeException: Always fails
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.decorateException(KafkaMessageListenerContainer.java:1777) [spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeErrorHandler(KafkaMessageListenerContainer.java:1766) [spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeRecordListener(KafkaMessageListenerContainer.java:1679) [spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeWithRecords(KafkaMessageListenerContainer.java:1605) [spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeRecordListener(KafkaMessageListenerContainer.java:1510) [spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeListener(KafkaMessageListenerContainer.java:1257) [spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.pollAndInvoke(KafkaMessageListenerContainer.java:1007) [spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:927) [spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_212]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_212]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_212]
Caused by: org.springframework.kafka.support.serializer.DeserializationException: failed to deserialize; nested exception is java.lang.RuntimeException: Always fails
    at org.springframework.kafka.support.serializer.ErrorHandlingDeserializer2.deserializationException(ErrorHandlingDeserializer2.java:228) ~[spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    at org.springframework.kafka.support.serializer.ErrorHandlingDeserializer2.deserialize(ErrorHandlingDeserializer2.java:203) ~[spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    at org.apache.kafka.clients.consumer.internals.Fetcher.parseRecord(Fetcher.java:1268) ~[kafka-clients-2.3.1.jar:na]
    at org.apache.kafka.clients.consumer.internals.Fetcher.access$3600(Fetcher.java:124) ~[kafka-clients-2.3.1.jar:na]
    at org.apache.kafka.clients.consumer.internals.Fetcher$PartitionRecords.fetchRecords(Fetcher.java:1492) ~[kafka-clients-2.3.1.jar:na]
    at org.apache.kafka.clients.consumer.internals.Fetcher$PartitionRecords.access$1600(Fetcher.java:1332) ~[kafka-clients-2.3.1.jar:na]
    at org.apache.kafka.clients.consumer.internals.Fetcher.fetchRecords(Fetcher.java:645) ~[kafka-clients-2.3.1.jar:na]
    at org.apache.kafka.clients.consumer.internals.Fetcher.fetchedRecords(Fetcher.java:606) ~[kafka-clients-2.3.1.jar:na]
    at org.apache.kafka.clients.consumer.KafkaConsumer.pollForFetches(KafkaConsumer.java:1294) ~[kafka-clients-2.3.1.jar:na]
    at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:1225) ~[kafka-clients-2.3.1.jar:na]
    at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:1201) ~[kafka-clients-2.3.1.jar:na]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doPoll(KafkaMessageListenerContainer.java:1034) [spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.pollAndInvoke(KafkaMessageListenerContainer.java:990) [spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    ... 4 common frames omitted
Caused by: java.lang.RuntimeException: Always fails
    at com.example.demo.MyBadDeserializer.deserialize(MyBadDeserializer.java:31) ~[classes/:na]
    at org.apache.kafka.common.serialization.Deserializer.deserialize(Deserializer.java:60) ~[kafka-clients-2.3.1.jar:na]
    at org.springframework.kafka.support.serializer.ErrorHandlingDeserializer2.deserialize(ErrorHandlingDeserializer2.java:200) ~[spring-kafka-2.3.6.RELEASE.jar:2.3.6.RELEASE]
    ... 15 common frames omitted
Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Thanks. I have come across that, but I am not sure how it can be used. Do you happen to have an example of how it can be used or maybe a test class or something to show that better in action? – Ali Mar 24 '20 at 21:53
  • The documentation I pointed you to shows how to configure it; what part of that don't you understand? The properties can be added to the consumer binding properties. – Gary Russell Mar 24 '20 at 21:55
  • Since we are using Spring Cloud Stream, most of the mentioned classes have been kept hidden from us, so I was hoping to have an example to be mostly based on Spring Cloud Stream and it's Kafka binder. I guess I need to dig in Spring Cloud Stream source code to see how that can be used in action – Ali Mar 24 '20 at 22:01
  • 1
    I added an example. – Gary Russell Mar 24 '20 at 22:21
  • So to ensure I've understood this correctly, the `ErrorHandlingDeserializer2` is being used as the deserializer, when there is no deserialization exception it routes it to the predefined deserializer (`io.confluent.kafka.serializers.KafkaAvroDeserializer` as we are using native decoding) if there is an exception it is being routed to `MyBadDeserializer` where I can catch the exception to whatever approach I'd like to have. The part I don't understand is how I can expect that `ErrorHandlingDeserializer2` knows `io.confluent.kafka.serializers.KafkaAvroDeserializer` is being used? – Ali Mar 25 '20 at 00:12
  • No; not at all; I was just providing a generic example of using the EHD2 with a deserializer that might fail. In your case you should point the `spring.cloud.stream.kafka.bindings.input.consumer.configuration.spring.deserializer.value.delegate.class=` to your avro deserializer. When the avro deserializer fails, the exception will go straight to the error handler. – Gary Russell Mar 25 '20 at 01:06
  • I see. And I guess the exception has been caught in the io.confluent.kafka.serializers.KafkaAvroDeserializer which then is going to be collected by errorChannel and published to dlq, right? – Ali Mar 25 '20 at 01:34
  • 1
    No; the EHD2 catches the exception thrown by the avro deserializer. Read my answer; the failed record will NOT be sent to a DLQ by default, it will simply be logged. "... (which will just just log the error, by default). You can use a ListenerContainerCustomizer bean...". This is not hard; just read the answer carefully. – Gary Russell Mar 25 '20 at 02:06
  • @GaryRussell so can I remove ```spring.cloud.stream.kafka.bindings.input.consumer.configuration.value.deserializer=io.confluent.kafka.serializers.KafkaAvroDeserializer``` if I replace with the ```spring.cloud.stream.kafka.bindings.input.consumer.configuration.spring.deserializer.value.delegate.class=``` or do I need both of them? – Beez Oct 29 '20 at 19:47
  • 1
    The `...value.deserializer` property has to be set to the `ErrorHandlingDeserializer` class name (tells Kafka what to call) and the `...delegate.class` is configuration for the EHD to tell it which actual deserializer to use. – Gary Russell Oct 29 '20 at 19:57