[ 
https://issues.apache.org/jira/browse/AVRO-3989?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17939459#comment-17939459
 ] 

Harshit Mittal edited comment on AVRO-3989 at 3/30/25 5:59 AM:
---------------------------------------------------------------

While this bug is annoying, I am able to figure out a work around for this. The 
fix is to use {{new SpecificDatumReader<>(AvroPojo.class)}} instead of {{new 
ReflectDatumReader<>(AvroPojo.class)}} or 
{{SpecificData.get().createDatumReader(AvroPojo.class)}}.

 

Similarly for serialization, we need to use {{SpecificDatumWritier}} directly.

This creates a new instance of {{SpecificData}} from {{MODEL$}} static member 
of the class that correctly handles logical type within a union field.

In fact, avro sourcecode seems to suggest this as the right fix per this 
unit-test - 
[TestSpecificData.java|https://github.com/apache/avro/blob/main/lang/java/compiler/src/test/java/org/apache/avro/specific/TestSpecificData.java]


was (Author: hmittal83):
While this bug is annoying, I am able to figure out a work around for this. The 
fix is to use `new SpecificDatumReader<>(AvroPojo.class)` instead of `new 
ReflectDatumReader<>(AvroPojo.class)` or 
`SpecificData.get().createDatumReader(AvroPojo.class)`.

 

Similarly for serialization, we need to use `SpecificDatumWritier` directly.

This creates a new instance of `SpecificData` from `MODEL$` static member of 
the class that correctly handles logical type within a union field.

> Schema conversion for logical types ignored when type is part of union
> ----------------------------------------------------------------------
>
>                 Key: AVRO-3989
>                 URL: https://issues.apache.org/jira/browse/AVRO-3989
>             Project: Apache Avro
>          Issue Type: Bug
>          Components: java
>    Affects Versions: 1.11.3
>            Reporter: Jacob Stampe Mikkelsen
>            Priority: Major
>         Attachments: image-2024-06-02-21-32-25-461.png
>
>
> I have a schema with an optional timestamp which is to be rendered as millis 
> and the generated Java class fails to get the conversions array and method 
> added, which means that at runtime I get a ClassCastException when an 
> "Instant" object is cast to a "Long" because there was no registered 
> converter:
> The element with an optional timestamp in my schema:
> {{{}}
> {{  "name": "DecisionStartTime",}}
> {{  "type": [}}
> {{    "null",}}
> {{    {}}
> {{      "type": "long",}}
> {{      "logicalType": "timestamp-millis"}}
> {{    }}}
> {{  ],}}
> {{  "default": null}}
> {{}}}
> The problem seems to be here:
> [https://github.com/apache/avro/blame/5a60b5c43fe9c3bb40f4a1303913fdb3598bd4a5/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm#L198]
> Which only renders the conversion part if any of the fields has logicalType 
> set and the actual method:
> [https://github.com/apache/avro/blob/5a60b5c43fe9c3bb40f4a1303913fdb3598bd4a5/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java#L976C3-L983C4]
> Does not take into account that a field which is a union does not have a 
> logical type, however one of the union types might.
> *Proposed solution* - replace method
> {{  public boolean hasLogicalTypeField(Schema schema) {}}
> {{    for (Schema.Field field : schema.getFields()) {}}
> {{      if (field.schema().getLogicalType() != null) {}}
> {{        return true;}}
> {{      }}}
> {{    }}}
> {{    return false;}}
> {{  }}}
> With a method like this:
> {{  public boolean hasLogicalTypeField(Schema schema) {}}
> {{    for (Schema.Field field : schema.getFields()) {}}
> {{      if (field.schema().getLogicalType() != null) {}}
> {{        return true;}}
> {{      } else if (field.schema().type == Type.UNION) {}}
> {{        for (Schema type : field.schema().getTypes()) {}}
> {{          if (type.getLogicalType() != null) {}}
> {{            return true;}}
> {{          }}}
> {{        }}}
> {{      }}}
> {{    }}}
> {{    return false;}}
> {{  }}}
> The conversionInstance() method might also need tweaking in order to identify 
> that the given type has a logical type as part of the union.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to