Describe the bug
After this commit that added nested record support to AutoGeneratedTimestampRecordExtension, the extension now recursively
introspects all attributes on a @DynamoDbBean to find @DynamoDbAutoGeneratedTimestampAttribute fields in nested types. This introspection does not respect @DynamoDbConvertedBy on list attributes — it attempts to resolve a TableSchema for the list element type even when a custom converter already handles serialization.
If the list element class is not annotated with @DynamoDbBean or @DynamoDbImmutable, TableSchema.fromClass() throws IllegalArgumentException. This is a regression and these configurations worked before the update.
Workaround:
Add @DynamoDbBean and a no-arg constructor to the nested POJO. This satisfies the schema resolution (the extension finds no timestamp fields and moves on), while the custom converter still handles actual serialization. This works but shouldn't be necessary — the custom converter contract means the SDK should not need to understand the element type's structure.
Impact:
This is a breaking change for any @DynamoDbBean that:
- Has
@DynamoDbAutoGeneratedTimestampAttribute on any field
- Has a
List<T> field with @DynamoDbConvertedBy
- Where
T is not a DynamoDB-annotated class
Regression Issue
Expected Behavior
The extension should skip introspection of List<NestedPojo> because the field has a @DynamoDbConvertedBy custom converter. The converter handles serialization — the extension doesn't need to resolve a TableSchema for the element type.
Current Behavior
java.lang.IllegalArgumentException: Class does not appear to be a valid DynamoDb annotated class.
[class = "class com.example.NestedPojo"]
at software.amazon.awssdk.enhanced.dynamodb.mapper.TableSchemaFactory.fromClass(TableSchemaFactory.java:39)
at software.amazon.awssdk.enhanced.dynamodb.TableSchema.fromClass(TableSchema.java:204)
at
software.amazon.awssdk.enhanced.dynamodb.internal.extensions.utility.NestedRecordUtils.getTableSchemaForListElement(NestedRecordUtils.
java:88)
at
software.amazon.awssdk.enhanced.dynamodb.internal.extensions.utility.NestedRecordUtils.getListElementSchemaCached(NestedRecordUtils.ja
va:230)
at
software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension.processTopLevelListOfMapsAttribute(AutoGener
atedTimestampRecordExtension.java:276)
at
software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension.processTopLevelAttributeForTimestamps(AutoGe
neratedTimestampRecordExtension.java:223)
at
software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension.lambda$processDirectNestedAttributes$0(AutoG
eneratedTimestampRecordExtension.java:195)
...
Reproduction Steps
- Define a
@DynamoDbBean entity with @DynamoDbAutoGeneratedTimestampAttribute on a field:
@DynamoDbBean
public class ParentEntity {
private List<NestedPojo> items;
private Instant lastUpdated;
@DynamoDbConvertedBy(CustomListConverter.class)
public List<NestedPojo> getItems() { return items; }
@DynamoDbAutoGeneratedTimestampAttribute
public Instant getLastUpdated() { return lastUpdated; }
}
- NestedPojo is a plain POJO with no DynamoDB annotations (serialization is handled entirely by CustomListConverter):
@Data
public class NestedPojo {
private String name;
private int value;
}
- Perform any write operation (
put, batchWrite) on ParentEntity.
Possible Solution
Root cause:
In NestedRecordUtils.getTableSchemaForListElement(), when EnhancedClientUtils.getNestedSchema() returns Optional.empty(), the fallback unconditionally calls TableSchema.fromClass() on the list element type. It should first check whether the attribute has a custom converter via @DynamoDbConvertedBy and skip introspection if one is present.
Additional Information/Context
No response
AWS Java SDK version used
2.42.31
JDK version used
OpenJDK Runtime Environment Corretto-17.0.18.9.1 (build 17.0.18+9-LTS)
Operating System and version
Amazon Linux
Describe the bug
After this commit that added nested record support to
AutoGeneratedTimestampRecordExtension, the extension now recursivelyintrospects all attributes on a
@DynamoDbBeanto find@DynamoDbAutoGeneratedTimestampAttributefields in nested types. This introspection does not respect@DynamoDbConvertedByon list attributes — it attempts to resolve aTableSchemafor the list element type even when a custom converter already handles serialization.If the list element class is not annotated with
@DynamoDbBeanor@DynamoDbImmutable,TableSchema.fromClass()throwsIllegalArgumentException. This is a regression and these configurations worked before the update.Workaround:
Add
@DynamoDbBeanand a no-arg constructor to the nested POJO. This satisfies the schema resolution (the extension finds no timestamp fields and moves on), while the custom converter still handles actual serialization. This works but shouldn't be necessary — the custom converter contract means the SDK should not need to understand the element type's structure.Impact:
This is a breaking change for any
@DynamoDbBeanthat:@DynamoDbAutoGeneratedTimestampAttributeon any fieldList<T>field with@DynamoDbConvertedByTis not a DynamoDB-annotated classRegression Issue
Expected Behavior
The extension should skip introspection of
List<NestedPojo>because the field has a@DynamoDbConvertedBycustom converter. The converter handles serialization — the extension doesn't need to resolve aTableSchemafor the element type.Current Behavior
Reproduction Steps
@DynamoDbBeanentity with@DynamoDbAutoGeneratedTimestampAttributeon a field:put,batchWrite) onParentEntity.Possible Solution
Root cause:
In
NestedRecordUtils.getTableSchemaForListElement(), whenEnhancedClientUtils.getNestedSchema()returnsOptional.empty(), the fallback unconditionally callsTableSchema.fromClass()on the list element type. It should first check whether the attribute has a custom converter via@DynamoDbConvertedByand skip introspection if one is present.Additional Information/Context
No response
AWS Java SDK version used
2.42.31
JDK version used
OpenJDK Runtime Environment Corretto-17.0.18.9.1 (build 17.0.18+9-LTS)
Operating System and version
Amazon Linux