Skip to content

Commit 2c912cd

Browse files
fix(java): Encoders.mapEncoder(TypeRef, TypeRef, TypeRef, Fory) should load bean classes (#2494)
We dynamically select the key and value type, and tried using this overload of Encoders.mapEncoder With the single-arg mapEncoder invocation, bean codec classes are loaded with `token4BeanLoad` But this overload never loads the bean classes leading to unexpected exceptions during Map codec compile since bean codecs are not loaded
1 parent 66a2e78 commit 2c912cd

2 files changed

Lines changed: 36 additions & 3 deletions

File tree

java/fory-format/src/main/java/org/apache/fory/format/encoder/Encoders.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ public static <T extends Map> MapEncoder<T> mapEncoder(TypeRef<T> token, Fory fo
474474
TypeRef<?> keyToken = token4BeanLoad(set1, tuple2.f0);
475475
TypeRef<?> valToken = token4BeanLoad(set2, tuple2.f1);
476476

477-
MapEncoder<T> encoder = mapEncoder(token, keyToken, valToken, fory);
477+
MapEncoder<T> encoder = mapEncoder0(token, keyToken, valToken, fory);
478478
return createMapEncoder(encoder);
479479
}
480480

@@ -495,6 +495,22 @@ public static <T extends Map, K, V> MapEncoder<T> mapEncoder(
495495
Preconditions.checkNotNull(keyToken);
496496
Preconditions.checkNotNull(valToken);
497497

498+
Set<TypeRef<?>> set1 = beanSet(keyToken);
499+
Set<TypeRef<?>> set2 = beanSet(valToken);
500+
LOG.info("Find beans to load: {}, {}", set1, set2);
501+
502+
token4BeanLoad(set1, keyToken);
503+
token4BeanLoad(set2, valToken);
504+
505+
return mapEncoder0(mapToken, keyToken, valToken, fory);
506+
}
507+
508+
private static <T extends Map, K, V> MapEncoder<T> mapEncoder0(
509+
TypeRef<? extends Map> mapToken, TypeRef<K> keyToken, TypeRef<V> valToken, Fory fory) {
510+
Preconditions.checkNotNull(mapToken);
511+
Preconditions.checkNotNull(keyToken);
512+
Preconditions.checkNotNull(valToken);
513+
498514
Schema schema = TypeInference.inferSchema(mapToken, false);
499515
Field field = DataTypes.fieldOfSchema(schema, 0);
500516
Field keyField = DataTypes.keyArrayFieldForMap(field);
@@ -685,6 +701,9 @@ public static Class<?> loadOrGenRowCodecClass(Class<?> beanClass) {
685701
TypeUtils.listBeansRecursiveInclusive(
686702
beanClass,
687703
new TypeResolutionContext(CustomTypeEncoderRegistry.customTypeHandler(), true));
704+
if (classes.isEmpty()) {
705+
return null;
706+
}
688707
LOG.info("Create RowCodec for classes {}", classes);
689708
CompileUnit[] compileUnits =
690709
classes.stream()

java/fory-format/src/test/java/org/apache/fory/format/encoder/MapEncoderTest.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ public void testSimpleNestStructWithMapEncoder() {
134134
@Test
135135
public void testKVStructMap() {
136136
Map<SimpleFoo, SimpleFoo> map = ImmutableMap.of(SimpleFoo.create(), SimpleFoo.create());
137-
MapEncoder encoder = Encoders.mapEncoder(new TypeRef<Map<SimpleFoo, SimpleFoo>>() {});
137+
var encoder = Encoders.mapEncoder(new TypeRef<Map<SimpleFoo, SimpleFoo>>() {});
138138
testStreamingEncode(encoder, map);
139-
MapEncoder encoder1 = Encoders.mapEncoder(new TypeRef<Map<Foo, Foo>>() {});
139+
var encoder1 = Encoders.mapEncoder(new TypeRef<Map<Foo, Foo>>() {});
140140
testStreamingEncode(encoder1, ImmutableMap.of(Foo.create(), Foo.create()));
141141
}
142142

@@ -192,4 +192,18 @@ public void testNestArrayWithMapEncoder() {
192192

193193
testStreamingEncode(encoder, lmap);
194194
}
195+
196+
@Test
197+
public <K, V> void testDynamicTypeDeclaration() {
198+
Encoders.mapEncoder(
199+
new TypeRef<HashMap<Integer, Bean>>() {},
200+
TypeRef.of(Integer.class),
201+
TypeRef.of(Bean.class),
202+
null)
203+
.encode(new HashMap<>());
204+
}
205+
206+
public static class Bean {
207+
int f1;
208+
}
195209
}

0 commit comments

Comments
 (0)