You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@avro.apache.org by "Stefan Burkard (Jira)" <ji...@apache.org> on 2023/11/20 09:32:00 UTC
[jira] [Commented] (AVRO-2902) ClassCastException in generated Java classes when used in OSGi
[ https://issues.apache.org/jira/browse/AVRO-2902?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17787902#comment-17787902 ]
Stefan Burkard commented on AVRO-2902:
--------------------------------------
I don't think this is OSGi specific. I have almost the same exception but in a SpringBoot consumer.
{code:java}
Caused by: java.lang.ClassCastException: class org.apache.avro.util.Utf8 cannot be cast to class java.util.UUID (org.apache.avro.util.Utf8 is in unnamed module of loader 'app'; java.util.UUID is in module java.base of loader 'bootstrap') {code}
The cause of the problem is a minor update of {{io.confluent:kafka-streams-avro-serde}} (which contains {{io.confluent:kafka-avro-serializer}} of the same version) in the consumer from 7.4.x to 7.5 while the producer still uses version 7.4.x
When I produce a message (that contains UUIDs), the consumer throws this deserialization exception.
> ClassCastException in generated Java classes when used in OSGi
> --------------------------------------------------------------
>
> Key: AVRO-2902
> URL: https://issues.apache.org/jira/browse/AVRO-2902
> Project: Apache Avro
> Issue Type: Bug
> Components: compatibility, logical types, tools
> Affects Versions: 1.9.2
> Environment: Karaf 4.2.8, 4.2.9
> Reporter: Ivan A. Malich
> Priority: Minor
>
> Example schema:
> {code:java}
> {
> "name": "ClientOrder",
> "type": "record",
> "namespace": "biz.sanwell.it.kafka.avsc",
> "version":"1",
> "fields": [
> { "name": "id", "type": { "type": "string", "logicalType": "uuid" } },
> { "name": "name", "type": [ "null", "string" ], "default": null },
> { "name": "creationDate", "type": { "type": "long", "logicalType": "timestamp-millis" } },
> { "name": "orderStatus", "type": { "type": "string", "logicalType": "uuid" }, "default": "6c311f46-b55b-11ea-b3de-0242ac130004" }
> ]
> }
> {code}
>
> Generated by {{avro-maven-plugin}} POJO fragment:
> {code:java}
> ...
> @Override
> @SuppressWarnings("unchecked")
> public ClientOrder build() {
> try {
> ClientOrder record = new ClientOrder();
> record.id = fieldSetFlags()[0] ? this.id : (java.util.UUID) defaultValue(fields()[0]);
> record.name = fieldSetFlags()[1] ? this.name : (java.lang.String) defaultValue(fields()[1]);
> record.creationDate = fieldSetFlags()[2] ? this.creationDate : (java.time.Instant) defaultValue(fields()[2]);
> record.orderStatus = fieldSetFlags()[3] ? this.orderStatus : (java.util.UUID) defaultValue(fields()[3]); //this line causes exception
> ...
> {code}
>
> Example code causing exception:
> {code:java}
> public class TestRunner implements BundleActivator {
> @Override
> public void start(BundleContext context) throws Exception {
> ClientOrder clientOrder = ClientOrder.newBuilder()
> .setId(UUID.randomUUID())
> .setCreationDate(Instant.now())
> .build(); //this line causes exception
> System.out.println(clientOrder.toString());
> }
> {code}
>
> Exception:
> {{...}}
> {{Error starting bundle 251: Activator start error in bundle biz.sanwell.it.kafka.sw-kafka-avro-schemas [251].}}
> {{...}}
> {{Caused by: org.apache.avro.AvroRuntimeException: java.lang.ClassCastException: class org.apache.avro.util.Utf8 cannot be cast to class java.util.UUID (org.apache.avro.util.Utf8 is in unnamed module of loader org.apache.felix.framework.BundleWiringImpl$BundleClassLoader @7579319f; java.util.UUID is in module java.base of loader 'bootstrap')}}
>
> Default values for UUID fields internally stored as Utf8 cannot be cast to UUID.
> AFAIU the problem comes from the fact that in OSGi environment classes {{org.apache.avro.util.Utf8}} and {{java.util.UUID}} are loaded by separate classloaders thus simple class casting cannot be done.
>
> To bypass the problem I changed
> {code:java}
> record.orderStatus = fieldSetFlags()[3] ? this.orderStatus : (java.util.UUID) defaultValue(fields()[3]);
> {code}
> to
> {code:java}
> record.orderStatus = fieldSetFlags()[3] ? this.orderStatus : java.util.UUID.fromString(defaultValue(fields()[3]).toString());
> {code}
> but I think maybe that could be done during class generation?
>
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)