2

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   

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @Marcin for replying, but @ the shared link above, content tag nowhere exists and I did tried with the format, still the same error. I am editing the question for better clarity.
This doesn't really answer his question. Yes, obviously his request is not correctly formed. So what form should it be? Linking to Byzantine documentation, which seems to imply his event JSON is correct, is not super helpful.
0

Not sure why you accepted @marcin's non-answer, but for anyone else who stumbled across this, the actual solution is to format your aws-cli payload like {"body": "<actual payload json formatted as a string>"} so it mimics the API-Gateway payload.

e.g.

aws lambda invoke --function-name <function_name> --payload '{
"body": "{\"id\": 1004, \"itemName\": \"HoneyAlmondFlakes\", \"quantity\": 7}"

}' response.json --cli-binary-format raw-in-base64-out

Note, you're not wrapping your JSON object in another object. You're encoding it as a string and passing it in an object attached to the "body" key.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.