serverless-java-container icon indicating copy to clipboard operation
serverless-java-container copied to clipboard

Exception when triggering Lambda based API from Cloudwatch Events

Open srp321 opened this issue 5 years ago • 11 comments

To help us debug your issue fill in the basic information below using the options provided

Serverless Java Container version: 1.5.1

Implementations: Spring Boot 2

Framework version: SpringBoot 2.2.6.RELEASE

Frontend service: AWS Cloudwatch Events

Deployment method: Console

Scenario

I'm trying to schedule a trigger for an API which I have written in Java and deployed in Lambda. Another purpose of this to avoid the cold start as I'm not using provisioned concurrency for my Lambda. I'm not sure what event to pass so that my API gets triggered properly

Expected behavior

I expect the API endpoint to be hit at a specific time and it should do what is implemented

Actual behavior

Since I don't know what even to pass to my trigger so I'm gettings exceptions in my lambda cloudwatch logs

Steps to reproduce

No code sample required, just create any Java-based Spring boot API on lambda and attach a scheduled cloudwatch event to it. It will give exceptions in the cloudwatch logs.

Full log output

2020-07-22 18:17:04.935 ERROR 1 --- [           main] c.a.s.proxy.AwsProxyExceptionHandler     : Called exception handler for:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "id" (class com.amazonaws.serverless.proxy.model.HttpApiV2ProxyRequest), not marked as ignorable (12 known properties: "requestContext", "rawQueryString", "body", "queryStringParameters", "isBase64Encoded", "routeKey", "version", "stageVariables", "rawPath", "cookies", "headers", "pathParameters"])
at [Source: (lambdainternal.util.NativeMemoryAsInputStream); line: 1, column: 22] (through reference chain: com.amazonaws.serverless.proxy.model.HttpApiV2ProxyRequest["id"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61) ~[task/:na]

srp321 avatar Jul 22 '20 18:07 srp321

Hey @srp321, today this library only supports events from API Gateway. However, many customers are asking us to support other event sources. we are using #367 to track that effort. We'll post an RFC there this week.

sapessi avatar Jul 22 '20 18:07 sapessi

Can you share how you would like this to work? Would you want to handle the events from a @RequestMapping annotated method?

sapessi avatar Jul 22 '20 18:07 sapessi

@sapessi, so is there any workaround for now so that i don't get the errors in the cloudwatch?

srp321 avatar Jul 22 '20 18:07 srp321

You could create your own event-reader and response writer to translate the CloudWatch events into a ServletRequest. The process is documented in the wiki but it's a heavy lift.

sapessi avatar Jul 22 '20 18:07 sapessi

Can you share how you would like this to work? Would you want to handle the events from a @RequestMapping annotated method?

a simple example i am trying to use is as follows:

@GetMapping("/getStatus") public ResponseEntity<ResponseBean> getStatus() { return new ResponseEntity<>("Services are working", HttpStatus.OK); }

srp321 avatar Jul 22 '20 18:07 srp321

Can you share how you would like this to work? Would you want to handle the events from a @RequestMapping annotated method?

a simple example i am trying to use is as follows:

@GetMapping("/getStatus") public ResponseEntity<ResponseBean> getStatus() { return new ResponseEntity<>("Services are working", HttpStatus.OK); }

Thank you. That's helpful. The question is, you'd likely connect multiple event sources to a Java application. For example, you may have two different CloudWatch Events pointing to the same function. How do we decide which method should receive the events for one versus the other?

sapessi avatar Jul 22 '20 18:07 sapessi

Can you share how you would like this to work? Would you want to handle the events from a @RequestMapping annotated method?

a simple example i am trying to use is as follows: @GetMapping("/getStatus") public ResponseEntity<ResponseBean> getStatus() { return new ResponseEntity<>("Services are working", HttpStatus.OK); }

Thank you. That's helpful. The question is, you'd likely connect multiple event sources to a Java application. For example, you may have two different CloudWatch Events pointing to the same function. How do we decide which method should receive the events for one versus the other?

one of the purposes of this configured event is to keep to lambda warm as I have other APIs on that lambda which is connected with HTTP API through API gateway proxy. Even if I configure multiple events, the API (or rather the purpose) would be the same, i.e. to hit the API as sometimes few API's function as a batch job and just need a trigger to execute, nothing else.

srp321 avatar Jul 22 '20 18:07 srp321

one of the purposes of this configured event is to keep to lambda warm as I have other APIs on that lambda which is connected with HTTP API through API gateway proxy. Even if I configure multiple events, the API (or rather the purpose) would be the same, i.e. to hit the API as sometimes few API's function as a batch job and just need a trigger to execute, nothing else.

Understood, thanks. Seems like a common pattern among other customers too. Have you considered provisioned concurrency?

sapessi avatar Jul 22 '20 18:07 sapessi

one of the purposes of this configured event is to keep to lambda warm as I have other APIs on that lambda which is connected with HTTP API through API gateway proxy. Even if I configure multiple events, the API (or rather the purpose) would be the same, i.e. to hit the API as sometimes few API's function as a batch job and just need a trigger to execute, nothing else.

Understood, thanks. Seems like a common pattern among other customers too. Have you considered provisioned concurrency?

Yup, i thought of that as well and tried it a while back but i'm not so clear about the bill i see from the cost calculator so I didn't continue with it as of now.

srp321 avatar Jul 22 '20 18:07 srp321

Instead of calling the AWS Lambda directly from Eventbridge, for the time being, create an Eventbridge integration with API Gateway instead, which in turn calls the Lambda.

reik-wargaming avatar Dec 04 '20 09:12 reik-wargaming

Instead of calling the AWS Lambda directly from Eventbridge, for the time being, create an Eventbridge integration with API Gateway instead, which in turn calls the Lambda.

I thought of this, but unfortunately, my services are on HTTP APIs of API Gateway which is not supported by Eventbridge, so that's also not an option that I can use.

srp321 avatar Dec 04 '20 15:12 srp321