To deploy this application to AWS Lambda with HTTP API, add a new Quarkus extension(quarkus-amazon-lambda-http) using Quarkus CLI:
quarkus ext add quarkus-amazon-lambda-http
The output should be:
[SUCCESS] ✅ Extension io.quarkus:quarkus-amazon-lambda-http has been installed
You can also search what kinds of extensions are available to install on the working project:
quarkus ext --installable -s aws
The output looks like:
Listing extensions (default action, see --help).
Current Quarkus extensions installable:
✬ ArtifactId Extension Name
✬ camel-quarkus-aws2-athena Camel AWS 2 Athena
✬ camel-quarkus-aws2-cw Camel AWS 2 CloudWatch
✬ camel-quarkus-aws2-ddb Camel AWS 2 DynamoDB
...
✬ quarkus-amazon-lambda AWS Lambda
✬ quarkus-amazon-lambda-http AWS Lambda HTTP
✬ quarkus-amazon-lambda-rest AWS Lambda Gateway REST API
✬ quarkus-amazon-lambda-xray AWS Lambda X-Ray
✬ quarkus-amazon-s3 Amazon S3
✬ quarkus-amazon-secretsmanager Amazon Secrets Manager
✬ quarkus-amazon-ses Amazon SES
✬ quarkus-amazon-sns Amazon SNS
✬ quarkus-amazon-sqs Amazon SQS
✬ quarkus-amazon-ssm Amazon SSM
✬ quarkus-funqy-amazon-lambda Funqy AWS Lambda Binding
quarkus-hibernate-search-orm-elasticsearch-aws Hibernate Search + Elasticsearch - AWS authentication and request signing
Before we deploy, let’s add a new method and class to expose a new function on AWS Lambda.
Create a new GreetingService.java
file in src/main/java/org/acme/. Then copy the following code:
package org.acme;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class GreetingService {
public String greeting(String name) {
return "Enter Serverless Functions with Quarkus, " + name;
}
}
Update GreetingResource.java
file in src/main/java/org/acme/ to inject a CDI bean as well as modifying the return string in hello method:
package org.acme;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@Path("/hello")
public class GreetingResource {
@Inject
GreetingService greetingService;
@GET
@Path("/greeting/{name}")
public String greeting(String name) {
return greetingService.greeting(name);
}
@GET
public String hello() {
return "Hello Serverless";
}
}
Verify both a new endpoint(/hello/greeting/{name}) and an existing one(/hello) using HTTPie:
http :8080/hello
The output looks like:
HTTP/1.1 200 OK
Content-Length: 16
Content-Type: text/plain;charset=UTF-8
Hello Serverless
Access another REST API:
http :8080/hello/greeting/daniel
The output looks like:
HTTP/1.1 200 OK
Content-Length: 47
Content-Type: text/plain;charset=UTF-8
Enter Serverless Functions with Quarkus, daniel
Note
|
You don’t need to stop and re-run the serverless application because Quarkus will reload the changes automatically via the In case you’re stuck when you invoke the REST APIs, make sure to close the Dev UI and restart the Quarkus dev mode. |
To mirror the AWS Lambda environment as closely as possible in a dev environment, the Quarkus Amazon Lambda extension boots up a mock AWS Lambda event server in Quarkus Dev and Test mode. This mock event server simulates a true AWS Lambda environment.
While running in Quarkus Dev Mode, you can feed events to it by doing an HTTP POST
to http://localhost:8080. The mock event server will receive the events and your lambda will be invoked. You can perform live coding on your lambda and changes will automatically be recompiled and available the next invocation you make.
Furthermore, if you’re still running (or re-run) the continuous testing, you can see the following TEST REPORT
in the terminal because you only changed the business application code (e.g. hello()) without the test code.
ERROR [io.qua.test] (Test runner thread) ==================== TEST REPORT #1 ====================
ERROR [io.qua.test] (Test runner thread) Test GreetingResourceTest#testHelloEndpoint() failed
: java.lang.AssertionError: 1 expectation failed.
Response body doesn't match expectation.
Expected: is "Hello from RESTEasy Reactive"
Actual: Hello Serverless
at io.restassured.internal.ValidatableResponseImpl.body(ValidatableResponseImpl.groovy)
at org.acme.GreetingResourceTest.testHelloEndpoint(GreetingResourceTest.java:18)
To fix the test error, update the test case along with the modified hello function. Open the GreetingResourceTest.java
file in src/test/java/org/acme directory and replace testHelloEndpoint()
method with the following code:
@Test
public void testHelloEndpoint() {
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("Hello Serverless"));
}
Save
the file then go back to the terminal where Quarkus Dev mode is running.
Then, you will see the test case passed as below:
All 1 test is passing (0 skipped), 1 test was run in 828ms. Tests completed at 10:59:56 due to changes to GreetingResourceTest.class.
Stop the Dev Mode using CTRL-C
! Package the application using the following Quarkus CLI:
quarkus build --no-tests
or Use maven package command as below:
./mvnw clean package
The output will end with BUILD SUCCESS
.
Inspect generated files in the target directory:
-
function.zip - lambda deployment file
-
bootstrap-example.sh - example bootstrap script for native deployments
-
sam.jvm.yaml - (optional) for use with sam cli and local testing
-
sam.native.yaml - (optional) for use with sam cli and native local testing
Note
|
If you have already tested the function using live coding with Quarkus Dev mode, you can skip the function simulation locally. Then jump into the deployment step. |
To simulate the function locally using SAM CLI. The AWS SAM command line interface (CLI) requires you to set AWS credentials so that it can make calls to AWS services on your behalf. Find more information how to set up AWS credentials for SAM CLI here.
Note
|
You need to run a container runtime(e.g. Docker) to run the SAM emulator. |
Open the sam.jvm.yaml
file in the target directory. Then, update the Runtime
to use Java 17. Currently, Quarkus doesn’t generate the Java17 runtime by default.
Runtime: java17
Save the file. Then, run the following SAM command:
sam local start-api -t target/sam.jvm.yaml
Output should look like:
Mounting EnterServerlessFunction at http://127.0.0.1:3000$default [X-AMAZON-APIGATEWAY-ANY-METHOD]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. If you used sam build before running local commands, you will need to re-run sam build for the changes to be picked up. You only need to restart SAM CLI if you update your AWS SAM template
YYYY-MM-SS HH:MM:SS WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:3000
YYYY-MM-SS HH:MM:SS Press CTRL+C to quit
Then, invoke the endpoint like in another terminal:
-
HTTPie:
http http://127.0.0.1:3000/hello/greeting/awslocal
-
Curl:
curl http://127.0.0.1:3000/hello
When you go back to the terminal where the sam local command is running, you will see that the Quarkus application gets started. It takes a few seconds to complete getting ready in Quarkus runtime.
Then, the output should look like:
HTTP/1.0 200 OK
Content-Type: text/plain;charset=UTF-8
Wed, 2 Non 2022 08:01:55 GMT
Server: Werkzeug/1.0.1 Python/3.8.13
content-length: 49
Enter Serverless Functions with Quarkus, awslocal
Stop the local testing by CTRL-C
!
Note
|
You can also use the live coding feature for Lambda functions development locally. Find more information here |
If you haven’t already configured AWS credential
locally (e.g., ~/.aws/credentials) yet, run the following aws command line:
aws configure
Find more information about Configuration and credential file settings.
Deploy the function to AWS Lambda using SAM CLI:
sam deploy -t target/sam.jvm.yaml -g
Input the configuration for the SAM Deploy with your preferences (e.g., Stack Name: quarkus-function
). For example,
Configuring SAM deploy
======================
Looking for config file [samconfig.toml] : Not found
Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]: quarkus-function
AWS Region [us-east-1]:
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [y/N]: y
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: y
#Preserves the state of previously provisioned resources when an operation fails
Disable rollback [y/N]: n
EnterServerlessFunction may not have authorization defined, Is this okay? [y/N]: y
Save arguments to configuration file [Y/n]: y
SAM configuration file [samconfig.toml]:
SAM configuration environment [default]:
...
Note
|
If you have a |
Then, you might need to confirm your configurations as below:
CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
-------------------------------------------------------------------------------------------------------------------------------------
+ Add EnterServerlessFunctionsHttpApi AWS::Lambda::Permission N/A
EventPermission
+ Add EnterServerlessFunctionsRole AWS::IAM::Role N/A
+ Add EnterServerlessFunctions AWS::Lambda::Function N/A
+ Add ServerlessHttpApiApiGatewayDefa AWS::ApiGatewayV2::Stage N/A
ultStage
+ Add ServerlessHttpApi AWS::ApiGatewayV2::Api N/A
-------------------------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:us-east-1:716861016243:changeSet/samcli-deploy1633488868/1e632117-3395-4b76-8037-bc6529ace78d
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]:
Press y
then you will receive the outputs by CloudFormation in a few minutes. It should look like:
CloudFormation events from changeset
-------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::IAM::Role EnterServerlessFunctionsRole Resource creation Initiated
CREATE_IN_PROGRESS AWS::IAM::Role EnterServerlessFunctionsRole -
CREATE_COMPLETE AWS::IAM::Role EnterServerlessFunctionsRole -
CREATE_IN_PROGRESS AWS::Lambda::Function EnterServerlessFunctions -
CREATE_IN_PROGRESS AWS::Lambda::Function EnterServerlessFunctions Resource creation Initiated
CREATE_COMPLETE AWS::Lambda::Function EnterServerlessFunctions -
CREATE_IN_PROGRESS AWS::ApiGatewayV2::Api ServerlessHttpApi -
CREATE_COMPLETE AWS::ApiGatewayV2::Api ServerlessHttpApi -
CREATE_IN_PROGRESS AWS::ApiGatewayV2::Api ServerlessHttpApi Resource creation Initiated
CREATE_IN_PROGRESS AWS::Lambda::Permission EnterServerlessFunctionsHttpApi Resource creation Initiated
EventPermission
CREATE_IN_PROGRESS AWS::Lambda::Permission EnterServerlessFunctionsHttpApi -
EventPermission
CREATE_IN_PROGRESS AWS::ApiGatewayV2::Stage ServerlessHttpApiApiGatewayDefa -
ultStage
CREATE_COMPLETE AWS::ApiGatewayV2::Stage ServerlessHttpApiApiGatewayDefa -
ultStage
CREATE_IN_PROGRESS AWS::ApiGatewayV2::Stage ServerlessHttpApiApiGatewayDefa Resource creation Initiated
ultStage
CREATE_COMPLETE AWS::Lambda::Permission EnterServerlessFunctionsHttpApi -
EventPermission
CREATE_COMPLETE AWS::CloudFormation::Stack quarkus-function -
-------------------------------------------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
----------------------------------------------------------------------------------------------------------------------------------------
Outputs
----------------------------------------------------------------------------------------------------------------------------------------
Key EnterServerlessFunctionsApi
Description URL for application
Value https://wcji0ss0ge.execute-api.us-east-1.amazonaws.com/
----------------------------------------------------------------------------------------------------------------------------------------
Successfully created/updated stack - quarkus-function in us-east-1
Note
|
During the |
Go to AWS Console then navigate the following resources if they are automatically created along with the Quarkus function.
A new API gateway(e.g., quarkus-function) will show up when you specified it during the SAM deployment:
A new Quarkus function will show up:
When you click on the function name, you can see the details such as package sizes as well as testing the function:
Access the function via HTTP gateway API URL. For example:
http https://wcji0ss0ge.execute-api.us-east-1.amazonaws.com/hello/greeting/awsprod
The output should look like:
HTTP/1.1 200 OK
Apigw-Requestid: EUxSijdzoAMEJ4w=
Connection: keep-alive
Content-Length: 48
Content-Type: text/plain;charset=UTF-8
Date: Wed, 03 May 2023 02:37:20 GMT
Enter Serverless Functions with Quarkus, awsprod
Deploy a native executable to AWS Lambda. Package the application once again using the following command:
Note
|
When you build a native executable on macOS or Windows, you need to add the following configuration in src/main/resources/application.properties for building a Linux format image using Docker runtime |
quarkus.native.container-runtime=docker
quarkus build --native --no-tests
Or you can run the following maven command:
./mvnw clean package -DskipTests -Pnative
Once the build is complete, run the SAM CLI to deploy it using the following command. It takes a few minutes to complete the build:
sam deploy -t target/sam.native.yaml -g
Key a different stack name (quarkus-native-function
) in the prompt:
Looking for config file [samconfig.toml] : Not found
Setting default arguments for 'sam deploy'
=========================================
Stack Name [quarkus-function]: quarkus-native-function
AWS Region [us-east-1]:
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [Y/n]: y
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: y
#Preserves the state of previously provisioned resources when an operation fails
Disable rollback [y/N]: n
EnterServerlessFunctionNative may not have authorization defined, Is this okay? [y/N]: y
Save arguments to configuration file [Y/n]: y
SAM configuration file [samconfig.toml]:
SAM configuration environment [default]:
...
Once you deploy it successfully, go back to the AWS console. You have new resources now.
Great job! You can access the new Quarkus native function via the new HTTP Gateway API. For example,
http https://whgv0dgboe.execute-api.us-east-1.amazonaws.com/hello/greeting/awsnativeprod
The output should look like:
HTTP/1.1 200 OK
Apigw-Requestid: T4gs9iu3oAMEMWw
Connection: keep-alive
Content-Length: 54
Content-Type: text/plain;charset=UTF-8
Date: Wed, 2 Nov 2022 20:18:14 GMT
Enter Serverless Functions with Quarkus, awsnativeprod
You can showcase the performance stats to compare JVM vs. Native function in CloudWatch metrics: