Pedro Ribeiro created AVRO-4144:
-----------------------------------

             Summary: Support for Java Records
                 Key: AVRO-4144
                 URL: https://issues.apache.org/jira/browse/AVRO-4144
             Project: Apache Avro
          Issue Type: Improvement
          Components: java
    Affects Versions: 1.12.0, 1.12.1
            Reporter: Pedro Ribeiro


Java Records were introduced in [Java 
14|[https://docs.oracle.com/en/java/javase/14/language/records.html|https://urldefense.com/v3/__https://docs.oracle.com/en/java/javase/14/language/records.html__;!!FrPt2g6CO4Wadw!N9KU6BAQG9WdAkZiXRsrLJdqsAVmjJlenLCFGQ0EV96ormoLu39rzGx643GL2erEqUqmcK1uSKLyZgmH88lF3Qk3cWEi4Q$]].
 They are the default alternative to @Data classes from Lombok, where the 
members are final, with all args constructor, and the toString, equals, and 
hashCode methods are implemented.

 

The members are immutable and need to be populated during construction.  Java 
does not allow you to modify the members' values through reflection, even if 
you change `Field::setAccessible` to true.

 

But they are regular classes otherwise. And you can serialize them with 
DatumWriter. However, when needed to be decoded, the Redecoded fails given that 
it relies on creating an empty instance of the class first, and populating its 
values later.

 

Here is how you can reproduce the error:
 * Disable the JDK 11, and modify the code source to be 17 and 21 only.
 * Insert the below snippet in the test class 
{{org.apache.avro.reflect.TestReflectDatumReader: }}

{{{}record PojoRecord(int max, int min) {{}}}{{{}}{}}}{{ }}
{{@Test}}
{{void testRead_RecordPojo() throws IOException {}}
{{PojoRecord record = new PojoRecord(10, 2);}}
{{Schema schema = ReflectData.get().getSchema(PojoRecord.class);}}

{{var dataWriter = new ReflectDatumWriter<>(schema);}}
{{try (var outStream = new ByteArrayOutputStream()) {}}
{{Encoder encoder = EncoderFactory.get().jsonEncoder(schema, outStream);}}
{{dataWriter.write(record, encoder);}}
{{encoder.flush();}}
{{String avroJson = outStream.toString(StandardCharsets.UTF_8);}}
{{assertEquals("\{\"max\":10,\"min\":2}", avroJson);}}
{{ReflectDatumReader<PojoRecord> reader = new ReflectDatumReader<>( schema, 
schema, new ReflectData());}}

{{try {}}
{{Decoder decoder = DecoderFactory.get().jsonDecoder(schema, avroJson);}}
{{PojoRecord readValue = reader.read(null, decoder);}}

{{} catch (IOException e) {}}
{{throw new IllegalStateException(String.format("Avro failed to decode %s to 
%s", avroJson, PojoRecord.class.getName()),}}
{{e);}}
{{}}}
{{}}}
 * Run this test, and you will  see this error:

 

Are there any plans for supporting Records in Avro?
{quote}{{java.lang.RuntimeException: java.lang.RuntimeException: 
java.lang.NoSuchMethodException: 
org.apache.avro.reflect.TestReflectDatumReader$PojoRecord.<init>()}}
{{{}at 
org.apache.avro.specific.SpecificData.newInstance(SpecificData.java:586){}}}{{{}at
 
org.apache.avro.specific.SpecificData.newRecord(SpecificData.java:604){}}}{{{}at
 org.apache.avro.reflect.ReflectData.newRecord(ReflectData.java:1044){}}}{{{}at 
...{}}}
{quote}
 

Given that CapitalOne relies heavily on the latest features of the Java 
language, We would like to contribute to a solution, if it doesn't exist yet.

 



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

Reply via email to