【问题标题】:AWS Serverless Requests - JSON body / httpMethod is always nullAWS 无服务器请求 - JSON 正文/httpMethod 始终为空
【发布时间】:2021-05-29 14:16:48
【问题描述】:

当我发送 POST 请求时,我从 input.getBody()input.getHttpMethod() 收到 NullPointerException。我没有定义映射模板 - 默认设置为 当没有模板与请求 Content-Type 标头匹配时

我的 POST 请求

{
    "shiftStart": "22/02/2021 18:00:00",
    "shiftEnd": "22/02/2021 19:00:00",
    "employee": {
        "id": "6",
        "firstName": "Joe",
        "lastName": "Brown"
    }
}

一旦我得到这个异常,它看起来就像 input.getHttpMethod() 传递了一次:

{
    "errorMessage": "BODY",
    "errorType": "java.lang.NullPointerException",
    "stackTrace": [
        "helloworld.App.handleRequest(App.java:48)",
        "java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
        "java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)",
        "java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)",
        "java.base/java.lang.reflect.Method.invoke(Unknown Source)"
    ]
}

但我没有改变任何东西,现在我得到以下异常:

{
    "errorMessage": "java.lang.NullPointerException",
    "errorType": "java.lang.NullPointerException",
    "stackTrace": [
        "helloworld.App.handleRequest(App.java:41)",
        "java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
        "java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)",
        "java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)",
        "java.base/java.lang.reflect.Method.invoke(Unknown Source)"
    ]
}

我的班级:

public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

    @Override
    public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {

        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("X-Custom-Header", "application/json");

        APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
                .withHeaders(headers);

        AmazonDynamoDB client = AmazonDynamoDBClientBuilder.defaultClient();
        DynamoDBMapper mapper = new DynamoDBMapper(client);

        Shift shift;
        String output;

        if (input.getHttpMethod().equalsIgnoreCase(HttpMethod.GET.name())) {
            shift = mapper.load(Shift.class, context.getAwsRequestId());
            if (shift == null) {
                throw new ResourceNotFoundException("Resource not found");
            }
            output = shift.toString();
        } else if (input.getHttpMethod().equalsIgnoreCase(HttpMethod.POST.name())) {
            if (input.getBody() == null) throw new NullPointerException("BODY");
            shift = new Shift(input.getBody());
            WorkSchedule workSchedule = new WorkSchedule(client);
            if (!workSchedule.isShiftPossible(shift)) {
                throw new ConditionalCheckFailedException("Conditional check failed");
            }
            mapper.save(shift);
            output = "SHIFT SAVED";
        } else {
            output = "Unsupported operation";
        }

        return response
                .withStatusCode(200)
                .withBody(output);
    }
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@DynamoDBTable(tableName = "WORK_SCHEDULE")
public class Shift {

    public Shift(String json) {
        Gson gson = new Gson();
        Shift request = gson.fromJson(json, Shift.class);
        this.id = request.getId();
        this.shiftStart = request.getShiftStart();
        this.shiftEnd = request.getShiftEnd();
        this.employee = request.getEmployee();
    }

    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
    private String id;

    @DynamoDBAttribute
    private String shiftStart;

    @DynamoDBAttribute
    private String shiftEnd;

    @DynamoDBAttribute
    private Employee employee;

    @Override
    public String toString() {
        return "Shift{" +
                "id='" + id + '\'' +
                ", shiftStart='" + shiftStart + '\'' +
                ", shiftEnd='" + shiftEnd + '\'' +
                ", employee=" + employee +
                '}';
    }
}
@Getter
@Setter
@AllArgsConstructor
@DynamoDBDocument
public class Employee {

    private String id;
    private String firstName;
    private String lastName;

    @Override
    public String toString() {
        return "Employee{" +
                "id='" + id + '\'' +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                '}';
    }
}

【问题讨论】:

  • 您已在 ApiGateway IntegrationRequest 中启用代理集成?
  • @BaluVyamajala 我启用了这个并且我的 POST 请求现在正在工作,但是当我尝试执行 GET 请求时,响应是:“消息”:“内部服务器错误”。你能检查我的 GET if 语句吗? - 是否正确:shift = mapper.load(Shift.class, context.getAwsRequestId());
  • 太棒了!!现在对于 GET,‘context.getAwsRequestId()’将只有一个由 AWS 生成的 UUID。我猜你需要来自路径或查询参数的东西,不是这个?它们应该是“输入”本身而不是“上下文”的一部分
  • @BaluVyamajala 首先我更改了 mapper.load(Shift.class, context.getAwsRequestId());转移 = mapper.load(Shift.class, input.getQueryStringParameters());然后我改变了 shift = mapper.load(Shift.class, input.getPathParameters());。他们都给我“内部服务器错误”。
  • 您能否打印input.toString() 并查看您是否按预期获得了参数值。 getQueryStringParameters 和 getPathParameters 也返回一个 Map,您可能需要获取值并将其传递给 mapper.load

标签: java amazon-web-services rest http aws-lambda


【解决方案1】:

Api Gateway 有两种基本类型的 Lambda 集成 LAMBDA 和 LAMBDA_PROXY。

常规 LAMBDA 将按原样通过请求正文。

如果我们在集成请求中启用Use Lambda Proxy integration,它将是 LAMBDA_PROXY,这将通过包装其他详细信息(如 queryParms、Api Keys、Http Headers、方法类型等)来传递请求,这些信息可以序列化为 APIGatewayProxyRequestEvent类。

queryStringParameters 与 queryParms。

body 以 Json 正文为字符串。

pathParameters 带路径参数。

所以,在这种情况下,我们只需要启用Use Lambda Proxy integration

【讨论】:

    猜你喜欢
    • 2021-11-27
    • 2021-02-01
    • 2015-09-08
    • 1970-01-01
    • 2016-10-10
    • 2016-06-01
    • 2020-02-10
    • 2019-03-08
    • 2018-04-26
    相关资源
    最近更新 更多