This is an automated email from the ASF dual-hosted git repository.
rskraba pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/master by this push:
new 72beda3f4 AVRO-3473: ServiceLoader for Conversion (#1624)
72beda3f4 is described below
commit 72beda3f40a72f898fbe0bf0057c5612a582f71e
Author: Oscar Westra van Holthe - Kind <[email protected]>
AuthorDate: Thu Jun 15 18:31:54 2023 +0200
AVRO-3473: ServiceLoader for Conversion (#1624)
* AVRO-3473: ServiceLoader for Conversion
Automatically register Conversion classes using the Java 6 service
loader upon startup. This works for any Conversion that does not need
constructor parameters.
* AVRO-3473: ServiceLoader for Conversion
Improved variable name.
* AVRO-3473: Spotless
* Apply suggestions from code review
Co-authored-by: Ryan Skraba <[email protected]>
* AVRO-3473: Removed newline to trigger build
* AVRO-3473: Add missing import
No idea when that got dropped...
* AVRO-3473: Removed unused import
* AVRO-3473: Fix rebase errors
* Fix static imports
---------
Co-authored-by: Ryan Skraba <[email protected]>
---
.../src/main/java/org/apache/avro/Conversion.java | 43 +++++++++------
.../src/main/java/org/apache/avro/Conversions.java | 29 +++++-----
.../java/org/apache/avro/generic/GenericData.java | 29 ++++++----
...ummyLogicalTypeFactory.java => CustomType.java} | 28 ++++++++--
...alTypeFactory.java => CustomTypeConverter.java} | 28 ++++++++--
...tory.java => CustomTypeLogicalTypeFactory.java} | 6 +--
.../test/java/org/apache/avro/TestLogicalType.java | 4 +-
.../avro/generic/TestGenericLogicalTypes.java | 61 ++++++++++++++++++++--
...gicalTypeFactory => org.apache.avro.Conversion} | 2 +-
...org.apache.avro.LogicalTypes$LogicalTypeFactory | 2 +-
10 files changed, 172 insertions(+), 60 deletions(-)
diff --git a/lang/java/avro/src/main/java/org/apache/avro/Conversion.java
b/lang/java/avro/src/main/java/org/apache/avro/Conversion.java
index 4ae75f4a5..934672e7d 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/Conversion.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/Conversion.java
@@ -21,6 +21,9 @@ package org.apache.avro;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Map;
+import java.util.ServiceLoader;
+
+import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericEnumSymbol;
import org.apache.avro.generic.GenericFixed;
import org.apache.avro.generic.IndexedRecord;
@@ -28,23 +31,33 @@ import org.apache.avro.generic.IndexedRecord;
/**
* Conversion between generic and logical type instances.
* <p>
- * Instances of this class are added to GenericData to convert a logical type
to
- * a particular representation.
+ * Instances of this class can be added to GenericData to convert a logical
type
+ * to a particular representation. This can be done manually, using
+ * {@link GenericData#addLogicalTypeConversion(Conversion)}, or automatically.
+ * This last option uses the Java {@link ServiceLoader}, and requires the
+ * implementation to be a public class with a public no-arg constructor, be
+ * named in a file called {@code
/META-INF/services/org.apache.avro.Conversion},
+ * and both must available in the classpath.</li>
* <p>
- * Implementations must provide: * {@link #getConvertedType()}: get the Java
- * class used for the logical type * {@link #getLogicalTypeName()}: get the
- * logical type this implements
+ * Implementations must provide:
+ * <ul>
+ * <li>{@link #getConvertedType()}: get the Java class used for the logical
+ * type</li>
+ * <li>{@link #getLogicalTypeName()}: get the logical type this implements</li>
+ * </ul>
* <p>
- * Subclasses must also override all of the conversion methods for Avro's base
- * types that are valid for the logical type, or else risk causing
+ * Subclasses must also override the conversion methods for Avro's base types
+ * that are valid for the logical type, or else risk causing
* {@code UnsupportedOperationException} at runtime.
* <p>
* Optionally, use {@link #getRecommendedSchema()} to provide a Schema that
will
- * be used when a Schema is generated for the class returned by
- * {@code getConvertedType}.
+ * be used when generating a Schema for the class. This is useful when using
+ * {@code ReflectData} or {@code ProtobufData}, for example.
*
- * @param <T> a Java type that generic data is converted to
+ * @param <T> a Java type that can represent the named logical type
+ * @see ServiceLoader
*/
+@SuppressWarnings("unused")
public abstract class Conversion<T> {
/**
@@ -65,9 +78,9 @@ public abstract class Conversion<T> {
* Certain logical types may require adjusting the code within the "setter"
* methods to make sure the data that is set is properly formatted. This
method
* allows the Conversion to generate custom setter code if required.
- *
- * @param varName
- * @param valParamName
+ *
+ * @param varName the name of the variable holding the converted value
+ * @param valParamName the name of the parameter with the new converted value
* @return a String for the body of the setter method
*/
public String adjustAndSetValue(String varName, String valParamName) {
@@ -102,7 +115,7 @@ public abstract class Conversion<T> {
throw new UnsupportedOperationException("fromCharSequence is not supported
for " + type.getName());
}
- public T fromEnumSymbol(GenericEnumSymbol value, Schema schema, LogicalType
type) {
+ public T fromEnumSymbol(GenericEnumSymbol<?> value, Schema schema,
LogicalType type) {
throw new UnsupportedOperationException("fromEnumSymbol is not supported
for " + type.getName());
}
@@ -150,7 +163,7 @@ public abstract class Conversion<T> {
throw new UnsupportedOperationException("toCharSequence is not supported
for " + type.getName());
}
- public GenericEnumSymbol toEnumSymbol(T value, Schema schema, LogicalType
type) {
+ public GenericEnumSymbol<?> toEnumSymbol(T value, Schema schema, LogicalType
type) {
throw new UnsupportedOperationException("toEnumSymbol is not supported for
" + type.getName());
}
diff --git a/lang/java/avro/src/main/java/org/apache/avro/Conversions.java
b/lang/java/avro/src/main/java/org/apache/avro/Conversions.java
index 1c28c9adb..7d01fc62a 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/Conversions.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/Conversions.java
@@ -106,11 +106,12 @@ public class Conversions {
byte fillByte = (byte) (value.signum() < 0 ? 0xFF : 0x00);
byte[] unscaled = value.unscaledValue().toByteArray();
byte[] bytes = new byte[schema.getFixedSize()];
- int offset = bytes.length - unscaled.length;
+ int unscaledLength = unscaled.length;
+ int offset = bytes.length - unscaledLength;
- // Fill the front of the array and copy remaining with unscaled values
+ // Fill the front with the filler and copy the unscaled value into the
remainder
Arrays.fill(bytes, 0, offset, fillByte);
- System.arraycopy(unscaled, 0, bytes, offset, bytes.length - offset);
+ System.arraycopy(unscaled, 0, bytes, offset, unscaledLength);
return new GenericData.Fixed(schema, bytes);
}
@@ -147,7 +148,7 @@ public class Conversions {
}
/**
- * Convert a underlying representation of a logical type (such as a
ByteBuffer)
+ * Convert an underlying representation of a logical type (such as a
ByteBuffer)
* to a higher level object (such as a BigDecimal).
*
* @param datum The object to be converted.
@@ -157,9 +158,9 @@ public class Conversions {
* @param conversion The tool used to finish the conversion. Cannot be null
if
* datum is not null.
* @return The result object, which is a high level object of the logical
type.
- * If a null datum is passed in, a null value will be returned.
- * @throws IllegalArgumentException if a null schema, type or conversion is
- * passed in while datum is not null.
+ * The null datum always converts to a null value.
+ * @throws IllegalArgumentException if datum is not null, but schema, type or
+ * conversion is.
*/
public static Object convertToLogicalType(Object datum, Schema schema,
LogicalType type, Conversion<?> conversion) {
if (datum == null) {
@@ -176,9 +177,9 @@ public class Conversions {
case RECORD:
return conversion.fromRecord((IndexedRecord) datum, schema, type);
case ENUM:
- return conversion.fromEnumSymbol((GenericEnumSymbol) datum, schema,
type);
+ return conversion.fromEnumSymbol((GenericEnumSymbol<?>) datum, schema,
type);
case ARRAY:
- return conversion.fromArray((Collection) datum, schema, type);
+ return conversion.fromArray((Collection<?>) datum, schema, type);
case MAP:
return conversion.fromMap((Map<?, ?>) datum, schema, type);
case FIXED:
@@ -201,13 +202,13 @@ public class Conversions {
return datum;
} catch (ClassCastException e) {
throw new AvroRuntimeException(
- "Cannot convert " + datum + ":" + datum.getClass().getSimpleName() +
": expected generic type", e);
+ "Cannot convert " + datum + ':' + datum.getClass().getSimpleName() +
": expected generic type", e);
}
}
/**
* Convert a high level representation of a logical type (such as a
BigDecimal)
- * to the its underlying representation object (such as a ByteBuffer)
+ * to its underlying representation object (such as a ByteBuffer)
*
* @param datum The object to be converted.
* @param schema The schema of datum. Cannot be null if datum is not
null.
@@ -218,8 +219,8 @@ public class Conversions {
* @return The result object, which is an underlying representation object of
* the logical type. If the input param datum is null, a null value
will
* be returned.
- * @throws IllegalArgumentException if a null schema, type or conversion is
- * passed in while datum is not null.
+ * @throws IllegalArgumentException if datum is not null, but schema, type or
+ * conversion is.
*/
public static <T> Object convertToRawType(Object datum, Schema schema,
LogicalType type, Conversion<T> conversion) {
if (datum == null) {
@@ -262,7 +263,7 @@ public class Conversions {
return datum;
} catch (ClassCastException e) {
throw new AvroRuntimeException(
- "Cannot convert " + datum + ":" + datum.getClass().getSimpleName() +
": expected logical type", e);
+ "Cannot convert " + datum + ':' + datum.getClass().getSimpleName() +
": expected logical type", e);
}
}
diff --git
a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
index 71861ef97..125e93062 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
@@ -32,6 +32,7 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.ServiceLoader;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
@@ -117,6 +118,7 @@ public class GenericData {
/** For subclasses. GenericData does not use a ClassLoader. */
public GenericData(ClassLoader classLoader) {
this.classLoader = (classLoader != null) ? classLoader :
getClass().getClassLoader();
+ loadConversions();
}
/** Return the class loader that's used (by subclasses). */
@@ -124,6 +126,17 @@ public class GenericData {
return classLoader;
}
+ /**
+ * Use the Java 6 ServiceLoader to load conversions.
+ *
+ * @see #addLogicalTypeConversion(Conversion)
+ */
+ private void loadConversions() {
+ for (Conversion<?> conversion : ServiceLoader.load(Conversion.class,
classLoader)) {
+ addLogicalTypeConversion(conversion);
+ }
+ }
+
private Map<String, Conversion<?>> conversions = new HashMap<>();
private Map<Class<?>, Map<String, Conversion<?>>> conversionsByClass = new
IdentityHashMap<>();
@@ -134,19 +147,17 @@ public class GenericData {
/**
* Registers the given conversion to be used when reading and writing with
this
- * data model.
+ * data model. Conversions can also be registered automatically, as
documented
+ * on the class {@link Conversion Conversion<T>}.
*
* @param conversion a logical type Conversion.
*/
public void addLogicalTypeConversion(Conversion<?> conversion) {
conversions.put(conversion.getLogicalTypeName(), conversion);
Class<?> type = conversion.getConvertedType();
- Map<String, Conversion<?>> conversions = conversionsByClass.get(type);
- if (conversions == null) {
- conversions = new LinkedHashMap<>();
- conversionsByClass.put(type, conversions);
- }
- conversions.put(conversion.getLogicalTypeName(), conversion);
+ Map<String, Conversion<?>> conversionsForClass =
conversionsByClass.computeIfAbsent(type,
+ k -> new LinkedHashMap<>());
+ conversionsForClass.put(conversion.getLogicalTypeName(), conversion);
}
/**
@@ -187,11 +198,11 @@ public class GenericData {
* @return the conversion for the logical type, or null
*/
@SuppressWarnings("unchecked")
- public Conversion<Object> getConversionFor(LogicalType logicalType) {
+ public <T> Conversion<T> getConversionFor(LogicalType logicalType) {
if (logicalType == null) {
return null;
}
- return (Conversion<Object>) conversions.get(logicalType.getName());
+ return (Conversion<T>) conversions.get(logicalType.getName());
}
public static final String FAST_READER_PROP = "org.apache.avro.fastread";
diff --git
a/lang/java/avro/src/test/java/org/apache/avro/DummyLogicalTypeFactory.java
b/lang/java/avro/src/test/java/org/apache/avro/CustomType.java
similarity index 64%
copy from
lang/java/avro/src/test/java/org/apache/avro/DummyLogicalTypeFactory.java
copy to lang/java/avro/src/test/java/org/apache/avro/CustomType.java
index 4957e3765..140ac901b 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/DummyLogicalTypeFactory.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/CustomType.java
@@ -15,16 +15,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.apache.avro;
-public class DummyLogicalTypeFactory implements
LogicalTypes.LogicalTypeFactory {
+import java.util.Objects;
+
+public final class CustomType {
+ private final String name;
+
+ public CustomType(CharSequence name) {
+ this.name = name.toString();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name);
+ }
+
@Override
- public LogicalType fromSchema(Schema schema) {
- return LogicalTypes.date();
+ public boolean equals(Object obj) {
+ return obj instanceof CustomType && name.equals(((CustomType) obj).name);
}
@Override
- public String getTypeName() {
- return "service-example";
+ public String toString() {
+ return "CustomType{name='" + name + "'}";
}
}
diff --git
a/lang/java/avro/src/test/java/org/apache/avro/DummyLogicalTypeFactory.java
b/lang/java/avro/src/test/java/org/apache/avro/CustomTypeConverter.java
similarity index 54%
copy from
lang/java/avro/src/test/java/org/apache/avro/DummyLogicalTypeFactory.java
copy to lang/java/avro/src/test/java/org/apache/avro/CustomTypeConverter.java
index 4957e3765..de8fea02c 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/DummyLogicalTypeFactory.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/CustomTypeConverter.java
@@ -15,16 +15,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.apache.avro;
-public class DummyLogicalTypeFactory implements
LogicalTypes.LogicalTypeFactory {
+public class CustomTypeConverter extends Conversion<CustomType> {
+ private static final CustomTypeLogicalTypeFactory logicalTypeFactory = new
CustomTypeLogicalTypeFactory();
+
+ @Override
+ public Class<CustomType> getConvertedType() {
+ return CustomType.class;
+ }
+
+ @Override
+ public String getLogicalTypeName() {
+ return logicalTypeFactory.getTypeName();
+ }
+
+ @Override
+ public Schema getRecommendedSchema() {
+ return Schema.create(Schema.Type.STRING);
+ }
+
@Override
- public LogicalType fromSchema(Schema schema) {
- return LogicalTypes.date();
+ public CustomType fromCharSequence(CharSequence value, Schema schema,
LogicalType type) {
+ return new CustomType(value);
}
@Override
- public String getTypeName() {
- return "service-example";
+ public CharSequence toCharSequence(CustomType value, Schema schema,
LogicalType type) {
+ return value.getName();
}
}
diff --git
a/lang/java/avro/src/test/java/org/apache/avro/DummyLogicalTypeFactory.java
b/lang/java/avro/src/test/java/org/apache/avro/CustomTypeLogicalTypeFactory.java
similarity index 86%
rename from
lang/java/avro/src/test/java/org/apache/avro/DummyLogicalTypeFactory.java
rename to
lang/java/avro/src/test/java/org/apache/avro/CustomTypeLogicalTypeFactory.java
index 4957e3765..3e121e024 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/DummyLogicalTypeFactory.java
+++
b/lang/java/avro/src/test/java/org/apache/avro/CustomTypeLogicalTypeFactory.java
@@ -17,14 +17,14 @@
*/
package org.apache.avro;
-public class DummyLogicalTypeFactory implements
LogicalTypes.LogicalTypeFactory {
+public class CustomTypeLogicalTypeFactory implements
LogicalTypes.LogicalTypeFactory {
@Override
public LogicalType fromSchema(Schema schema) {
- return LogicalTypes.date();
+ return new LogicalType(getTypeName());
}
@Override
public String getTypeName() {
- return "service-example";
+ return "custom";
}
}
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestLogicalType.java
b/lang/java/avro/src/test/java/org/apache/avro/TestLogicalType.java
index 800772e7f..acc8899b2 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestLogicalType.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestLogicalType.java
@@ -288,9 +288,9 @@ public class TestLogicalType {
}
@Test
- void registerLogicalTypeFactoryByServiceLoader() {
+ public void testRegisterLogicalTypeFactoryByServiceLoader() {
assertThat(LogicalTypes.getCustomRegisteredTypes(),
- IsMapContaining.hasEntry(equalTo("service-example"),
instanceOf(LogicalTypes.LogicalTypeFactory.class)));
+ IsMapContaining.hasEntry(equalTo("custom"),
instanceOf(LogicalTypes.LogicalTypeFactory.class)));
}
public static void assertEqualsTrue(String message, Object o1, Object o2) {
diff --git
a/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericLogicalTypes.java
b/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericLogicalTypes.java
index 3d5e2300d..25a838db3 100644
---
a/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericLogicalTypes.java
+++
b/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericLogicalTypes.java
@@ -18,11 +18,6 @@
package org.apache.avro.generic;
-import static org.hamcrest.Matchers.is;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotSame;
-import static org.hamcrest.MatcherAssert.assertThat;
-
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
@@ -35,8 +30,10 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
+
import org.apache.avro.Conversion;
import org.apache.avro.Conversions;
+import org.apache.avro.CustomType;
import org.apache.avro.LogicalType;
import org.apache.avro.LogicalTypes;
import org.apache.avro.Schema;
@@ -51,6 +48,11 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+
public class TestGenericLogicalTypes {
@TempDir
@@ -402,4 +404,53 @@ public class TestGenericLogicalTypes {
assertEquals(expected,
read(GenericData.get().createDatumReader(timestampSchema), test),
"Should read LocalDateTime as longs");
}
+
+ @Test
+ public void testReadAutomaticallyRegisteredUri() throws IOException {
+ Schema stringSchema = Schema.create(Schema.Type.STRING);
+ GenericData.setStringType(stringSchema, GenericData.StringType.String);
+ LogicalType customType =
LogicalTypes.getCustomRegisteredTypes().get("custom").fromSchema(stringSchema);
+ Schema customTypeSchema =
customType.addToSchema(Schema.create(Schema.Type.STRING));
+
+ CustomType ct1 = new CustomType("foo");
+ CustomType ct2 = new CustomType("bar");
+ List<CustomType> expected = Arrays.asList(ct1, ct2);
+
+ Conversion<CustomType> conversion = GENERIC.getConversionFor(customType);
+
+ // use the conversion directly instead of relying on the write side
+ CharSequence ct1String = conversion.toCharSequence(ct1, stringSchema,
customType);
+ CharSequence ct2String = conversion.toCharSequence(ct2, stringSchema,
customType);
+
+ File test = write(stringSchema, ct1String, ct2String);
+ assertEquals(expected, read(GENERIC.createDatumReader(customTypeSchema),
test),
+ "Should convert string to CustomType");
+ }
+
+ @Test
+ public void testWriteAutomaticallyRegisteredUri() throws IOException {
+ Schema stringSchema = Schema.create(Schema.Type.STRING);
+ GenericData.setStringType(stringSchema, GenericData.StringType.String);
+ LogicalType customType =
LogicalTypes.getCustomRegisteredTypes().get("custom").fromSchema(stringSchema);
+ Schema customTypeSchema =
customType.addToSchema(Schema.create(Schema.Type.STRING));
+
+ CustomType ct1 = new CustomType("foo");
+ CustomType ct2 = new CustomType("bar");
+
+ Conversion<CustomType> conversion = GENERIC.getConversionFor(customType);
+
+ // use the conversion directly instead of relying on the write side
+ CharSequence ct1String = conversion.toCharSequence(ct1, stringSchema,
customType);
+ CharSequence ct2String = conversion.toCharSequence(ct2, stringSchema,
customType);
+ List<CharSequence> expected = Arrays.asList(ct1String, ct2String);
+
+ File test = write(GENERIC, customTypeSchema, ct1, ct2);
+
+ // Note that this test still cannot read strings using the logical type
+ // schema, as all GenericData instances have the logical type and the
+ // conversions loaded. That's why this final assert is slightly different.
+
+ assertEquals(expected,
read(GenericData.get().createDatumReader(stringSchema), test),
+ "Should read CustomType as strings");
+ }
}
diff --git
a/lang/java/avro/src/test/resources/META-INF/services/org.apache.avro.LogicalTypes$LogicalTypeFactory
b/lang/java/avro/src/test/resources/META-INF/services/org.apache.avro.Conversion
similarity index 95%
copy from
lang/java/avro/src/test/resources/META-INF/services/org.apache.avro.LogicalTypes$LogicalTypeFactory
copy to
lang/java/avro/src/test/resources/META-INF/services/org.apache.avro.Conversion
index e111a25c4..890ba7642 100644
---
a/lang/java/avro/src/test/resources/META-INF/services/org.apache.avro.LogicalTypes$LogicalTypeFactory
+++
b/lang/java/avro/src/test/resources/META-INF/services/org.apache.avro.Conversion
@@ -14,4 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-org.apache.avro.DummyLogicalTypeFactory
+org.apache.avro.CustomTypeConverter
diff --git
a/lang/java/avro/src/test/resources/META-INF/services/org.apache.avro.LogicalTypes$LogicalTypeFactory
b/lang/java/avro/src/test/resources/META-INF/services/org.apache.avro.LogicalTypes$LogicalTypeFactory
index e111a25c4..b55c233ae 100644
---
a/lang/java/avro/src/test/resources/META-INF/services/org.apache.avro.LogicalTypes$LogicalTypeFactory
+++
b/lang/java/avro/src/test/resources/META-INF/services/org.apache.avro.LogicalTypes$LogicalTypeFactory
@@ -14,4 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-org.apache.avro.DummyLogicalTypeFactory
+org.apache.avro.CustomTypeLogicalTypeFactory