Creating an AWS Serverless Java 11 Application with CDK (Lambda, S3, DynamoDb, API Gateway)
You will see how Lambdas can interact with cloud resources such as S3 Buckets and DynamoDB. With API Gateway, you can allow external calls to these services as a web based client would do. At Xerris, we help organizations with their digital transformation efforts often involving moving on premises workloads to the cloud using best practices.
Objective: Create a Serverless AWS Application with Java 11
- Prerequisites
- You have configured your AWS Account setup and have Java 11(Amazon Corretto) and your Eclipse IDE setup
(If not please refer to Getting started with AWS, Java 11 (Amazon Corretto), Eclipse and AWS Toolkit before proceeding)
- NodeJS https://nodejs.org/en/download/
- Cloud Development Kit(CDK) https://docs.aws.amazon.com/cdk/latest/guide/cli.html
npm install -g aws-cdk
cdk --version
2. Create your CDK Java Project
Go to your projects folder, I am using C:\projects on my machine.
Open a new command prompt and do the following:
cd c:\projects
mkdir JavaCDK
cd JavaCDK
cdk init app --language java
3. Open your project in Eclipse
File > Import > Maven > Existing Maven Projects
Ensure your java project is running in Java 11:
Right click your project in project explorer, select “Build Path”, then “Configure Build Path…, ensure your Java build path is set to Java 11. Remove the Java 8 Reference and under Libraries, Add Library.., JRE System Library, Next, Execution Environment and select Java SE-11 then press Finish. Ensure Maven Dependencies are included as well. Ensure Java SE-11 and Maven dependencies are checked under Order and Export as seen below.
Update your pom.xml file to have the org.apache.maven.plugins section as follows:
Please update your pom.xml file with the 2 sections regarding aws-lambda-java-core dependencies and the maven-shade-plugin plugin as noted at https://docs.aws.amazon.com/lambda/latest/dg/java-package.html#java-package-maven . Refer to https://github.com/collin-smith/poc-javacdk/blob/master/pom.xml as a reference to your own pom.xml.
Add the following in the <build> section:
<plugin>
<groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.2</version>
<configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
You should be able to recompile the project by right clicking java_cdk_app in the Project explorer and selecting Run As / 5 Maven Build… Then typing “clean install” into the Goals: text box and pressing Run
It should then build successfully as follows:
There are a couple files to examine in this default project
JavaCdkApp.cs: The entry point for your JavaCdkApp application
JavaCdkStack.cs: This class will define your JavaCdk stack to determine which AWS Infrastructure resources get generated. It is currently empty.
The pom.xml (Project Object Model) file is also important here. POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details used by Maven to build the project. This will contain information on the java libraries to be referenced in your code.
3. Compiling and deploying your first application
Even though the project is empty, we can go through the steps to deploy it using cdk (or Cloud Development Kit)
The instructions here are:
cd c:\projects\JavaCDK
cdk bootstrap
cdk synth
cdk deploy
After running these commands, it should look like the following:
Even without any custom code added, this deployment can be seen in your aws console if you look at the CloudFormation service
4. Customizing and compiling your first application
Now that we know that this project is deploying correctly. We will now customize the code to create a meaningful project. This will not be over architected but will illustrate how to create lambdas that interact with an s3 bucket and a dynamodb table. The s3 bucket and dynamodb table will be created as part of this.
We will need to update the 2 existing files in the project: (Please see the Appendix for any code snippets or you can check out the github repository at https://github.com/collin-smith/poc-javacdk )
Note that your pom.xml file will have to be updated with the required dependencies which may change. Address any dependencies based on the compilation errors and finding the appropriate dependencies at https://mvnrepository.com/
- com.myorg.JavaCdkApp.java
2. pom.xml
We will also need to add the following 8 files to make it all compile successfully:
3. Add the class com.myorg.dynamodb.City
Right click src/main/java in the Eclipse Project Explorer, New > Class
This will then create the desired class stub.
Then you can copy the required code into this class.
We can then continue creating the next 8 classes (and updating their code from the Appendix or from the github repository)
4. Add com.myorg.builder.CityBuilder
5. Add com.myorg.lambda.SimpleLamdaHandler
6. Add com.myorg.lambda.S3LambdaHandler
7. Add com.myorg.lambda.InsertDynamoDbLambdaHandler
8. Add com.myorg.lambda.ScanLambdaHandler
9. Add com.myorg.lambda.PartitionLambdaHandler
10. Add com.myorg.lambda.GSILambdaHandler
11. Add com.myorg.lambda.LSILambdaHandler
Your project should then look something like:
You should be able to recompile the project by right clicking java_cdk_app in the Project explorer and selecting Run As / 5 Maven Build… Then typing “clean install” into the Goals: text box and pressing Run
It should successfully build as was done previously.
4. Deploy the application to your AWS Account
cd c:\projects\JavaCDK
cdk bootstrap
cdk synth
cdk deploy
A successful deployment should look something like:
Key deployment information should be shown in the console in blue to identify the resources that were created during the deployment.
5. Review the resources that were created in the AWS Console
a) There should be one s3 bucket (dev-mys3bucket-????) created from the deployment
b) There should be one dynamodb table (dev-City) created from the deployment
c) There should be 7 Lambdas (Java 11(Corretto)) created from the deployment
6. A look at JavaCdkStack
We won’t go into much detail here and can leave the working code to be examined by the reader in more detail. If you look at JavaCdkStack.java, you should see the following items:
a)Creation of the S3 Bucket
b)Creation of the DynamoDB table (along with a Global Secondary Index(GSI) and a Local Secondary Index(GS). For more on DynamoDB, I would suggest looking at https://collin-smith.medium.com/dynamodb-introduction-2b010f48959
c)Creation of all the Lambdas. This includes passing the environment variables into them to reference resources correctly
d)The API Gateway configuration so that all of the Lambdas can be exposed externally. And can be called by web applications or even PostMan https://www.postman.com/
e) The CfnOutputs to display the details on each of the resources created for reference purposes.
7. A look at SimpleLambdaHander
The SimpleLambdaHandler, it simply demonstrates a simple lambda receiving a request and returning some information. In your console, you should see the CfnOutputs and see the url that is after Simple Lambda:
Something like:
Assuming you have Postman installed, you can take this url and configure Postman to call it:
Feel free to examine SimpleLambdaHander.java to explore the details on the response that is returned.
8. S3LambdaHander
You can call S3LambdaHandler in the same manner as above. What you can do is upload some files into your S3 Bucket. This Lambda should return a list of the contents of the S3 Bucket.
9. The remaining DynamoDB Lambdas
InsertDynamoDbLambdaHandler.java : This lambda will insert data into the DynamoDb Table
When you actually run this Lambda you can look at the table in the AWS Console under the DynamoDB service. Select the dev-City table and you should then see that the records have been successfully inserted based on the execution of this Lambda.
The other remaining Lambdas will perform query operations on the DynamoDb that has been created
ScanLambdaHandler.java (Demonstrate the use of the Scan operation)
The scan lambda finds all of the cities with a population greater than 1 million. Feel free to look at the code for review.
PartitionLambdaHandler.java (Demonstrate the querying off of the default Partition Key)
This Lambda will use the Partition key to retrieve all of the cities in the “New York” state and sort by the default sort key “City”. Note the use of the scanIndexForward attribute as setting it to false indicates that the sorting will be descending and setting it to false will set the sorting to be ascending. This attribute is used when using a sort key and retrieving data using the partition key or a global secondary index.
GSILambdaHandler.java (Demonstrate the use of a Global Secondary Index)
This lambda will use the created Global Secondary Index (FloodDangerGSIIndex) that was created to search the cities by their FloodDanger level and then sort based on the GSI Sort key of elevation. The GSI allows you to search on something that is not the default partition key.
In this query, we are searching for those with a FloodDanger of Medium
LSILambdaHandler.java (Demonstrate the use of a Local Secondary Index)
The Local Secondary index is an additional sorting index off of the originally created partition key. Here we are searching for those cities in Alberta but sorting by the LSI Sort Key which is the attribute “founded”.
Also note the use of the City.java class and the use of DynamoDBMapper in the queries. This means that java objects can be used in the saving and retrieving of DynamoDb Records.
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.html
10. Cleaning up your CDK Stack
If you want to delete the resources that you have created with this exercise, you can type in the command. This should delete all lambdas, dynamodb tables, API Gateway resources and s3 buckets that were created in this cdk stack. Just a note that your s3 bucket must be empty to be deleted this way. You can look at configuring the Removal Policy attribute in JavaCdkStack.java as well.
cdk destroy
Appendix:
Code Snippets:
These can also be found at the github repository at https://github.com/collin-smith/poc-javacdk
- pom.xml
2. JavaCdkStack.java
3. City.java
4. CityBuilder.java
5. SimpleLamdaHandler.java
6. S3LambdaHandler.java
7. InsertDynamoDbLambdaHandler.java
8. ScanLambdaHandler.java
9. PartitionLambdaHandler.java
10. GSILambdaHandler.java
11. LSILambdaHandler.java