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)