Many Java applications use Apache Maven or Gradle for building and managing the project. These tools help map how to build a particular piece of software, along with its different dependencies. In almost every scenario, these applications will depend on several external dependencies/libraries.
AWS Lambda
functions written in Java also use these tools for packaging software.
Previously, if you wanted to build and package Lambda functions with external dependencies in
AWS Cloud Development Kit (AWS CDK)
using Java or other supported language runtimes, you needed to create artifacts that included all the required dependencies. You would typically do this manually or via wrapper scripts. You could use
AWS Serverless Application Model (AWS SAM)
, which does this out of the box; but, thanks to AWS CDK Assets (specifically, the
aws-s3-assets
module), this is now possible with AWS CDK, too.
Lambda functions written with the Python or Node.js runtime can leverage higher level constructs building on top of
aws-s3-assets
. There are no higher level constructs for packaging Lambda functions with external dependencies written in other languages such as Java yet, but the aws-s3-assets module can be used regardless.
In this article, we’ll show how to build and package Lambda functions written in Java with external dependencies via AWS CDK. You can download the code used in this walkthrough from
the project’s GitHub repo
.
Overview
In this example, we set up a basic serverless architecture using AWS CDK. It creates a REST API using
Amazon API Gateway
and Lambda proxy integration. The CDK application will create two Lambda functions written in Java and maintained as separate Maven projects.
Project structure for the demo CDK application
├── infrastructure # Infrastructure code vi CDK (Java).
├── software # Holds business logic in AWS lambda functions
│ ├── FunctionOne # Sample Lambda function (Maven project)
│ └── FunctionTwo # Sample Lambda function (Maven project)
└── ...
Step 1: Clone the GitHub repository and synthesize the application with the AWS CDK. Run the following commands in a terminal:
git clone [email protected]:aws-samples/cdk-lambda-packaging-java.git
cd cdk-lambda-packaging-java/infrastructure/
cdk synth
Note: When running the synth command for the first time, the CDK application will pull the Docker image for Java 11. This step might take few minutes to complete depending on your internet connection bandwidth.
Step 2: Deploy the application:
cdk deploy
Approve the AWS Identity and Access Management (IAM)-related changes and let the stack deploy. After deployment, the stack outputs the API Gateway HTTP API endpoint.
Step 3: Validate the deployed application by copying the HttpApi URL from the output in Step 2:
We deployed two Lambda functions with external dependencies, built and packaged natively via AWS CDK.
Walkthrough of the AWS CDK application
Now that we have seen how to build and deploy the demo application, let’s dive into the code for the CDK stack, which takes care of packaging and building the two Lambda functions out of the box.
In this example, we have created a Java 11 Lambda function. The rest of the configuration is fairly typical, except for how the code for the function is configured. It uses the Code.fromAsset API to pass the path to the directory where the code for the Lambda function exists along with bundling options:
Function functionOne = new Function(this, "FunctionOne", FunctionProps.builder()
.runtime(Runtime.JAVA_11)
.code(Code.fromAsset("../software/", AssetOptions.builder().bundling(builderOptions.build()).build()))
.handler("helloworld.App")
.memorySize(1024)
.timeout(Duration.seconds(10))
.logRetention(RetentionDays.ONE_WEEK)
.build());
Bundling options and commands
When defining an asset via Code.fromAsset API, the bundling options command is used to specify a command to run inside a Docker container. The command can read the contents of the asset source from /asset-input and writes files under /asset-output (directories mapped inside the container). The files under /asset-outputwill be zipped and uploaded to Amazon Simple Storage Service (Amazon S3) as the asset by default. In our example, the asset is already zipped in form of .jar, so we have set the output type as ARCHIVED explicitly.
We are using the official Docker image for Java 11. The packaging instructions for function depends upon how you want to build the application. In this example, because we’re using Maven, the packaging instructions follow that setup.
We have optionally configured it to mount the local volumes. This can be useful in cases where you would want to mount your cache directory to avoid downloading all the external dependencies on each build. In the example below, we have mounted to local .m2 directory to avoid downloading external dependencies again.
With this setup, the CDK application takes care of building and packaging the Lambda function during the synthesizing or deploy stage. We no longer need a wrapper script that makes sure to build the Lambda function artifact first.
Cleanup
Run the following command to delete the resources created while following this walkthrough:
cdk destroy LambdaPackagingStack
Conclusion
AWS CDK lets you apply existing skills and tools to the task of building cloud infrastructure. The launch of a higher level construct in the form of the AWS CDK Assets module allows developers to deploy CDK apps that include constructs with assets. A common example of an asset is a directory that contains the handler code for a Lambda function along with external dependencies.
This article shows how to build and package AWS Lambda functions written in Java with external dependencies using AWS CDK natively. The approach can be applied to other AWS Lambda-supported language runtimes as well.
Pankaj is a Solutions Architect at AWS, where he works with different customers across Nordics, helping them to make best use of AWS services and accelerate their journey to cloud. In his spare time, he enjoys running into the woods and loves to learn new technical skills. He is quite passionate about DevOps and Serverless technologies.