You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by yh...@apache.org on 2023/06/20 15:08:25 UTC

[beam] branch master updated: Avro datum factory fixup (#27173)

This is an automated email from the ASF dual-hosted git repository.

yhu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new 4c66866aa95 Avro datum factory fixup (#27173)
4c66866aa95 is described below

commit 4c66866aa9544d1796c7c3880192cb57d2a8dcc0
Author: Michel Davit <mi...@davit.fr>
AuthorDate: Tue Jun 20 17:08:17 2023 +0200

    Avro datum factory fixup (#27173)
    
    * Remove DecimalConversion from logical-type conversions
    
    * Restore AvroCloudObject compatibility
---
 .../util/AvroCoderCloudObjectTranslator.java       | 30 +++++++++++++++++-----
 .../extensions/avro/schemas/utils/AvroUtils.java   |  3 ++-
 2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/runners/google-cloud-dataflow-java/src/main/java/org/apache/beam/runners/dataflow/util/AvroCoderCloudObjectTranslator.java b/runners/google-cloud-dataflow-java/src/main/java/org/apache/beam/runners/dataflow/util/AvroCoderCloudObjectTranslator.java
index e5c6ded2fdf..9f5913f051b 100644
--- a/runners/google-cloud-dataflow-java/src/main/java/org/apache/beam/runners/dataflow/util/AvroCoderCloudObjectTranslator.java
+++ b/runners/google-cloud-dataflow-java/src/main/java/org/apache/beam/runners/dataflow/util/AvroCoderCloudObjectTranslator.java
@@ -31,6 +31,9 @@ import org.apache.beam.sdk.util.StringUtils;
 class AvroCoderCloudObjectTranslator implements CloudObjectTranslator<AvroCoder> {
   private static final String DATUM_FACTORY_FIELD = "datum_factory";
   private static final String SCHEMA_FIELD = "schema";
+  // deprecated fields
+  private static final String TYPE_FIELD = "type";
+  private static final String REFLECT_API_FIELD = "reflect_api";
 
   @Override
   public CloudObject toCloudObject(AvroCoder target, SdkComponents sdkComponents) {
@@ -45,15 +48,28 @@ class AvroCoderCloudObjectTranslator implements CloudObjectTranslator<AvroCoder>
 
   @Override
   public AvroCoder<?> fromCloudObject(CloudObject cloudObject) {
-    Schema.Parser parser = new Schema.Parser();
-    byte[] deserializedDatumFactory =
-        StringUtils.jsonStringToByteArray(Structs.getString(cloudObject, DATUM_FACTORY_FIELD));
     String schemaString = Structs.getString(cloudObject, SCHEMA_FIELD);
+    Schema.Parser parser = new Schema.Parser();
     Schema schema = parser.parse(schemaString);
-    AvroDatumFactory<?> datumFactory =
-        (AvroDatumFactory)
-            SerializableUtils.deserializeFromByteArray(
-                deserializedDatumFactory, DATUM_FACTORY_FIELD);
+    AvroDatumFactory<?> datumFactory;
+    if (cloudObject.containsKey(TYPE_FIELD)) {
+      // coder was created with an older beam version. use default datum factory
+      try {
+        String className = Structs.getString(cloudObject, TYPE_FIELD);
+        Class<?> type = Class.forName(className);
+        boolean useReflectApi = Structs.getBoolean(cloudObject, REFLECT_API_FIELD);
+        datumFactory = AvroDatumFactory.of(type, useReflectApi);
+      } catch (ClassNotFoundException e) {
+        throw new IllegalArgumentException(e);
+      }
+    } else {
+      byte[] deserializedDatumFactory =
+          StringUtils.jsonStringToByteArray(Structs.getString(cloudObject, DATUM_FACTORY_FIELD));
+      datumFactory =
+          (AvroDatumFactory)
+              SerializableUtils.deserializeFromByteArray(
+                  deserializedDatumFactory, DATUM_FACTORY_FIELD);
+    }
     return AvroCoder.of(datumFactory, schema);
   }
 
diff --git a/sdks/java/extensions/avro/src/main/java/org/apache/beam/sdk/extensions/avro/schemas/utils/AvroUtils.java b/sdks/java/extensions/avro/src/main/java/org/apache/beam/sdk/extensions/avro/schemas/utils/AvroUtils.java
index eb1b9cdaba4..1f4fca5e831 100644
--- a/sdks/java/extensions/avro/src/main/java/org/apache/beam/sdk/extensions/avro/schemas/utils/AvroUtils.java
+++ b/sdks/java/extensions/avro/src/main/java/org/apache/beam/sdk/extensions/avro/schemas/utils/AvroUtils.java
@@ -153,7 +153,8 @@ public class AvroUtils {
   private static final ForLoadedType JODA_INSTANT = new ForLoadedType(Instant.class);
 
   public static void addLogicalTypeConversions(final GenericData data) {
-    data.addLogicalTypeConversion(new Conversions.DecimalConversion());
+    // do not add DecimalConversion by default as schema must have extra 'scale' and 'precision'
+    // properties. avro reflect already handles BigDecimal as string with the 'java-class' property
     data.addLogicalTypeConversion(new Conversions.UUIDConversion());
     // joda-time
     data.addLogicalTypeConversion(new AvroJodaTimeConversions.DateConversion());