Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/next-release/bugfix-AmazonDynamoDB-c60c54b.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "bugfix",
"category": "Amazon DynamoDB",
"description": "Fix `TableSchema.fromBean` for mutually recursive `@DynamoDbBean` classes. ([#6110](https://github.com/aws/aws-sdk-java-v2/issues/6110))",
"contributor": "afarber"
}
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ private static <T> BeanTableSchema<T> create(BeanTableSchemaParams<T> params, Me
return newTableSchema;
}

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

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

}

Expand Down Expand Up @@ -603,4 +604,3 @@ static void clearSchemaCache() {
BEAN_TABLE_SCHEMA_CACHE.clear();
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,28 @@
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.RecursiveRecordBean;
import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.RecursiveRecordImmutable;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;

public class BeanTableSchemaRecursiveTest {
@Test
public void transitiveRecursiveBean_document() {
TableSchema<TransitiveRecursiveParent> tableSchema = TableSchema.fromBean(TransitiveRecursiveParent.class);

TransitiveRecursiveChild child = new TransitiveRecursiveChild();
child.setName("child");

TransitiveRecursiveParent parent = new TransitiveRecursiveParent();
parent.setName("parent");
parent.setChild(child);

TransitiveRecursiveParent roundTrip = tableSchema.mapToItem(tableSchema.itemToMap(parent, true));

assertThat(roundTrip.getName()).isEqualTo("parent");
assertThat(roundTrip.getChild().getName()).isEqualTo("child");
assertThat(roundTrip.getChild().getParent()).isNull();
}

@Test
public void recursiveRecord_document() {
TableSchema<RecursiveRecordBean> tableSchema = TableSchema.fromClass(RecursiveRecordBean.class);
Expand Down Expand Up @@ -89,4 +108,48 @@ public void recursiveRecord_list() {
});
});
}

@DynamoDbBean
public static class TransitiveRecursiveParent {
private String name;
private TransitiveRecursiveChild child;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public TransitiveRecursiveChild getChild() {
return child;
}

public void setChild(TransitiveRecursiveChild child) {
this.child = child;
}
}

@DynamoDbBean
public static class TransitiveRecursiveChild {
private String name;
private TransitiveRecursiveParent parent;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public TransitiveRecursiveParent getParent() {
return parent;
}

public void setParent(TransitiveRecursiveParent parent) {
this.parent = parent;
}
}
}