[
https://issues.apache.org/jira/browse/AVRO-3186?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17424444#comment-17424444
]
ASF subversion and git services commented on AVRO-3186:
-------------------------------------------------------
Commit 00a4f5c486baf2876bb0aaa3d1978285f0cf1d0a in avro's branch
refs/heads/master from Yubao Liu
[ https://gitbox.apache.org/repos/asf?p=avro.git;h=00a4f5c ]
AVRO-3186: Use consistent logic to find SpecificData by class (#1304)
SpecificDatumReader.SpecificDatumReader(Schema writer, Schema reader)
-> SpecificData.getForSchema(reader)
// It breaks if system class loader fails to load generated class,
// thus returns an empty SpecificData.
SpecificDatumReader.readField()
-> datum = readWithoutConversion(oldDatum, field.schema(), in);
// conversion is null for union field
-> GenericDatumReader.read(Object old, Schema expected, ResolvingDecoder in)
-> Conversion<?> conversion = getData().getConversionFor(logicalType);
// returns null wrongly
Without this patch, the unit test fails:
java.lang.ClassCastException: class java.lang.Long cannot be cast to class
java.time.Instant (java.lang.Long and java.time.Instant are in module java.base
of loader 'bootstrap')
at foo.Bar.put(Bar.java:113)
at org.apache.avro.generic.GenericData.setField(GenericData.java:826)
at
org.apache.avro.specific.SpecificDatumReader.readField(SpecificDatumReader.java:139)
at
org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:247)
at
org.apache.avro.specific.SpecificDatumReader.readRecord(SpecificDatumReader.java:123)
at
org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:179)
at
org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:160)
at
org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:153)
at
org.apache.avro.specific.TestSpecificData$1.run(TestSpecificData.java:75)
The separate class loader scenario probably happens in OSGi module and Java 9
module too.
> Java: Avro can't decode union<null, logicalType> field of a record
> -------------------------------------------------------------------
>
> Key: AVRO-3186
> URL: https://issues.apache.org/jira/browse/AVRO-3186
> Project: Apache Avro
> Issue Type: Bug
> Components: java
> Affects Versions: 1.10.2
> Environment: JDK 11, macOS.
> Reporter: Yubao Liu
> Priority: Critical
> Labels: pull-request-available
> Fix For: 1.11.0
>
> Time Spent: 40m
> Remaining Estimate: 0h
>
> [https://github.com/apache/avro/blob/release-1.10.2/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java#L163]
> {code:java}
> protected Object read(Object old, Schema expected, ResolvingDecoder in)
> throws IOException {
> Object datum = readWithoutConversion(old, expected, in);
> LogicalType logicalType = expected.getLogicalType();
> if (logicalType != null) {
> Conversion<?> conversion = getData().getConversionFor(logicalType); //
> <---- bad
> if (conversion != null) {
> return convert(datum, expected, logicalType, conversion);
> }
> }
> return datum;
> }
> {code}
>
> For a logic type field in a union, getData().getConversionFor(logicalType)
> returns null, the cause is SpecificData.getForSchema() isn't compatible with
> JDK >= 9, it can't depend on Class.forName() to load user class.
> [https://github.com/apache/avro/blob/release-1.10.2/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java#L147]
> {code:java}
> diff --git
> a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java
> b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java
> index 58bc660b..33fc3418 100644
> --- a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java
> +++ b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java
> @@ -140,15 +140,9 @@ public class SpecificData extends GenericData {
> */
> public static SpecificData getForSchema(Schema reader) {
> if (reader != null && reader.getType() == Type.RECORD) {
> - final String className = getClassName(reader);
> - if (className != null) {
> - final Class<?> clazz;
> - try {
> - clazz = Class.forName(className);
> - return getForClass(clazz);
> - } catch (ClassNotFoundException e) {
> - return SpecificData.get();
> - }
> + final Class<?> clazz = SpecificData.get().getClass(reader);
> + if (clazz != null) {
> + return getForClass(clazz);
> }
> }
> return SpecificData.get();
> {code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)