amazon-web-servicesaws-lambdaaws-cloudformationaws-api-gatewayaws-sam-cli

AWS Lambda parameter passing error | API Gateway


I am working with a simple AWS Lambda function :

public class CreateOrderLambda {

    private final ObjectMapper objectMapper = new ObjectMapper();
    // This Particular Order needs to be saved to the DynamoDB.

    private final DynamoDB dynamoDB = new DynamoDB(AmazonDynamoDBClientBuilder.defaultClient());

    public APIGatewayProxyResponseEvent createOrder(final APIGatewayProxyRequestEvent input,
                                                    final Context context)
            throws JsonProcessingException {

        Order thisOrder = objectMapper.readValue(input.getBody(), Order.class);

Now, Here is how the template looks like :-

  CreateOrdersFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabspw/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: ordersapi
      Handler: com.aditya.learn.function.CreateOrderLambda::createOrder
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref OrdersTable
      Events:
        OrderEvents:
          Type: Api
          Properties:
            Path: /orders
            Method: POST

While I hit the aforesaid API through API Gateway, I am able to execute the request well :-

curl --location --request POST 'https://o2cf5ti7ik.execute-api.us-east-1.amazonaws.com/Prod/orders/' \
--header 'Content-Type: application/json' \
--data-raw '{
    "id":1001,
    "itemName":"Nariyal",
    "quantity":3
}'

enter image description here

But, while testing the Lambda standalone from console with following request :

{
  "id": 1004,
  "itemName": "HoneyAlmondFlakes",
  "quantity": 7
}

It gives following error :-

START RequestId: 63aa8edd-38b3-408e-8727-652393964f14 Version: $LATEST
argument "content" is null: java.lang.IllegalArgumentException
java.lang.IllegalArgumentException: argument "content" is null
    at com.fasterxml.jackson.databind.ObjectMapper._assertNotNull(ObjectMapper.java:4757)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3515)
    at com.aditya.learn.function.CreateOrderLambda.createOrder(CreateOrderLambda.java:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)

END RequestId: 63aa8edd-38b3-408e-8727-652393964f14
REPORT RequestId: 63aa8edd-38b3-408e-8727-652393964f14  Duration: 4.72 ms   Billed Duration: 5 ms   Memory Size: 512 MB Max Memory Used: 134 MB 

Basically, it's not able to typecast the request into the custom object.

enter image description here

Is the API0Gateway passing the request to Lambda in some special way ? What am I missing in testing the Lambda standalone ?

Any help shall be highly appreciated.

Basis of Marcin's response :-

Tried with following structure of event :-

{
      "resource": "/",
      "path": "/",
      "httpMethod": "POST",
      "requestContext": {
          "id":7,
          "itemName":"Flakes",
          "quantity":6,
          "resourcePath": "/",
          "httpMethod": "POST",
          "path": "/Prod/",
          "requestId": "JKJaXmPLvHcESHA=",
          "time": "23/Jan/2021:05:16:23 +0000"
      },
      "headers": {
          "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
          "accept-encoding": "gzip, deflate, br",
          "Host": "70ixmpl4fl.execute-api.us-east-2.amazonaws.com",
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36",
          "X-Amzn-Trace-Id": "Root=1-5e66d96f-7491f09xmpl79d18acf3d050"
      },
      "multiValueHeaders": {
          "accept": [
              "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
          ],
          "accept-encoding": [
              "gzip, deflate, br"
          ]
      },
    "isBase64Encoded": false
  }

Still same error :-

START RequestId: 028d4942-f2cf-4dbc-afe3-08783a106555 Version: $LATEST
argument "content" is null: java.lang.IllegalArgumentException
java.lang.IllegalArgumentException: argument "content" is null
    at com.fasterxml.jackson.databind.ObjectMapper._assertNotNull(ObjectMapper.java:4757)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3515)
    at com.aditya.learn.function.CreateOrderLambda.createOrder(CreateOrderLambda.java:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)

END RequestId: 028d4942-f2cf-4dbc-afe3-08783a106555
REPORT RequestId: 028d4942-f2cf-4dbc-afe3-08783a106555  Duration: 371.97 ms Billed Duration: 372 ms Memory Size: 512 MB Max Memory Used: 134 MB Init Duration: 2568.48 ms   

Solution

  • Lambda standalone from console

    The event that you get in your lambda function from API, and the one used when you run the function from the console are different. The event from api passed to your function will have a fixed known format. But when you run the function from console, you are passing the event in the incorrect format, thus it all breaks.

    You have to ensure that your event structure used when you run the code in console matches the event structure from the API format.