Serverless Development with Kotlin, AWS Lambda, and MongoDB Atlas
Rate this tutorial
However, maybe your stack doesn't consist of Java, but instead Kotlin. What needs to be done to use Kotlin for AWS Lambda and MongoDB development? The good news is not much will be different!
There are a few prerequisites that must be met in order to be successful with this particular tutorial:
- Must have a Kotlin development environment installed and configured on your local computer.
- Must have an Amazon Web Services (AWS) account.
The easiest way to develop with Kotlin is through IntelliJ, but it is a matter of preference. The requirement is that you can build Kotlin applications with Gradle.
For the purpose of this tutorial, any MongoDB Atlas instance will be sufficient whether it be the M0 free tier, the serverless pay-per-use tier, or something else. However, you will need to have the instance properly configured with user rules and network access rules. If you need help, as a starting point.
Assuming you have a project created using your tooling of choice, we need to properly configure the build.gradle.kts file with the correct dependencies for AWS Lambda with MongoDB.
In the build.gradle.kts file, include the following:
There are a few noteworthy items in the above configuration.
AWS Lambda expects a ZIP or a JAR. By using the Shadow plugin, we can use Gradle to build a "fat" JAR, which includes both the application and all required dependencies. When using Shadow, the main class must be defined.
To define the main class, we have the following:
The above assumes that all our code will exist in a
Handlerclass in an
examplepackage. Yours does not need to match, but note that this particular class and package will be referenced throughout the tutorial. You should swap names wherever necessary.
The next item to note is the
In the above block, we are including the various AWS Lambda SDK packages as well as the MongoDB Kotlin driver. These dependencies will allow us to use MongoDB with Kotlin and AWS Lambda.
If you wanted to, you could run the following command:
As long as the main class exists, it should build a JAR file for you.
With the configuration items out of the way, we can focus on the development of our serverless function. Open the project's src/main/kotlin/example/Handler.kt file and include the following boilerplate code:
The above code won't do much of anything if you tried to execute it on AWS Lambda, but it is a starting point. Let's start by establishing a connection to MongoDB.
Handlerclass, add the following:
First, you'll notice that we are creating a
mongoClientvariable to hold the information about our connection. This client will be created using a MongoDB Atlas URI that we plan to store as an environment variable. It is strongly recommended that you use environment variables to store this information so your credentials don't get added to your version control.
In case you're unsure what the MongoDB Atlas URI looks like, it looks like the following:
You can find your exact connection string using the MongoDB Atlas CLI or through the MongoDB Atlas dashboard.
handleRequestfunction, we get a reference to the database and collection that we want to use:
Now we can focus on interactions with MongoDB. Make a few changes to the
Handlerclass so it looks like this:
Instead of using
voidas the return type for the
handleRequestfunction, we are now using
List<Document>because we plan to return an array of documents to the requesting client.
This brings us to the following:
Instead of executing a fixed query when the function is invoked, we are accepting input from the user. If the user provides a
titlefield with the invocation, we construct a filter for it. In other words, we will be looking for movies with a title that matches the user input. If no
titleis provided, we just query for all documents in the collection.
For the actual
findoperation, rather than risking the return of more than a thousand documents, we are limiting the result set to five and are converting the response from a cursor to a list.
At this point in time, our simple AWS Lambda function is complete. We can focus on the building and deployment of the function now.
Before we worry about AWS Lambda, let's build the project using Shadow. From the command line, IntelliJ, or with whatever tool you're using, execute the following:
Find the JAR file, which is probably in the build/libs directory unless you specified otherwise.
Everything we do next will be done in the AWS portal. There are three main items that we want to take care of during this process:
- Add the environment variable with the MongoDB Atlas URI to the Lambda function.
- Rename the "Handler" information in Lambda to reflect the actual project.
- Upload the JAR file to AWS Lambda.
Within the AWS Lambda dashboard for your function, click the "Configuration" tab followed by the "Environment Variables" navigation item. Add
MONGODB_ATLAS_URIalong with the appropriate connection string when prompted. Make sure the connection string reflects your instance with the proper username and password.
You can now upload the JAR file from the "Code" tab of the AWS Lambda dashboard. When this is done, we need to tell AWS Lambda what the main class is and the function that should be executed.
In the "Code" tab, look for "Runtime Settings" and choose to edit it. In our example, we had example as the package and Handler as the class. We also had our function logic in the handleRequest function.
With all this in mind, change the "Handler" within AWS Lambda to example.Handler::handleRequest or whatever makes sense for your project.
At this point, you should be able to test your function.
On the "Test" tab of the AWS Lambda dashboard, choose to run a test as is. You should get a maximum of five results back. Next, try using the following input criteria:
Your response will now look different because of the filter.
Congratulations! You created your first AWS Lambda function in Kotlin and that function supports communication with MongoDB!
While this example was intended to be short and simple, you could add significantly more logic to your functions that engage with other functionality of MongoDB, such as aggregations and more.