-
Notifications
You must be signed in to change notification settings - Fork 559
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NullPointerException if calling Lambda via CloudWatch event #237
Comments
What does the scheduled event do? Does it invoke the same Lambda function or does it send an HTTP request? |
It invokes the same Lambda function. |
Ok. I'll add a null check for this particular exception. However, this framework is only meant to work with API Gateway or ALB proxy events, it will not recognize events from other sources (such as CloudWatch scheduled events). To make this work, you will either have to implement your own |
Is there any examples how to handle this? As I understand right now there is single entry point |
I'm assuming you are using the scheduled event just to keep the function "warm". If that's the case, I would probably recommend just catching the exception and returning successfully. Even though there is an exception, you are achieving your goal which is to force Lambda to keep instances of the function around. The most important this to remember is to catch the exception and exit the function successfully. If you don't, Lambda will treat a cold start exception as an initialization failure and will discard the instance of the function. |
…ain an HTTP method and a request context we throw an . This addresses #237 by making the error more explicit.
@sapessi Thanks for a important note about function exit! However I am genuinely interested in able to use all 3 types of events in Spring Boot application deployed as AWS Lambda - event (SNS) processing, cron tasks, API gw endpoints |
Understood. I'll write a short version of the steps here. I'll use this issue to remind myself to expand the docs on how to achieve this. In the examples below I use the StreamHandler instead of the typed one because Lambda's built-in serialization mechanism does not support Jackson annotations. This frameworks uses a Jackson instance with annotations to parse the authorizer context in the proxy event. Also, I wrote the Java code below directly in the GitHub comment window so forgive me for typos/errors and missing try/catch. You have a couple of options: public class StreamLambdaHandler implements RequestStreamHandler {
private static SpringLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
static {
try {
handler = SpringLambdaContainerHandler.getAwsProxyHandler(PetStoreSpringAppConfig.class);
} catch (ContainerInitializationException e) {
// if we fail here. We re-throw the exception to force another cold start
e.printStackTrace();
throw new RuntimeException("Could not initialize Spring framework", e);
}
}
@Override
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
throws IOException {
// use Apache IOUtils to read the full contents of the stream to a String so that we can
// re-use it multiple times.
StringWriter eventWriter = new StringWriter();
IOUtils.copy(inputStream, eventWriter, LambdaContainerHandler.getContainerConfig().getDefaultContentCharset());
String eventString = writer.toString();
// next, we try to deserialize this into the various event types
AwsProxyRequest req = LambdaContainerHandler.getObjectMapper().readValue(eventString, AwsProxyRequest.class);
if (req.getHttpMethod() == "" or "".equals(req.getHttpMethod()) { // it's not a proxy request event
SNSEvent sns = LambdaContainerHandler.getObjectMapper().readValue(eventString, SNSEvent.class);
if (isValidSnsEvent(sns)) { // logic for this up to you
req = snsEventToRequest(sns); // also up to you
}
}
AwsProxyResponse resp = handler.proxy(req, context);
LambdaContainerHandler.getObjectMapper().writeValue(outputStream, resp);
}
} Option 2 While option 2 seems cleaner and more Java-ish, it involves a lot more code. For a simple solution, I would probably opt for option 1. |
@sapessi Thanks for a thorough description! |
Added workaround so SNS/SQS/CloudWatch events are not sent through to AWSProxy code as-is. Good idea to convert them to AwsProxyRequest but I think such logic is heavily application-depended (i.e. which endpoint to hit?) or can/need to be configured somehow. |
@huksley I've added a new page to the docs about supporting custom event types. Hopefully this helps explain what is happening behind the scenes |
@sapessi Thanks! Really appreciated it! Maybe you are too much verbose but there is no such thing for docs) |
Is the doc for custom event still valid?
I can not return an object AwsProxyHttpServletRequest because instantiating it requires the first argument as AwsProxyRequest and needs a custom HttpServletRequest. I have to create a custom HttpServletRequest. I also encountered an "Cannot infer type arguments for SpringBootLambdaContainerHandler<>" error. Here's a link. Maybe you guys would like to check out just in case: https://github.com/franciszabala/aws-lambda-springboot2.0 |
Hi @franciszabala. Yes, the docs are still valid. The You have a couple of options:
|
Scenario
Adding following event to MyServiceFunction
results in NullPointerException generated when CloudWatch periodically calls Lambda at AwsProxyHttpServletRequestReader.java:48
Expected behavior
No NullPointerException in Cloudformation logs
Actual behavior
Actually running Lambda + provide some way to execute code on such event.
Steps to reproduce
Add event to sam.yaml, deploy, observe CloudWatch logstream.
Full log output
The text was updated successfully, but these errors were encountered: