-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Hi,
Following my question on StackOverflow which revealed to be actually a bug :
https://stackoverflow.com/questions/53559944/spring-kafka-2-2-type-mappings-class-loader-mismatch
Here it is again below for reference :
I'm trying to use the new type mappings feature introduced in Spring Kafka 2.2 :
Scroll down to "Mapping Types" :
https://docs.spring.io/spring-kafka/reference/htmlsingle/#serdes
On the producer side, I registered a mapping as follow :
senderProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
senderProps.put(JsonSerializer.TYPE_MAPPINGS, "foo:com.myfoo.Foo");
And on the consumer as follow :
consumerProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class);
consumerProps.put(JsonDeSerializer.TYPE_MAPPINGS, "foo:com.yourfoo.Foo");
However, when sending an event to Kafka on the producer side of the com.myfoo.Foo class, the classId header that is added to the record is com.myfoo.Foo instead of foo. Thus on the consumer side, it fails to deserialize because com.myfoo.Foo is unknown.
I have narrowed the issue down to this method in spring-kafka :
protected void addHeader(Headers headers, String headerName, Class<?> clazz) {
if (this.classIdMapping.containsKey(clazz)) {
headers.add(new RecordHeader(headerName, this.classIdMapping.get(clazz)));
}
else {
headers.add(new RecordHeader(headerName, clazz.getName().getBytes(StandardCharsets.UTF_8)));
}
}
When debugging through the execution of the serialization of a kafka record, the execution actually goes to the else branch, whereas in my understanding it should actually go to the if branch and add foo as a header. Instead it adds com.myfoo.Foo to the header.
The culprit seems to be related to a class loader mismatch but I'm not sure if it's actually a bug or something stupid I did on my end.
Basically, the classIdMapping map is correctly filled with com.myfoo.Foo as a key and the UTF-8 byte[] representation of foo as the corresponding value.
However during the if chec, the clazz parameter is a Class loaded by a different class loader as what was stored in the classIdMapping map, thus the hashcodes are different and it goes to the else branch.
Thanks