Schema-registry: Schema registry should not include classes in the org.apache.avro package

Created on 29 Apr 2020  路  24Comments  路  Source: confluentinc/schema-registry

I noticed that the latest release 5.5.0 includes a class that crosses with the default Apache Avro package names. This should be changed to avoid potential conflicts with upstream Avro but also to avoid potential issues for the schema-regsitry client with Java 11.

Pinging @rayokota since git says is the author.

https://github.com/confluentinc/schema-registry/blob/master/client/src/main/java/org/apache/avro/Schemas.java

Most helpful comment

All 24 comments

Thanks @iemejia , I'll submit a small PR to Avro to get this added to 1.10.0.

Thanks for bringing this feature to upstream Avro, I think it makes somehow sense but let's see with the rest of the community, let's follow the discussion on the contribution there.

In the meantime I strongly recommend you to put the Schemas class inside of the io.confluent.kafka.schemaregistry.avro package since you only use it there and make it package private (remove the public keyword everywhere) to reduce API exposure.

@iemejia , it is currently in the org.apache.avro namespace because it is accessing a package-private method of Schema.

Oh I haven't noticed that, you could have addressed this by Reflection somehow to avoid no?

I also found an exception in the tests of other project I work in with the upgrade, not sure yet if it is related to this access detail but in that project we use Avro 1.8.2 and only by changing the version to this latest one it breaks with this exception (It used to work well with version 5.3.x).

java.lang.NoSuchFieldError: FACTORY
    at org.apache.avro.Schemas.toString(Schemas.java:36)
    at org.apache.avro.Schemas.toString(Schemas.java:30)
    at io.confluent.kafka.schemaregistry.avro.AvroSchema.canonicalString(AvroSchema.java:136)
    at io.confluent.kafka.schemaregistry.client.MockSchemaRegistryClient.getSchemaMetadata(MockSchemaRegistryClient.java:299)
    at io.confluent.kafka.schemaregistry.client.MockSchemaRegistryClient.getLatestSchemaMetadata(MockSchemaRegistryClient.java:311)

If you have any idea of what could have gone wrong that would be appreciated, I still need to dig deeper.

I think reflection will also break if Java Modules is ever used, which is why I submitted the PR to expose a proper method in Avro 1.10.0 :)

As for your error, FACTORY is also package-private in org.apache.avro, perhaps that is causing issues for you.

I'm currently seeing the same error as noted above at runtime using avro 1.8.2 after upgrading to kafka-streams-avro-serde 5.5.

Schema Registry uses Avro 1.9

https://github.com/confluentinc/common/blob/master/pom.xml#L48

Does this means that confluent schema-registry is not working with Avro Version < 1.9?

@imalik8088 Why wouldn't it? Did you try it? There's no significant breaking changes in Avro library between 1.8 and 1.9 (or 1.10)

When using Avro 1.8.2 I'm getting the following exception:

Exception in thread "main" java.lang.NoSuchFieldError: FACTORY
    at org.apache.avro.Schemas.toString(Schemas.java:36)
    at org.apache.avro.Schemas.toString(Schemas.java:30)
    at io.confluent.kafka.schemaregistry.avro.AvroSchema.canonicalString(AvroSchema.java:136)
    at io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient.registerAndGetId(CachedSchemaRegistryClient.java:206)
    at io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient.register(CachedSchemaRegistryClient.java:268)
    at io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient.register(CachedSchemaRegistryClient.java:244)
    at io.confluent.kafka.serializers.AbstractKafkaAvroSerializer.serializeImpl(AbstractKafkaAvroSerializer.java:74)
    at io.confluent.kafka.serializers.KafkaAvroSerializer.serialize(KafkaAvroSerializer.java:58)
    at org.apache.kafka.common.serialization.Serializer.serialize(Serializer.java:62)
    at org.apache.kafka.clients.producer.KafkaProducer.doSend(KafkaProducer.java:902)
    at org.apache.kafka.clients.producer.KafkaProducer.send(KafkaProducer.java:862)
    at io.github.imalik8088.clients.AvroProducer.main(AvroProducer.java:51)

here is the working example with avro 1.9.2 when I'm switching to 1.8.2 in the parent pom it gets this exception

@rayokota Avro 1.10.0 is out with your fix included so maybe worth to upgrade to fix the multi package issue.

When using Avro 1.8.2

Not clear how/why you're using 1.8.2 when 1.9.2 is pulled as part of kafka-avro-serializer:5.5.0

Ah ok, I see that avro dependency is already included. thanks for pointing out, so the explicit dependency in my pom.xml for Avro isn't necessary.

Thanks @iemejia , I'll probably wait until Confluent Platform is ready to upgrade to Jackson 2.11.0.

i am getting the same error 'java.lang.NoSuchFieldError: FACTORY', i am using kafka-avro-serializer:5.5.0, and have removed dependency on org.apache.avro from build, but the issue still exists. I would really appreciate any help on how to fix the issue.

Here is the list of dependencies i am using:
org.apache.hadoop:hadoop-hdfs:3.2.1
org.apache.hadoop:hadoop-aws:3.2.1
org.apache.spark:spark-core_2.12:2.4.4
org.apache.spark:spark-sql_2.12:2.4.4
org.apache.spark:spark-yarn_2.12:2.4.4
org.apache.spark:spark-streaming_2.12:2.4.4
org.apache.spark:spark-streaming-kafka-0-10_2.12:2.4.4
org.apache.spark:spark-sql-kafka-0-10_2.12:2.4.4
org.apache.spark:spark-avro_2.12:2.4.4
io.confluent:kafka-schema-registry-client:5.5.0
io.confluent:kafka-avro-serializer:5.5.0
org.apache.kafka:kafka-clients:5.5.0-ccs

@jessiedanwang spark-avro_2.12 includes a lower version of Avro, and hadoop-hdfs might as well

@OneCricketeer thanks for pointing it out, i was suspecting some dependencies are causing the issue, what would be fix then?

also, i am not seeing dependency of spark-avro_2.12:2.4.4 on avro here https://mvnrepository.com/artifact/org.apache.spark/spark-avro_2.12/2.4.4

ok, i find out that it is spark-core_2.12:2.4.4 that has dependency on avro 1.8.2, is there a way to force using avro 1.9.2?

Maven enforces a "closest" dependency chain, so if you first explicitly declare a Avro version, that's what should be used, however, no guarantee that won't break something within Spark as it uses an older version...

If you just want to use Avro and Spark, I'd suggest looking at the Abris library on Github

@OneCricketeer thanks for reply. I have tried first explicitly avro version of 1.9.2, however, i am still getting 'java.lang.NoSuchFieldError: FACTORY'. Looking at Abris library on Github, it is using confluent 5.3.1 which depends on avro 1.8.1, and Abris also includes avro 1.9.2 as well, so i think it is likely to run into same NoSuchFieldError. It is probably better to just use kafka avro serializer 5.3.1 instead of 5.5.0 so that there is no version conflict on avro

Did anyone find the solution . I tried using the abris latest version which is using confluent 5.5.1 and Avro 1.9.2 but still stuck with same issue while use this lib . There is reference of avro 1.8.2 in spark sql that i am using Exception in thread "main"

java.lang.NoSuchFieldError: FACTORY
at org.apache.avro.Schemas.toString(Schemas.java:36)
at org.apache.avro.Schemas.toString(Schemas.java:30)
at io.confluent.kafka.schemaregistry.avro.AvroSchema.canonicalString(AvroSchema.java:140)
at io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient.registerAndGetId(CachedSchemaRegistryClient.java:206)
at io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient.register(CachedSchemaRegistryClient.java:268)
at io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient.register(CachedSchemaRegistryClient.java:244)
at io.confluent.kafka.schemaregistry.client.SchemaRegistryClient.register(SchemaRegistryClient.java:42)

Abris developer here.

@OneCricketeer > @imalik8088 Why wouldn't it? Did you try it? There's no significant breaking changes in Avro library between 1.8 and 1.9 (or 1.10)

There is a hidden breaking change between Avro 1.8 and 1.9. The FACTORY field in Schema class has different type:

1.8.2  org.codehaus.jackson.JsonFactory
1.9.2  com.fasterxml.jackson.core.JsonFactory

This explains the java.lang.NoSuchFieldError: FACTORY Error.

As far as I know this makes schema registry 5.4.x+ incompatible with Spark (because Spark uses Avro 1.8.x)

So if you depend on Avro 1.8 the safe way is to stick with schema registry 5.3.x for now.

Was this page helpful?
0 / 5 - 0 ratings