Skip to content

Chapter 6 JUnit Error: Cannot construct instance of com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification$S3EventNotificationRecord #187

Closed

Description

@stevenang

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"
                }
            }
        }
    ]
}

Activity

  1. jeromevdl commented on Dec 10, 2020

    @jeromevdl
    Contributor

    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:

    S3Event event = EventLoader.loadS3Event("s3_event.json");

    or

    @ParameterizedTest
    @Event(value="s3_event.json", type=S3Event.class)
    public void testHandler(S3Event event) {
     // ... test ...
    }
  2. adaly56 commented on Dec 31, 2022

    @adaly56

    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:

    S3Event event = EventLoader.loadS3Event("s3_event.json");

    or

    @ParameterizedTest
    @Event(value="s3_event.json", type=S3Event.class)
    public void testHandler(S3Event event) {
     // ... test ...
    }

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions