micronaut-aws icon indicating copy to clipboard operation
micronaut-aws copied to clipboard

SQSEvent.getRecords() returns null for my Lambda's RequestHandler

Open bnegrao opened this issue 2 years ago • 6 comments

Description

I used the mn cli to help me creating a simple lambda to be triggered by SQS. I changed the generated code to make it receive SQSEvent instead of the API Gateway request.

After building the navite image and uploading it to AWS, when I trigger the lambda using a "SQSEvent" json, the lambda throws exception. I added some debugging code and I noticed that the SQSEvent.getRecords() method is returning null. It looks like some deserialization issue is happening.

It looks like this guy on stackoverflow had the same issue and he created a workaround to solve it. But I'm not satisfied with his solution.

Steps to reproduce

Created a simple lambda with this command:

mn create-function-app com.perch.micronaut-lambda-sqs \
    --features=aws-lambda,graalvm \
    --build=gradle --lang=java

Update the FunctionRequestHandler to make it receive an SQSEvent instead of API Gateway event.

package com.perch;

import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.micronaut.function.aws.MicronautRequestHandler;
import jakarta.inject.Inject;
public class FunctionRequestHandler extends MicronautRequestHandler<SQSEvent, Void> {
    @Inject
    ObjectMapper objectMapper;

    @Override
    public Void execute(SQSEvent sqsEvent) {
        if (sqsEvent == null){
            throw new RuntimeException("sqsEvent cannot be null");
        }
        System.out.println(sqsEvent);
        if (sqsEvent.getRecords() == null) {
            throw new RuntimeException("getRecords() cannot return null");
        }
        if (sqsEvent.getRecords().isEmpty()){
            throw new RuntimeException("getRecords() cannot return an empty list");
        }
        for (SQSEvent.SQSMessage sqsMessage: sqsEvent.getRecords()){
            System.out.println(sqsMessage);
        }
        return null;
    }
}

I created a template.yml file to be able to invoke locally with aws's "sam cli", and I receive the following error (the same that happens if I deploy the code to AWS):

$ sam.cmd local invoke -e events/NewUserSqsMessage.json            
Invoking com.perch.FunctionRequestHandler (provided.al2)
Decompressing C:\Users\bnegrao\perch\micronaut-lambda-sqs\build\libs\micronaut-lambda-sqs-0.1-lambda.zip
Skip pulling image and use local one: public.ecr.aws/sam/emulation-provided.al2:rapid-1.55.0-x86_64.

Mounting C:\Users\bnegrao\AppData\Local\Temp\tmprtx130gq as /var/task:ro,delegated inside runtime container
START RequestId: 6ef8dd47-e727-4992-97b7-50ca928fde45 Version: $LATEST
16:15:52.041 [main] INFO  i.m.context.env.DefaultEnvironment - Established active environments: [ec2, cloud, function, lambda]
{}
Invocation with requestId [6ef8dd47-e727-4992-97b7-50ca928fde45] failed: getRecords() cannot return nulljava.lang.RuntimeException: getRecords() cannot return nul
l
        at com.perch.FunctionRequestHandler.execute(FunctionRequestHandler.java:18)
        at com.perch.FunctionRequestHandler.execute(FunctionRequestHandler.java:7)
        at io.micronaut.function.aws.MicronautRequestHandler.handleRequest(MicronautRequestHandler.java:128)
        at io.micronaut.function.aws.runtime.AbstractMicronautLambdaRuntime.startRuntimeApiEventLoop(AbstractMicronautLambdaRuntime.java:356)
        at io.micronaut.function.aws.runtime.AbstractMicronautLambdaRuntime.run(AbstractMicronautLambdaRuntime.java:137)
        at com.perch.FunctionLambdaRuntime.main(FunctionLambdaRuntime.java:13)

END RequestId: 6ef8dd47-e727-4992-97b7-50ca928fde45
REPORT RequestId: 6ef8dd47-e727-4992-97b7-50ca928fde45  Init Duration: 0.24 ms  Duration: 2378.24 ms    Billed Duration: 2379 ms        Memory Size: 512 MB     Ma
x Memory Used: 512 MB
{"errorMessage":"getRecords() cannot return null"}

The NewUserSqsMessage.json file is this:

{
  "Records": [
    {
      "messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78",
      "receiptHandle": "MessageReceiptHandle",
      "body": "{\"toAddress\":\"[email protected]\"}",
      "attributes": {
        "ApproximateReceiveCount": "1",
        "SentTimestamp": "1523232000000",
        "SenderId": "123456789012",
        "ApproximateFirstReceiveTimestamp": "1523232000001"
      },
      "messageAttributes": {},
      "md5OfBody": "{{{md5_of_body}}}",
      "eventSource": "aws:sqs",
      "eventSourceARN": "arn:aws:sqs:us-east-1:123456789012:MyQueue",
      "awsRegion": "us-east-1"
    }
  ]
}

Example that reproduces the problem uploaded to Github

https://github.com/bnegrao/micronaut-lambda-sqs

Expected Behaviour

I would be able to iterate and print the records (List<SQSEvent.SQSMessage>) from the event.

Actual Behaviour

sqsEvent.getRecords() returns null instead of returning a list with one element.

Environment Information

  • Operating System: windows.
  • Micronaut Version: 3.6.1
  • JDK Version: graalvm-ce-java17-22.2.0

Example Application

  • https://github.com/bnegrao/micronaut-lambda-sqs

bnegrao avatar Aug 31 '22 16:08 bnegrao

+1 same issue - https://github.com/micronaut-projects/micronaut-aws/issues/102#issuecomment-1233238563

storytime avatar Aug 31 '22 18:08 storytime

+1

pablohaedo avatar Feb 14 '23 13:02 pablohaedo

+1

kieranjen avatar Mar 23 '23 09:03 kieranjen

+1

rahman avatar Mar 23 '23 09:03 rahman

  • 1

prashantcodecraft avatar Jul 25 '23 12:07 prashantcodecraft

Is there any update on this issue? We faced the same with DynamodbEvent when processing events from a DynamoDb stream, but this issue occured only after the upgrade to Micronaut 4

DushanNovak1983 avatar Aug 28 '23 09:08 DushanNovak1983