////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
////
= Quarkus - Amazon Lambda

include::./attributes.adoc[]


The `quarkus-amazon-lambda` extension allows you to use Quarkus to build your Amazon Lambda's.
Your lambdas can use injection annotations from CDI or Spring and other Quarkus facilities as you need them.

Quarkus lambdas can be deployed using the Amazon Java Runtime, or you can build a native GraalVM executable and use
Amazon's Custom Runtime if you want a smaller memory footprint and faster cold boot startup time.

== Prerequisites

To complete this guide, you need:

* less than 30 minutes
* JDK 1.8 (AWS requires JDK 1.8)
* Apache Maven 3.5.3+
* https://aws.amazon.com[An Amazon AWS account]
* https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html[AWS CLI]

== Getting Started

This guide walks you through generating an example Java project via a maven archetype and deploying it to AWS.

== Installing AWS bits

Installing all the AWS bits is probably the most difficult thing about this guide.  Make sure that you follow all the steps
for installing AWS CLI.

== Creating the Maven Deployment Project

Create the Quarkus AWS Lambda maven project using our Maven Archetype.


[source, subs=attributes+]
----
mvn archetype:generate \
       -DarchetypeGroupId=io.quarkus \
       -DarchetypeArtifactId=quarkus-amazon-lambda-archetype \
       -DarchetypeVersion={quarkus-version}
----

== Choose Your Lambda

The `quarkus-amazon-lambda` extension scans your project for a class that implements the Amazon `RequestHandler` interface.
It must find a class in your project that implements this interface, or it will throw a build time failure.
If it finds more than one handler class, a build time exception will also be thrown.

Sometimes though, you might have a few related lambdas that share a ton of code and creating multiple maven modules is just
an overhead you don't want to do.  The `quarkus-amazon-lambda` extension allows you to bundle multiple lambdas in one
project and use configuration or an environment variable to pick the handler you want to deploy.

The generated project has two lambdas within it.  One that is used, and one that is unused.  If you open up
`src/main/resources/application.properties` you'll see this:

[source, subs=attributes+]
----
quarkus.lambda.handler=test
----

The `quarkus.lambda.handler` property tells Quarkus which lambda handler to deploy. This can be overriden
with an environment variable too.

If you look at the two generated handler classes in the project, you'll see that they are `@Named` differently.

[source, subs=attributes+]
----
@Named("test")
public class TestLambda implements RequestHandler<InputObject, OutputObject> {

}

@Named("unused")
public class UnusedLambda implements RequestHandler<InputObject, OutputObject> {

}
----

The CDI name of the handler class must match the value specified within the `quarkus.lambda.handler` property.


== Deploy to AWS Lambda Java Runtime

There are a few steps to get your lambda running on AWS.  The generated maven project contains some helpful scripts to
create, update, delete, and invoke your lambdas for pure Java and native deployments.

== Build and Deploy

Build the project using maven.

[source, subs=attributes+]
----
mvn clean install
----

This will compile and package your code.

== Create an Execution Role

View the https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-awscli.html[Getting Started Guide] for deploying
a lambda with AWS CLI.  Specifically, make sure you have created an `Execution Role`.  You will need to copy and
paste the `Role Arn` into the scripts generated by the maven archetype.

== Edit Script Files

Edit the `create.sh` and `create-native.sh` scripts included with the generated project.  After the `--role` switch
replace the dummy `Role Arn` with the Arn of the `Execution Role` you created in the Amazon IAM console.

== Create the function

The `create.sh` script is for deploying your lambda using the AWS Lambda Java runtime.

.create.sh
[source, subs=attributes+]
----
aws lambda create-function --function-name my-function \
           --zip-file fileb://target/my-function-1.0-SNAPSHOT-runner.jar \
           --handler io.quarkus.amazon.lambda.runtime.QuarkusStreamHandler::handleRequest \
           --runtime java8 \
           --role arn:aws:iam::1234567:role/lambda-cli-role
----

Don't forget to replace the `--role` flag with the Arn of your `Execution Role`.

DO NOT CHANGE the handler switch.
This must be hardcoded to `io.quarkus.amazon.lambda.runtime.QuarkusStreamHandler::handleRequest`.  This Quarkus
handler bootstraps Quarkus and wraps your actual handler so that injection can be performed.

If there are any problems creating the function, you must delete it with the `delete.sh` script before re-running
the `create.sh` script.

== Invoke the Lambda

Use the `invoke.sh` script to invoke your function.

.invoke.sh
[source, subs=attributes+]
----
aws lambda invoke --function-name my-function
                  --payload file://payload.json out
                  --log-type Tail --query 'LogResult' --output text |  base64 -d
----

The example lambda takes input.  This input is passed in via the `--payload` switch which points to a json file
in the root directory of the project.  If you want to see the return output of the lambda, open the `out` file.
This script will also write the log output to the console.

== Update the Lambda

You can update the Java code as you see fit.  Once you've rebuilt, you can redeploy your lambda by executing the
`update.sh` script.

.update.sh
[source, subs=attributes+]
----
aws lambda update-function-code --function-name my-function \
           --zip-file fileb://target/my-function-1.0-SNAPSHOT-runner.jar
----

== Deploy to AWS Lambda Custom (native) Runtime

If you want a lower memory footprint and faster initialization times for your lambda, you can compile your Java
code to a native executable using GraalVM.  Just make sure to rebuild your project with the `-Dnative` switch.

== Build and Deploy (native)

Build the native executable.

[source, subs=attributes+]
----
mvn clean install -Dnative
----

This will compile and create a native executable image using GraalVM.  It also generates a zip file `target/function.zip`.
This zip file contains your native executable image renamed to `bootstrap`.  This is a requirement of Amazon Lambda
Custom Runtime.


== Create an Execution Role

View the https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-awscli.html[Getting Started Guide] for deploying
a lambda with AWS CLI.  Specifically make sure you have created an `Execution Role`.  You will need the `Role Arn` to copy/paste
into the scripts generated by the maven archetype.

== Edit native script files

Edit the `create-native.sh` scripts included with the generated project.  After the `--role` switch
replace the dummy `Role Arn` with the Arn of the `Execution Role` you created in the Amazon IAM console.

== Create the Native Lambda

The `create-native.sh` script is for deploying your lambda using the AWS Lambda Custom runtime.

.create-native.sh
[source, subs=attributes+]
----
aws lambda create-function --function-name my-native-function \
           --zip-file fileb://target/function.zip --handler any.name.not.used \
           --runtime provided --role arn:aws:iam::1234567:role/lambda-cli-role \
           --environment Variables="{DISABLE_SIGNAL_HANDLERS=true}"
----

Don't forget to replace the `--role` flag with the Arn of your `Execution Role`.

Notice that the `--zip-file` flag points to the `function.zip` file generated by the build.
The handler switch is not used, but must be set.  It can be any value.  Finally, notice that an environment variable
must be set: `DISABLE_SIGNAL_HANDLERS`.  This resolves an incompatibility with the Amazon Lambda Custom Runtime container
and GraalVM.

If there are any problems creating the function, you must delete it with the `delete-native.sh` script before re-running
the `create-native.sh` script.

== Invoke the Native Lambda

Use the `invoke-native.sh` script to invoke your function.

.invoke-native.sh
[source, subs=attributes+]
----
aws lambda invoke --function-name my-native-function
                  --payload file://payload.json out
                  --log-type Tail --query 'LogResult' --output text |  base64 -d
----

The example lambda takes input.  This input is passed in via the `--payload` switch which points to a json file
in the root directory of the project.  If you want to see the return output of the lambda, open the `out` file.
This script will also write the log output to the console.

== Update the Native Lambda

You can update the Java code as you see fit.  Once you've rebuilt, you can redeploy your lambda by executing the
`update-native.sh` script.

.update-native.sh
[source, subs=attributes+]
----
aws lambda update-function-code --function-name my-native-function \
           --zip-file fileb://target/function.zip
----

== Examine the POM

If you want to adapt an existing project to use Quarku's Amazon Lambda extension, there's a couple
of things you need to do.  Take a look at the generated example project to get an example of what you need to adapt.

1. Include the `quarkus-amazon-lambda` extension as a pom dependency
2. Configure Quarkus to build an `uber-jar`
3. If you are doing a native GraalVM build, Amazon requires you to rename your executable to `bootstrap` and zip it up.  Notice that the `pom.xml` uses the `maven-assemby-plugin` to perform this requirement.










