Skip to content

Commit c14dd0c

Browse files
committed
Support mutually recursive DynamoDB bean schemas
1 parent a42ea7a commit c14dd0c

3 files changed

Lines changed: 73 additions & 4 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "bugfix",
3+
"category": "Amazon DynamoDB",
4+
"description": "Fix `TableSchema.fromBean` for mutually recursive `@DynamoDbBean` classes. ([#6110](https://github.com/aws/aws-sdk-java-v2/issues/6110))",
5+
"contributor": "afarber"
6+
}

services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/BeanTableSchema.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,8 @@ private static <T> BeanTableSchema<T> create(BeanTableSchemaParams<T> params, Me
192192
return newTableSchema;
193193
}
194194

195-
// Called when creating an immutable TableSchema recursively. Utilizes the MetaTableSchema cache to stop infinite
196-
// recursion
195+
// Called when creating a bean TableSchema recursively. Utilizes the MetaTableSchema cache to stop infinite
196+
// recursion for self-referencing and mutually recursive schemas.
197197
static <T> TableSchema<T> recursiveCreate(Class<T> beanClass, MethodHandles.Lookup lookup,
198198
MetaTableSchemaCache metaTableSchemaCache) {
199199
Optional<MetaTableSchema<T>> metaTableSchema = metaTableSchemaCache.get(beanClass);
@@ -211,7 +211,8 @@ static <T> TableSchema<T> recursiveCreate(Class<T> beanClass, MethodHandles.Look
211211
}
212212

213213
// Otherwise: cache doesn't know about this class; create a new one from scratch
214-
return create(BeanTableSchemaParams.builder(beanClass).lookup(lookup).build());
214+
return create(BeanTableSchemaParams.builder(beanClass).lookup(lookup).build(), metaTableSchemaCache,
215+
ExecutionContext.ROOT);
215216

216217
}
217218

@@ -603,4 +604,3 @@ static void clearSchemaCache() {
603604
BEAN_TABLE_SCHEMA_CACHE.clear();
604605
}
605606
}
606-

services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BeanTableSchemaRecursiveTest.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,28 @@
2323
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
2424
import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.RecursiveRecordBean;
2525
import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.RecursiveRecordImmutable;
26+
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
2627
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
2728

2829
public class BeanTableSchemaRecursiveTest {
30+
@Test
31+
public void transitiveRecursiveBean_document() {
32+
TableSchema<TransitiveRecursiveParent> tableSchema = TableSchema.fromBean(TransitiveRecursiveParent.class);
33+
34+
TransitiveRecursiveChild child = new TransitiveRecursiveChild();
35+
child.setName("child");
36+
37+
TransitiveRecursiveParent parent = new TransitiveRecursiveParent();
38+
parent.setName("parent");
39+
parent.setChild(child);
40+
41+
TransitiveRecursiveParent roundTrip = tableSchema.mapToItem(tableSchema.itemToMap(parent, true));
42+
43+
assertThat(roundTrip.getName()).isEqualTo("parent");
44+
assertThat(roundTrip.getChild().getName()).isEqualTo("child");
45+
assertThat(roundTrip.getChild().getParent()).isNull();
46+
}
47+
2948
@Test
3049
public void recursiveRecord_document() {
3150
TableSchema<RecursiveRecordBean> tableSchema = TableSchema.fromClass(RecursiveRecordBean.class);
@@ -89,4 +108,48 @@ public void recursiveRecord_list() {
89108
});
90109
});
91110
}
111+
112+
@DynamoDbBean
113+
public static class TransitiveRecursiveParent {
114+
private String name;
115+
private TransitiveRecursiveChild child;
116+
117+
public String getName() {
118+
return name;
119+
}
120+
121+
public void setName(String name) {
122+
this.name = name;
123+
}
124+
125+
public TransitiveRecursiveChild getChild() {
126+
return child;
127+
}
128+
129+
public void setChild(TransitiveRecursiveChild child) {
130+
this.child = child;
131+
}
132+
}
133+
134+
@DynamoDbBean
135+
public static class TransitiveRecursiveChild {
136+
private String name;
137+
private TransitiveRecursiveParent parent;
138+
139+
public String getName() {
140+
return name;
141+
}
142+
143+
public void setName(String name) {
144+
this.name = name;
145+
}
146+
147+
public TransitiveRecursiveParent getParent() {
148+
return parent;
149+
}
150+
151+
public void setParent(TransitiveRecursiveParent parent) {
152+
this.parent = parent;
153+
}
154+
}
92155
}

0 commit comments

Comments
 (0)