Repository navigation
Chapter 6 JUnit Error: Cannot construct instance of com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification$S3EventNotificationRecord #187
Copy link
Copy link
Closed
Description
An error occurred when running the JUnit codes of the Chapter 6 Lab.
Here is the full details of the error log:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification$S3EventNotificationRecord` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (BufferedInputStream); line: 4, column: 13] (through reference chain: com.amazonaws.services.lambda.runtime.events.S3Event["Records"]->java.util.ArrayList[0])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1750)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1211)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1400)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:311)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:243)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:324)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:187)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4568)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3560)
at tw.idv.stevenang.pipeline.bulk.BulkEventFunctionTest.testHandler(BulkEventFunctionTest.java:40)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.contrib.java.lang.system.EnvironmentVariables$EnvironmentVariablesStatement.evaluate(EnvironmentVariables.java:122)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:258)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Process finished with exit code 255
and my java coses:
@Test
public void testHandler() throws IOException {
// Set up mock AWS SDK clients
AmazonSNS mockSNS = Mockito.mock(AmazonSNS.class);
AmazonS3 mockS3 = Mockito.mock(AmazonS3.class);
AmazonSQS mockSQS = Mockito.mock(AmazonSQS.class);
// Fixture S3 event
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
S3Event s3Event = objectMapper.readValue(
getClass().getResourceAsStream("/s3_event.json"),
S3Event.class
);
String bucket = s3Event.getRecords().get(0).getS3().getBucket().getName();
String key = s3Event.getRecords().get(0).getS3().getObject().getKey();
// Fixture S3 return value
S3Object s3Object = new S3Object();
s3Object.setObjectContent(getClass().getResourceAsStream(String.format("/%s", key)));
Mockito.when(mockS3.getObject(bucket, key)).thenReturn(s3Object);
// Fixture environment
String topic = "test-topic";
environment.set(BulkEventsLambda.FAN_OUT_TOPIC_ENV, topic);
// Construct Lambda function class, and invoke handler
BulkEventsLambda lambda = new BulkEventsLambda(mockSNS, mockS3, mockSQS);
lambda.handlerRequest(s3Event);
// Capture outbound SNS messages
ArgumentCaptor<String> topics = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> messages = ArgumentCaptor.forClass(String.class);
Mockito.verify(mockSNS, Mockito.times(3)).publish(topics.capture(), messages.capture());
// Assert
Assert.assertArrayEquals(new String[]{topic, topic, topic}, topics.getAllValues().toArray());
Assert.assertArrayEquals(new String[]{
"{\"locationName\":\"Brooklyn, NY\",\"temperature\":91.0,\"timestamp\":1564428897,\"longitude\":-73.99,\"latitude\":40.7}",
"{\"locationName\":\"Oxford, UK\",\"temperature\":64.0,\"timestamp\":1564428898,\"longitude\":-1.25,\"latitude\":51.75}",
"{\"locationName\":\"Charlottesville, VA\",\"temperature\":87.0,\"timestamp\":1564428899,\"longitude\":-78.47,\"latitude\":38.02}"
}, messages.getAllValues().toArray());
}and here is the s3_event.json I am trying to used to create a s3 event:
{
"Records": [
{
"eventVersion": "2.0",
"eventSource": "aws:s3",
"awsRegion": "us-east-1",
"eventTime": "1970-01-01T00:00:00.000Z",
"eventName": "ObjectCreated:Put",
"userIdentity": {
"principalId": "EXAMPLE"
},
"requestParameters": {
"sourceIPAddress": "127.0.0.1"
},
"responseElements": {
"x-amz-request-id": "EXAMPLE123456789",
"x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
},
"s3": {
"s3SchemaVersion": "1.0",
"configurationId": "testConfigRule",
"bucket": {
"name": "example-bucket",
"ownerIdentity": {
"principalId": "EXAMPLE"
},
"arn": "arn:aws:s3:::example-bucket"
},
"object": {
"key": "bulk_data.json",
"size": 1024,
"eTag": "0123456789abcdef0123456789abcdef",
"sequencer": "0A1B2C3D4E5F678901"
}
}
}
]
}
Reactions are currently unavailable
Activity
jeromevdl commentedon Dec 10, 2020
Hi,
You cannot simply deserialize a S3 JSON Event directly with an ObjectMapper. Indeed the Java Lambda Runtime has some advanced (de)serialization mechanism. You can use aws-lambda-java-serialization to deserialize the event correctly.
Or simpler, we just released a test module: aws-lambda-java-tests. With this last one you just need to do:
or
adaly56 commentedon Dec 31, 2022
I did the same tutorial as this - and mine worked within the Maven env as set up by tutorial. It is directly from the book Chapin and Robert's 'Programming AWS Lambda'. No problem exactly as is . The book's solution on github worked also. So the objectMapper did deserialise the event. However when I ported the solution to a different project that was set up with gradle it failed with this error. I think it is due to the library version being used for the gradle build just checking now. Will update. Appreciate this is closed but has been annoying error for me too. I will however checkout the aws lamda-java-serialization rep thank you for that.