Håkan Lantz created CAMEL-22625:
-----------------------------------

             Summary: AvroDataFormat unmarshal fails for union with logicalType
                 Key: CAMEL-22625
                 URL: https://issues.apache.org/jira/browse/CAMEL-22625
             Project: Camel
          Issue Type: Bug
          Components: camel-avro
    Affects Versions: 4.14.1
            Reporter: Håkan Lantz
         Attachments: DateRecord-1.avsc, DateRecordTest.java

When using optional logical types in avro for dates and time stamps unmarshal 
fails with exception:
{noformat}
ClassCastException: class java.lang.Integer cannot be cast to class 
java.time.LocalDate (java.lang.Integer and java.time.LocalDate are in module 
java.base of loader 'bootstrap')
{noformat}

Here is a sample avro schema that illustrates that:

{code:json}
{
  "type": "record",
  "name": "DateRecord",
  "namespace": "se.replyto.avro.test",
  "fields": [
    {
      "name": "date",
      "type": [
        "null",
        {
          "type": "int",
          "logicalType": "date"
        }
      ],
      "default": null
    },
    {
      "name": "timestamp",
      "type": [
        "null",
        {
          "type": "long",
          "logicalType": "timestamp-millis"
        }
      ],
      "default": null
    }
  ]
}
{code}

This can be reproduced by generating the DateRecord class using the maven 
avro-maven-plugin and try it with the following sample route builder:
{code:java}
AvroDataFormat avroDataFormat = new AvroDataFormat(DateRecord.SCHEMA$);
avroDataFormat.setInstanceClassName(DateRecord.class.getName());

from("direct:unmarshal")
    .unmarshal(avroDataFormat).id("avro-unmarshal")
    .to("mock:unmarshaled");
{code}

A fix for this is to override the unmarshal method and create a 
SpecificDatumReader for the instanceClassName instead of creating it from a 
SpecificData using the class loader of the avro schema.
{code:java}
AvroDataFormat avroDataFormat = new AvroDataFormat(DateRecord.SCHEMA$) {
    @Override
    public Object unmarshal(Exchange exchange, InputStream inputStream) throws 
Exception {
        String instanceClassName = getInstanceClassName();

        if ( null != instanceClassName) {
            Class<?> clazz = Class.forName(instanceClassName);
            if (null != clazz) {
                Decoder decoder = 
DecoderFactory.get().binaryDecoder(inputStream, null);
                DatumReader<?> reader = new SpecificDatumReader<>(clazz);
                return reader.read(null, decoder);
            }
        }

        return super.unmarshal(exchange, inputStream);
    }
};
{code}




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

Reply via email to