diff --git a/aws-lambda-java-serialization/src/main/java/com/amazonaws/services/lambda/runtime/serialization/events/LambdaEventSerializers.java b/aws-lambda-java-serialization/src/main/java/com/amazonaws/services/lambda/runtime/serialization/events/LambdaEventSerializers.java index b24b4060..4173211e 100644 --- a/aws-lambda-java-serialization/src/main/java/com/amazonaws/services/lambda/runtime/serialization/events/LambdaEventSerializers.java +++ b/aws-lambda-java-serialization/src/main/java/com/amazonaws/services/lambda/runtime/serialization/events/LambdaEventSerializers.java @@ -158,7 +158,7 @@ public class LambdaEventSerializers { * If mixins are required for inner classes of an event, then those nested classes must be specified here. */ @SuppressWarnings("rawtypes") - private static final Map> NESTED_CLASS_MAP = Stream.of( + private static final Map> NESTED_CLASS_MAP = Stream.of( new SimpleEntry<>("com.amazonaws.services.lambda.runtime.events.CodeCommitEvent", Arrays.asList( new NestedClass("com.amazonaws.services.lambda.runtime.events.CodeCommitEvent$Record"))), @@ -180,6 +180,14 @@ public class LambdaEventSerializers { "com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord", "com.amazonaws.services.dynamodbv2.model.StreamRecord"), new NestedClass("com.amazonaws.services.lambda.runtime.events.DynamodbEvent$DynamodbStreamRecord"))), + new SimpleEntry<>("com.amazonaws.services.lambda.runtime.events.DynamodbEvent$DynamodbStreamRecord", + Arrays.asList( + new AlternateNestedClass( + "com.amazonaws.services.lambda.runtime.events.models.dynamodb.AttributeValue", + "com.amazonaws.services.dynamodbv2.model.AttributeValue"), + new AlternateNestedClass( + "com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord", + "com.amazonaws.services.dynamodbv2.model.StreamRecord"))), new SimpleEntry<>("com.amazonaws.services.lambda.runtime.events.DynamodbTimeWindowEvent", Arrays.asList( new AlternateNestedClass( @@ -236,7 +244,7 @@ public static PojoSerializer serializerFor(Class eventClass, ClassLoad } // if event model has nested classes then load those classes and check if mixins apply if (NESTED_CLASS_MAP.containsKey(eventClass.getName())) { - List nestedClasses = NESTED_CLASS_MAP.get(eventClass.getName()); + List nestedClasses = NESTED_CLASS_MAP.get(eventClass.getName()); for (NestedClass nestedClass: nestedClasses) { // if mixin exists for nested class then apply if (MIXIN_MAP.containsKey(nestedClass.className)) { diff --git a/aws-lambda-java-tests/src/main/java/com/amazonaws/services/lambda/runtime/tests/EventLoader.java b/aws-lambda-java-tests/src/main/java/com/amazonaws/services/lambda/runtime/tests/EventLoader.java index 68cd37d3..7228fb90 100644 --- a/aws-lambda-java-tests/src/main/java/com/amazonaws/services/lambda/runtime/tests/EventLoader.java +++ b/aws-lambda-java-tests/src/main/java/com/amazonaws/services/lambda/runtime/tests/EventLoader.java @@ -65,6 +65,10 @@ public static DynamodbEvent loadDynamoDbEvent(String filename) { return loadEvent(filename, DynamodbEvent.class); } + public static DynamodbEvent.DynamodbStreamRecord loadDynamoDbStreamRecord(String filename) { + return loadEvent(filename, DynamodbEvent.DynamodbStreamRecord.class); + } + public static KafkaEvent loadKafkaEvent(String filename) { return loadEvent(filename, KafkaEvent.class); } diff --git a/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java b/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java index e36016a1..3177b9cc 100644 --- a/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java +++ b/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java @@ -160,27 +160,43 @@ public void testLoadSNSEvent() { @Test public void testLoadDynamoEvent() { - DynamodbEvent event = EventLoader.loadDynamoDbEvent("dynamo_event.json"); + DynamodbEvent event = EventLoader.loadDynamoDbEvent("ddb/dynamo_event.json"); assertThat(event).isNotNull(); assertThat(event.getRecords()).hasSize(3); + assertDynamoDbStreamRecord(event.getRecords().get(1)); + } - DynamodbEvent.DynamodbStreamRecord record = event.getRecords().get(0); + @Test + public void testLoadDynamoDbStreamRecord() { + assertDynamoDbStreamRecord(EventLoader.loadDynamoDbStreamRecord("ddb/dynamo_ddb_stream_record.json")); + } + + private static void assertDynamoDbStreamRecord(final DynamodbEvent.DynamodbStreamRecord record) { assertThat(record) + .isNotNull() .returns("arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", from(DynamodbEvent.DynamodbStreamRecord::getEventSourceARN)) - .returns("INSERT", from(Record::getEventName)); + .returns("MODIFY", from(Record::getEventName)); StreamRecord streamRecord = record.getDynamodb(); assertThat(streamRecord) - .returns("4421584500000000017450439091", StreamRecord::getSequenceNumber) - .returns(26L, StreamRecord::getSizeBytes) + .returns("4421584500000000017450439092", StreamRecord::getSequenceNumber) + .returns(59L, StreamRecord::getSizeBytes) .returns("NEW_AND_OLD_IMAGES", StreamRecord::getStreamViewType) - .returns(Date.from(ofEpochSecond(1428537600)), StreamRecord::getApproximateCreationDateTime); - - assertThat(streamRecord.getKeys()).contains(entry("Id", new AttributeValue().withN("101"))); - assertThat(streamRecord.getNewImage()).containsAnyOf( - entry("Message", new AttributeValue("New item!")), - entry("Id", new AttributeValue().withN("101")) - ); + .returns(Date.from(ofEpochSecond(1635734407).plusNanos(123456789)), StreamRecord::getApproximateCreationDateTime); + + assertThat(streamRecord.getKeys()) + .isNotNull() + .contains(entry("Id", new AttributeValue().withN("101"))); + assertThat(streamRecord.getNewImage()) + .isNotNull() + .containsAnyOf( + entry("Message", new AttributeValue("This item has changed")), + entry("Id", new AttributeValue().withN("101"))); + assertThat(streamRecord.getOldImage()) + .isNotNull() + .containsAnyOf( + entry("Message", new AttributeValue("New item!")), + entry("Id", new AttributeValue().withN("101"))); } @Test diff --git a/aws-lambda-java-tests/src/test/resources/ddb/dynamo_ddb_stream_record.json b/aws-lambda-java-tests/src/test/resources/ddb/dynamo_ddb_stream_record.json new file mode 100644 index 00000000..f5df23ff --- /dev/null +++ b/aws-lambda-java-tests/src/test/resources/ddb/dynamo_ddb_stream_record.json @@ -0,0 +1,35 @@ +{ + "eventID": "c81e728d9d4c2f636f067f89cc14862c", + "eventName": "MODIFY", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "NewImage": { + "Message": { + "S": "This item has changed" + }, + "Id": { + "N": "101" + } + }, + "OldImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1.635734407123456789E9, + "SequenceNumber": "4421584500000000017450439092", + "SizeBytes": 59, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899" +} diff --git a/aws-lambda-java-tests/src/test/resources/dynamo_event.json b/aws-lambda-java-tests/src/test/resources/ddb/dynamo_event.json similarity index 97% rename from aws-lambda-java-tests/src/test/resources/dynamo_event.json rename to aws-lambda-java-tests/src/test/resources/ddb/dynamo_event.json index f28ce0e6..2e43ba49 100644 --- a/aws-lambda-java-tests/src/test/resources/dynamo_event.json +++ b/aws-lambda-java-tests/src/test/resources/ddb/dynamo_event.json @@ -59,7 +59,7 @@ "N": "101" } }, - "ApproximateCreationDateTime": 1428537600, + "ApproximateCreationDateTime": 1.635734407123456789E9, "SequenceNumber": "4421584500000000017450439092", "SizeBytes": 59, "StreamViewType": "NEW_AND_OLD_IMAGES"