带有POJO和Lambda函数的AWS Lambda JAVA函数返回'null'

时间:2017-12-10 10:37:21

标签: json xmlhttprequest aws-lambda aws-api-gateway

目前我正在开发一个迷你项目,我正在设计一个在S3中托管的静态网站。有一个“上传”页面,用户可在其中输入姓名,电子邮件和手机号码和文件,然后点击“上传”按钮调用API网址终端。我创建了API网关url端点“https://myAPIName.execute-api.ap-region-1.amazonaws.com/Testing/TestinLambda2”,我在其上使用XMLHTTPRequest调用post请求并像这样发送 -

    xhttp.open("POST", "https://myAPIName.execute-api.ap-region-1.amazonaws.com/Testing/TestinLambda2", true);
xhttp.send(JSON.stringify({Name:$('#Name').val(),Email:$('#email').val(),MobileNo:$('#mno').val()}));

我将数据作为JSON输入发送到aws lambda Java函数。

我还没有在AWS API网关中完成任何正文映射设置。

回到AWS方面,我正在使用AWS Lambda Java函数使用POJO。以下是我从AWS lambda文档中获取的类 -

我的Lambda函数

package com.amazonaws.lambda.demo;

import java.util.Map;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

public class FirstLambda implements RequestHandler<InputClass, OutputClass> {

    @Override
    public OutputClass handleRequest(InputClass input, Context context) {
        String greetingString = String.format("Hello %s, %s , %s.", input.getName(), input.getEmail(), input.getMobile());
         //String greetingString = String.format("Hello");
         return new OutputClass(greetingString);
    }

}

我的输入类

package com.amazonaws.lambda.demo;

public class InputClass {

    String Name;
    String Email;
    String MobileNo;

    public String getName(){
        return this.Name;
    }

    public String getEmail(){
        return this.Email;
    }

    public String getMobile(){
        return this.MobileNo;
    }

    public void setName(String Name){
        this.Name = Name;
    }

    public void setEmail(String Email){
        this.Email = Email;
    }

    public void setMobile(String Mobile){
        this.MobileNo = Mobile;
    }

    public InputClass(){

    }

    public InputClass(String Name, String Email, String Mobile){
        this.Name = Name;
        this.Email = Email;
        this.MobileNo = Mobile;
    }
}

我的输出类

public class OutputClass {

    String greetings;

    public String getStrings()
    {
        return greetings;
    }

    public void setString()
    {
        this.greetings = greetings;
    }

    public OutputClass(String greetings)
    {
        this.greetings = greetings;
    }

    public OutputClass()
    {

    }
}

当我点击“上传”按钮时,我将屏幕上的值设为 -

{"strings":"Hello null, null , null."}

这与使用“Test”选项在API网关中测试POST方法时获得的值相同。

如果有人可以指出我在这里缺少什么,我真的很感激。

非常感谢!

3 个答案:

答案 0 :(得分:1)

杰拉德(Gerards)尝试重现问题的原因不起作用,是因为他使用测试事件而不是通过apigateway进行了尝试。

这里发生的是,当您通过网关调用lambda时,您发送的整个json封装在另一个对象中,该对象具有其他详细信息,例如pathparameters和其他相关详细信息。 为了对此进行测试,您可以创建一个新的POJO并将InputClass作为其中的成员。将lambda参数更改为新的POJO,然后再次通过api网关调用lambda。

这将为您提供所需的数据。

答案 1 :(得分:0)

为了简单起见,我使用您使用Lambda测试事件代替API网关提供的类对此进行了测试,修复程序也应该继续使用您的JavaScript。

似乎无论你如何命名代码中的类变量,JSON中的参数都必须遵循getter / setter的名称。只需更正代码中的属性即可解决问题。这是有道理的,因为无法从包外部访问类变量。所以你必须遵循mutator方法的名称。

xhttp.open("POST", "https://myAPIName.execute-api.ap-region-1.amazonaws.com/Testing/TestinLambda2", true);
xhttp.send(JSON.stringify({name: $('#Name').val(), email: $('#email').val(), mobile: $('#mno').val()}));

以下有效负载:

{
  "Name": "Gerard",
  "Email": "abc@123.com",
  "MobileNo": "8675309"
}

生成

{"strings":"Hello null, null , null."}

此有效载荷

{
  "name": "Gerard",
  "email": "abc@123.com",
  "mobile": "8675309"
}

产生预期的响应:

{"strings": "Hello Gerard, abc@123.com , "8675309"."}

答案 2 :(得分:0)

如果您的AWS Lambda位于API网关后面,则网关将转换传入的有效负载并将其以其他格式(您可能期望的格式)传递到AWS Lambda。

它添加有关请求的一些元数据(例如标头),并将所有内容包装为JSON,格式如下:

{
 "headers": {} 
 "body": ""
 ...
}

此JSON传递到Java AWS Lambda函数。您可以通过使用以下签名临时调整RequestHandler来查看一下:

public class FirstLambda implements RequestHandler<Map<String, Object>, OutputClass> {

    @Override
    public OutputClass handleRequest(Map<String, Object> input, Context context) {
         input.forEach((key, value) -> System.out.println(key + ":" + value);
         return new OutputClass("");
    }

}

每当您使用AWS控制台并使用简单的有效负载(例如

)发送测试事件时
{
  "Name": "Duke",
  "Email": "mail@whatever.io"
}

反映当您使用API​​网关调用Lambda时收到的有效负载,例如卷发或邮递员。

因此,在您的情况下,应使用Jackson或GSON将有效载荷的String字段内的body序列化到您的POJO。

如果您不想使用通用Map,也可以添加

<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-lambda-java-events</artifactId>
  <version>3.1.0</version>
</dependency>

转到您的项目,并使用APIGatewayProxyRequestEventAPIGatewayProxyResponseEvent包装器类以及访问标头,正文等。

public class FirstLambda implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEventinput, Context context) {
         System.out.println(input.getBody());

        // e.g. use the ObjectMapper from Jackson to parse the String body to your POJO
         APIGatewayProxyResponseEvent result = new APIGatewayProxyResponseEvent();
         result.setStatusCode(200);
         result.setBody(objectMapper.writeValueAsString(new OutputClass(""));
         return result;
    }

}

另一种解决方案是调整API网关将数据传递到Lambda函数的方式,如here

所述