Explore Developer Center's New Chatbot! MongoDB AI Chatbot can be accessed at the top of your navigation to answer all your MongoDB questions.

Learn why MongoDB was selected as a leader in the 2024 Gartner® Magic Quadrant™
MongoDB Developer
Atlas
plus
Sign in to follow topics
MongoDB Developer Centerchevron-right
Developer Topicschevron-right
Productschevron-right
Atlaschevron-right

How to Use Azure Functions with MongoDB Atlas in Java

Mohit Sharma8 min read • Published Apr 14, 2023 • Updated Apr 14, 2023
AzureAtlasJava
Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Cloud computing is one of the most discussed topics in the tech industry. Having the ability to scale your infrastructure up and down instantly is just one of the many benefits associated with serverless apps. In this article, we are going write the function as a service (FaaS) — i.e., a serverless function that will interact with data via a database, to produce meaningful results. FaaS can also be very useful in A/B testing when you want to quickly release an independent function without going into actual implementation or release.
In this article, you'll learn how to use MongoDB Atlas, a cloud database, when you're getting started with Azure functions in Java.

Prerequisites

  1. A Microsoft Azure account that we will be using for running and deploying our serverless function. If you don't have one, you can sign up for free.
  2. A MongoDB Atlas account, which is a cloud-based document database. You can sign up for an account for free.
  3. IntelliJ IDEA Community Edition to aid our development activities for this tutorial. If this is not your preferred IDE, then you can use other IDEs like Eclipse, Visual Studio, etc., but the steps will be slightly different.
  4. An Azure supported Java Development Kit (JDK) for Java, version 8 or 11.
  5. A basic understanding of the Java programming language.

Serverless function: Hello World!

Getting started with the Azure serverless function is very simple, thanks to the Azure IntelliJ plugin, which offers various features — from generating boilerplate code to the deployment of the Azure function. So, before we jump into actual code, let's install the plugin.

Installing the Azure plugin

The Azure plugin can be installed on IntelliJ in a very standard manner using the IntelliJ plugin manager. Open Plugins and then search for "Azure Toolkit for IntelliJ" in the Marketplace. Click Install.
IntelliJ Plugin
With this, we are ready to create our first Azure function.

First Azure function

Now, let's create a project that will contain our function and have the necessary dependencies to execute it. Go ahead and select File > New > Project from the menu bar, select Azure functions from Generators as shown below, and hit Next.
New Project Wizard
Now we can edit the project details if needed, or you can leave them on default.
New Project Wizard Azure function
In the last step, update the name of the project and location.
New Project Wizard Create
With this complete, we have a bootstrapped project with a sample function implementation. Without further ado, let's run this and see it in action.
Project structure

Deploying and running

We can deploy the Azure function either locally or on the cloud. Let's start by deploying it locally. To deploy and run locally, press the play icon against the function name on line 20, as shown in the above screenshot, and select run from the dialogue.
Hello World output console
Copy the URL shown in the console log and open it in the browser to run the Azure function.
Hello World output error
This will prompt passing the name as a query parameter as defined in the bootstrapped function.
1if (name == null) {
2 return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
3 .body("Please pass a name on the query string or in the request body").build();
4} else {
5 return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
6}
Update the URL by appending the query parameter name to http://localhost:XXXXX/api/HttpExample?name=World, which will print the desired result.
Hello World output
To learn more, you can also follow the official guide.

Connecting the serverless function with MongoDB Atlas

In the previous step, we created our first Azure function, which takes user input and returns a result. But real-world applications are far more complicated than this. In order to create a real-world function, which we will do in the next section, we need to understand how to connect our function with a database, as logic operates over data and databases hold the data.
Similar to the serverless function, let's use a database that is also on the cloud and has the ability to scale up and down as needed. We'll be using MongoDB Atlas, which is a document-based cloud database.

Setting up an Atlas account

Creating an Atlas account is very straightforward, free forever, and perfect to validate any MVP project idea, but if you need a guide, you can follow the documentation.

Adding the Azure function IP address in Atlas Network Config

The Azure function uses multiple IP addresses instead of a single address, so let's add them to Atlas. To get the range of IP addresses, open your Azure account and search networking inside your Azure virtual machine. Copy the outbound addresses from outbound traffic.
One of the steps while creating an account with Atlas is to add the IP address for accepting incoming connection requests. This is essential to prevent unwanted access to our database. In our case, Atlas will get all the connection requests from the Azure function, so let's add this address.
Azure IP address
Add these to the IP individually under Network Access.
MongoDB IP Allow List

Installing dependency to interact with Atlas

There are various ways of interacting with Atlas. Since we are building a service using a serverless function in Java, my preference is to use MongoDB Java driver. So, let's add the dependency for the driver in the build.gradle file.
1dependencies {
2 implementation 'com.microsoft.azure.functions:azure-functions-java-library:3.0.0'
3 // dependency for MongoDB Java driver
4 implementation 'org.mongodb:mongodb-driver-sync:4.9.0'
5}
With this, our project is ready to connect and interact with our cloud database.

Building an Azure function with Atlas

With all the prerequisites done, let's build our first real-world function using the MongoDB sample dataset for movies. In this project, we'll build two functions: One returns the count of the total movies in the collection, and the other returns the movie document based on the year of release.
Let's generate the boilerplate code for the function by right-clicking on the package name and then selecting New > Azure function class. We'll call this function class Movies.
1public class Movies {
2 /**
3 * This function listens at endpoint "/api/Movie". Two ways to invoke it using "curl" command in bash:
4 * 1. curl -d "HTTP Body" {your host}/api/Movie
5 * 2. curl {your host}/api/Movie?name=HTTP%20Query
6 */
7 @FunctionName("Movies")
8 public HttpResponseMessage run(
9 @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
10 final ExecutionContext context) {
11 context.getLogger().info("Java HTTP trigger processed a request.");
12
13 // Parse query parameter
14 String query = request.getQueryParameters().get("name");
15 String name = request.getBody().orElse(query);
16
17 if (name == null) {
18 return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body("Please pass a name on the query string or in the request body").build();
19 } else {
20 return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
21 }
22 }
23}
Now, let's:
  1. Update @FunctionName parameter from Movies to getMoviesCount.
  2. Rename the function name from run to getMoviesCount.
  3. Remove the query and name variables, as we don't have any query parameters.
Our updated code looks like this.
1public class Movies {
2
3 @FunctionName("getMoviesCount")
4 public HttpResponseMessage getMoviesCount(
5 @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
6 final ExecutionContext context) {
7 context.getLogger().info("Java HTTP trigger processed a request.");
8
9 return request.createResponseBuilder(HttpStatus.OK).body("Hello").build();
10 }
11}
To connect with MongoDB Atlas using the Java driver, we first need a connection string that can be found when we press to connect to our cluster on our Atlas account. For details, you can also refer to the documentation.
Screenshot connection URL
Using the connection string, we can create an instance of MongoClients that can be used to open connection from the database.
1public class Movies {
2
3 private static final String MONGODB_CONNECTION_URI = "mongodb+srv://xxxxx@cluster0.xxxx.mongodb.net/?retryWrites=true&w=majority";
4 private static final String DATABASE_NAME = "sample_mflix";
5 private static final String COLLECTION_NAME = "movies";
6 private static MongoDatabase database = null;
7
8 private static MongoDatabase createDatabaseConnection() {
9 if (database == null) {
10 try {
11 MongoClient client = MongoClients.create(MONGODB_CONNECTION_URI);
12 database = client.getDatabase(DATABASE_NAME);
13 } catch (Exception e) {
14 throw new IllegalStateException("Error in creating MongoDB client");
15 }
16 }
17 return database;
18 }
19
20 /*@FunctionName("getMoviesCount")
21 public HttpResponseMessage run(
22 @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
23 final ExecutionContext context) {
24 context.getLogger().info("Java HTTP trigger processed a request.");
25
26 return request.createResponseBuilder(HttpStatus.OK).body("Hello").build();
27 }*/
28}
We can query our database for the total number of movies in the collection, as shown below.
1long totalRecords=database.getCollection(COLLECTION_NAME).countDocuments();
Updated code for getMoviesCount function looks like this.
1@FunctionName("getMoviesCount")
2public HttpResponseMessage getMoviesCount(
3 @HttpTrigger(name = "req",
4 methods = {HttpMethod.GET},
5 authLevel = AuthorizationLevel.ANONYMOUS
6 ) HttpRequestMessage<Optional<String>> request,
7 final ExecutionContext context) {
8
9 if (database != null) {
10 long totalRecords = database.getCollection(COLLECTION_NAME).countDocuments();
11 return request.createResponseBuilder(HttpStatus.OK).body("Total Records, " + totalRecords + " - At:" + System.currentTimeMillis()).build();
12 } else {
13 return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR).build();
14 }
15}
Now let's deploy this code locally and on the cloud to validate the output. We'll use Postman.
local deployment
Copy the URL from the console output and paste it on Postman to validate the output.
local postman output
Let's deploy this on the Azure cloud on a Linux machine. Click on Azure Explore and select Functions App to create a virtual machine (VM).
Azure explore
Now right-click on the Azure function and select Create.
create new VM
Change the platform to Linux with Java 1.8.
create vm with linux
If for some reason you don't want to change the platform and would like use Window OS, then add standard DNS route before making a network request.
1System.setProperty("java.naming.provider.url", "dns://8.8.8.8");
After a few minutes, you'll notice the VM we just created under Function App. Now, we can deploy our app onto it.
vm deploy
Press Run to deploy it.
vm deploy
Once deployment is successful, you'll find the URL of the serverless function.
cloud deployment success
Again, we'll copy this URL and validate using Postman.
cloud postman validation
With this, we have successfully connected our first function with MongoDB Atlas. Now, let's take it to next level. We'll create another function that returns a movie document based on the year of release.
Let's add the boilerplate code again.
1@FunctionName("getMoviesByYear")
2public HttpResponseMessage getMoviesByYear(
3 @HttpTrigger(name = "req",
4 methods = {HttpMethod.GET},
5 authLevel = AuthorizationLevel.ANONYMOUS
6 ) HttpRequestMessage<Optional<String>> request,
7 final ExecutionContext context) {
8
9}
To capture the user input year that will be used to query and gather information from the collection, add this code in:
1final int yearRequestParam = valueOf(request.getQueryParameters().get("year"));
To use this information for querying, we create a Filters object that can pass as input for find function.
1Bson filter = Filters.eq("year", yearRequestParam);
2Document result = collection.find(filter).first();
The updated code is:
1@FunctionName("getMoviesByYear")
2public HttpResponseMessage getMoviesByYear(
3 @HttpTrigger(name = "req",
4 methods = {HttpMethod.GET},
5 authLevel = AuthorizationLevel.ANONYMOUS
6 ) HttpRequestMessage<Optional<String>> request,
7 final ExecutionContext context) {
8
9 final int yearRequestParam = valueOf(request.getQueryParameters().get("year"));
10 MongoCollection<Document> collection = database.getCollection(COLLECTION_NAME);
11
12 if (database != null) {
13 Bson filter = Filters.eq("year", yearRequestParam);
14 Document result = collection.find(filter).first();
15 return request.createResponseBuilder(HttpStatus.OK).body(result.toJson()).build();
16 } else {
17 return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body("Year missing").build();
18 }
19}
Now let's validate this against Postman.
get movies by year output
The last step in making our app production-ready is to secure the connection URI, as it contains credentials and should be kept private. One way of securing it is storing it into an environment variable.
Adding an environment variable in the Azure function can be done via the Azure portal and Azure IntelliJ plugin, as well. For now, we'll use the Azure IntelliJ plugin, so go ahead and open Azure Explore in IntelliJ.
Azure Explore
Then, we select Function App and right-click Show Properties.
Azure Explore VM property
This will open a tab with all existing properties. We add our property into it.
Azure Explore
Now we can update our function code to use this variable. From
1private static final String MONGODB_CONNECTION_URI = "mongodb+srv://xxxxx:xxxx@cluster0.xxxxx.mongodb.net/?retryWrites=true&w=majority";
to
1private static final String MONGODB_CONNECTION_URI = System.getenv("MongoDB_Connection_URL");
After redeploying the code, we are all set to use this app in production.

Summary

Thank you for reading — hopefully you find this article informative! The complete source code of the app can be found on GitHub.
If you're looking for something similar using the Node.js runtime, check out the other tutorial on the subject.
With MongoDB Atlas on Microsoft Azure, developers receive access to the most comprehensive, secure, scalable, and cloud–based developer data platform on the market. Now, with the availability of Atlas on the Azure Marketplace, it’s never been easier for users to start building with Atlas while streamlining procurement and billing processes. Get started today through the Atlas on Azure Marketplace listing.
If you have any queries or comments, you can share them on the MongoDB forum or tweet me @codeWithMohit.

Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Related
Tutorial

Seamless Media Storage: Integrating Azure Blob Storage and MongoDB With Spring Boot


Nov 05, 2024 | 9 min read
Code Example

EHRS-Peru


Sep 11, 2024 | 3 min read
Article

The MongoDB Atlas Sample Datasets


Dec 02, 2024 | 8 min read
Tutorial

Build an Image Search Engine With Python & MongoDB


Sep 18, 2024 | 8 min read
Table of Contents