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)