Skip to content

Wrong Serdes for different binders #2543

Description

@fabiofilz

Hi,

We are migrating from AVRO to Proto so we have some topics using Avro and other Proto.

I am trying to use a function that has 2 parameters as input: the first one is AVRO and second is Proto and the output is Avro.

When I try to run the application tries to deserialise the Avro event using Proto Serdes.

Please find below the configuration:

`

application.yml

spring:
cloud:
stream:
function:
definition: processTopicEventProto;processTopicEventAvro

  binders:
    kstream-proto:
      type: kstream
      environment:
        spring.cloud.stream.kafka.streams.binder:
          brokers: localhost:9092
          configuration:
            default.value.serde: io.confluent.kafka.streams.serdes.protobuf.KafkaProtobufSerde
            schema.registry.url: http://localhost:8081
            derive.type: true

    kstream-avro:
      type: kstream
      environment:
        spring.cloud.stream.kafka.streams.binder:
          brokers: localhost:9092
          configuration:
            specific.avro.reader: true
            default.value.serde: io.confluent.kafka.streams.serdes.avro.SpecificAvroSerde
            schema.registry.url: http://localhost:8081

    globalktable:
      type: globalktable
      environment:
        spring.cloud.stream.kafka.streams.binder:
          brokers: localhost:9092
          configuration:
            default.value.serde: io.confluent.kafka.streams.serdes.protobuf.KafkaProtobufSerde
            schema.registry.url: http://localhost:8081
            derive.type: true

    processTopicEventProto-in-0:
      destination: topicEvent.proto
      binder: kstream-proto
      contentType: application/x-protobuf
    processTopicEventProto-in-1:
      destination: consent.proto
      binder: globalktable
      contentType: application/x-protobuf
    processTopicEventProto-out-0:
      destination: filteredTopicEvent.proto
      binder: kstream-proto
      contentType: application/x-protobuf

    processTopicEventAvro-in-0:
      destination: topicEvent.avro
      binder: kstream-avro
    processTopicEventAvro-in-1:
      destination: consent.proto
      binder: globalktable
    processTopicEventAvro-out-0:
      destination: filteredTopicEvent.avro
      binder: kstream-avro

  kafka:
    streams:
      binder:
        deserialization-exception-handler: sendtodlq
        functions:
          processTopicEventProto.applicationId: service-processTopicEventProto
          processTopicEventAvro.applicationId: service-processTopicEventAvro
        configuration:
          state.dir: state-store
          acceptable.recovery.lag: 0

Topology

@Bean
public BiFunction<KStream<String, SpecificRecord>, GlobalKTable<String, CustomerConsentProto.CustomerConsent>, KStream<String, SpecificRecord>> processTopicEventAvro() {

    return (stream, table) -> (
        stream
            .peek((key, value) -> log.info("Received event key={} value={}", key, value.toString()))
            .leftJoin(table, (key, value) -> key, (streamRecord, tableRecord) -> {
                if (tableRecord == null){
                    return streamRecord;
                }
                return null;
            } )
            .filter((key, value) -> Optional.ofNullable(value).isPresent())
            .peek((key, value) -> log.info("The Event customerId={} will go to the output", key))
    );
}


@Bean
public BiFunction<KStream<String, com.google.protobuf.Message>, GlobalKTable<String, CustomerConsentProto.CustomerConsent>, KStream<String, com.google.protobuf.Message>> processTopicEventProto() {

    return (stream, table) -> (
            stream
                .peek((key, value) -> log.debug("Received event key={} value={}", key, value.toString()))
                .leftJoin(table, (key, value) -> key, (streamRecord, tableRecord) -> {
                    if (tableRecord == null){
                        return streamRecord;
                    }
                    return null;
                } )
                .filter((key, value) -> Optional.ofNullable(value).isPresent())
                .peek((key, value) -> log.info("The Event customerId={} will go to the output", key))
    );
}

Logs

2022-10-25 15:28:53.568  WARN 44031 --- [-StreamThread-1] o.a.k.s.p.internals.RecordDeserializer   : stream-thread [service-processTopicEventAvro-69ad1666-13ca-4550-8dd4-8a6fc65293d3-StreamThread-1] task [0_2] Skipping record due to deserialization error. topic=[topicEvent.avro] partition=[2] offset=[2669629]

org.apache.kafka.common.errors.SerializationException: Error deserializing Protobuf message for id 744
at io.confluent.kafka.serializers.protobuf.AbstractKafkaProtobufDeserializer.deserialize(AbstractKafkaProtobufDeserializer.java:175) ~[kafka-protobuf-serializer-7.2.1.jar:na]
at io.confluent.kafka.serializers.protobuf.KafkaProtobufDeserializer.deserialize(KafkaProtobufDeserializer.java:76) ~[kafka-protobuf-serializer-7.2.1.jar:na]
at io.confluent.kafka.serializers.protobuf.KafkaProtobufDeserializer.deserialize(KafkaProtobufDeserializer.java:27) ~[kafka-protobuf-serializer-7.2.1.jar:na]
at org.apache.kafka.common.serialization.Deserializer.deserialize(Deserializer.java:60) ~[kafka-clients-3.1.1.jar:na]
at org.apache.kafka.streams.processor.internals.SourceNode.deserializeValue(SourceNode.java:58) ~[kafka-streams-3.1.1.jar:na]
at org.apache.kafka.streams.processor.internals.RecordDeserializer.deserialize(RecordDeserializer.java:66) ~[kafka-streams-3.1.1.jar:na]
at org.apache.kafka.streams.processor.internals.RecordQueue.updateHead(RecordQueue.java:176) ~[kafka-streams-3.1.1.jar:na]
at org.apache.kafka.streams.processor.internals.RecordQueue.addRawRecords(RecordQueue.java:112) ~[kafka-streams-3.1.1.jar:na]
at org.apache.kafka.streams.processor.internals.PartitionGroup.addRawRecords(PartitionGroup.java:304) ~[kafka-streams-3.1.1.jar:na]
at org.apache.kafka.streams.processor.internals.StreamTask.addRecords(StreamTask.java:960) ~[kafka-streams-3.1.1.jar:na]
at org.apache.kafka.streams.processor.internals.TaskManager.addRecordsToTasks(TaskManager.java:1068) ~[kafka-streams-3.1.1.jar:na]
at org.apache.kafka.streams.processor.internals.StreamThread.pollPhase(StreamThread.java:962) ~[kafka-streams-3.1.1.jar:na]
at org.apache.kafka.streams.processor.internals.StreamThread.runOnce(StreamThread.java:751) ~[kafka-streams-3.1.1.jar:na]
at org.apache.kafka.streams.processor.internals.StreamThread.runLoop(StreamThread.java:604) ~[kafka-streams-3.1.1.jar:na]
at org.apache.kafka.streams.processor.internals.StreamThread.run(StreamThread.java:576) ~[kafka-streams-3.1.1.jar:na]
Caused by: java.io.IOException: Invalid schema << IT SHOWS THE AVRO SCHEMA HERE >> with refs [] of type AVRO
at io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient.lambda$getSchemaByIdFromRegistry$6(CachedSchemaRegistryClient.java:305) ~[kafka-schema-registry-client-7.2.1.jar:na]
at java.base/java.util.Optional.orElseThrow(Optional.java:403) ~[na:na]
at io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient.getSchemaByIdFromRegistry(CachedSchemaRegistryClient.java:303) ~[kafka-schema-registry-client-7.2.1.jar:na]
at io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient.getSchemaBySubjectAndId(CachedSchemaRegistryClient.java:417) ~[kafka-schema-registry-client-7.2.1.jar:na]
at io.confluent.kafka.serializers.protobuf.AbstractKafkaProtobufDeserializer.deserialize(AbstractKafkaProtobufDeserializer.java:126) ~[kafka-protobuf-serializer-7.2.1.jar:na]
... 14 common frames omitted

2022-10-25 15:28:53.814 ERROR 44031 --- [-StreamThread-1] i.c.k.s.c.CachedSchemaRegistryClient : Invalid schema type AVRO

Libs

JAVA 17

org.springframework.boot
spring-boot-starter-parent
2.7.5

<spring-cloud.version>2021.0.4</spring-cloud.version>

`

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions