Java Spring Boot, MongoDB Atlas App on Azure App Service
Published Apr 27 2023 09:00 AM 6,769 Views
Microsoft

In this tutorial, we’re going to build a resilient Java Spring Boot application that scales automatically and also provides high availability with built-in monitoring and diagnostics.

 

For this, we will be using Microsoft Azure App Service, a PaaS (platform as a service) offering by Microsoft Azure, because it's quite suitable for long running applications and web workloads.

 

As we want our application to be fully-managed and scaling automatically in the cloud, MongoDB Atlas is a great choice for our data store since it’s a fully-managed, cloud-native database as a service that can also scale up and down automatically in a cost-effective way to meet the needs of any application.

 

For this particular tutorial, we’ll be using the Spring Initializr plugin for IntelliJ,  connect it to a MongoDB Atlas serverless cluster, and deploy the Java Spring Boot application to Azure App Service using the Azure Toolkit for IntelliJ.

 

Prerequisites

 

Spin up a new MongoDB cluster deployed on Microsoft Azure

 

Since our Java Spring Boot application is ready, let’s create our MongoDB Atlas cluster with the sample datasets. You can follow the basics tutorial.

 

1. Let’s create the cluster required by going to the Data Services tab and clicking on the create button.

 

denverbrittain_0-1682365855083.png

 

2. Create a database cluster deployed on Azure. We can use a serverless/dedicated cluster for our production use cases. However, we are creating a shared free cluster for this example.

Select Azure as the cloud provider and select the region of your cluster. Choose the cluster tier (we will be choosing M0 for this tutorial with no backup options), select your cluster name, and click on Create.

 

denverbrittain_1-1682365855092.png

 

3. Load a sample data set, if you’d like, when the cluster is ready by clicking on the ellipsis button.

 

denverbrittain_2-1682365855093.png

 

denverbrittain_3-1682365855097.png

 

4. Let’s add some database users who can access the database cluster we just created. Go to the Database Access tab on the left and click on Add new database user.

 

denverbrittain_4-1682365855104.png

 

denverbrittain_5-1682365855112.png

 

5. Even if we have added database users, we need to add IPs that can access our database cluster. So let’s add a few IPs to the IP Access List that can access the database cluster over the network, by going to the Network Access tab from the left panel and clicking on Add IP Address Button. We can choose either Add Current IP Address to run and test the app locally or Allow access from anywhere (suitable for development purposes only) to run locally as well as for accessing MongoDB Atlas from the app deployed on Azure App Service. 

 

Please note that we added access from anywhere to start with, but it’s not recommended for production environments as it will lead to a data breach if the connection string that contains the database user details is exposed. We will show you how to use “Peering Connection” in an upcoming section to secure our deployment.

 

denverbrittain_6-1682365855125.png

 

6. Click the Connect button on top of your database cluster, select Connect your application, and copy the MongoDB connection string. We will use this to connect to our database cluster later in the Spring properties files.

 

denverbrittain_7-1682365855130.png

 

Create a Java Spring Boot app using the Spring Initializr Generator

 

Let’s create a new Java Spring Boot application using the IDE IntelliJ and its extension, the Spring Initializr plugin for IntelliJ, which will help us specify the Spring Boot version, JDK, and add the required dependencies.

 

1. Click File, expand New, and then click Project.

 

denverbrittain_8-1682365855189.png

 

2. In the New Project dialog box, select Spring Initializr, which will take care of generating a Spring Boot project with selected Java versions. Make sure the selected JDK is one of the Microsoft Build of OpenJDK and the Java version also aligns with it, and then click Next.

 

denverbrittain_9-1682365855193.png

 

3. Add dependencies. For this tutorial, we are adding the below required dependencies:

  • Spring Web - Spring Web embeds Apache Spring MVC, REST, etc. and MongoDB drivers to access data from our MongoDB Atlas cluster. (We’ll see this in upcoming sections.) Click on Create
  • Spring Data MongoDB - The Spring Data MongoDB provides seamless integration with MongoDB using MongoTemplate class or MongoRepository interface.

 

For this example, we will be using the MongoRepository interface which is handy for basic CRUD.

Please note, MongoTemplate APIs can be used for more complex and custom queries and aggregations.

 

Note: Both the approaches are quite easy to implement and need only a few lines of code.

 

denverbrittain_10-1682365855198.png

 

We have used IntelliJ Ultimate Edition, Spring Boot version 2.7.10, Java 11 (OpenJDK 11u), and IntelliJ Spring Initializr Generator.

 

We will see the below two dependencies in the generated pom.xml.

 

 

 

<dependencies>

  <dependency>

     <groupId>org.springframework.boot</groupId>

     <artifactId>spring-boot-starter-data-mongodb</artifactId>

  </dependency>

  <dependency>

     <groupId>org.springframework.boot</groupId>

     <artifactId>spring-boot-starter-web</artifactId>

  </dependency>

<dependencies>

 

 

 

Please note that we won’t use  use https://start.spring.io/ as we need to use the supported JDKs for Azure only.

 

Configure the MongoDB driver for Java within the Spring Boot project

 

We have now created a boilerplate Java Spring Boot application and set up our MongoDB Atlas cluster. We can start creating our Java Spring Boot application by using the below package structure and classes.

 

denverbrittain_11-1682365983330.png

 

What will we create?

 

Let’s create a very simple Person database with the first and last name. We will define a model Person with ID, first name, and last name, and then we will do basic CRUD using MongoRepository interface.

 

  1. Let’s first see the auto-generated main configuration class with the annotation @SpringBootApplication, AtlasAzureAppServiceDemoApplication.java that triggers auto-configuration and component scanning. Also note that @SpringBootApplication is equivalent to declaring @Configuration, @EnableAutoConfiguration, and @ComponentScan.

     

AtlasAzureAppServiceDemoApplication.java

 

 

 

package com.mongo.atlas.example;

 

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

 

@SpringBootApplication

public class AtlasAzureAppServiceDemoApplication

 {

 

  public static void main(String[] args) {

     SpringApplication.run(AtlasAzureAppServiceDemoApplication.class, args);

  }

 

}

 

 

 

  1. We add the @Value to read the MongoDB Atlas cluster connection string from properties and @Bean method that will be processed by the Spring container to generate the MongoClient service at runtime by providing the connection string. We will be adding it to the properties file in a bit, to the above class as it is equivalent to declaring @Configuration annotation.

 

Please note that we could also define another class(es), use @Configuration, and move the @Value and @Bean to that class.

 

 

 

package com.mongo.atlas.example;

 

import com.mongodb.ConnectionString;

import com.mongodb.MongoClientSettings;

import com.mongodb.client.MongoClient;

import com.mongodb.client.MongoClients;

import org.bson.codecs.configuration.CodecRegistry;

import org.bson.codecs.pojo.PojoCodecProvider;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.Bean;

import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

 

import static org.bson.codecs.configuration.CodecRegistries.fromProviders;

import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;

 

@SpringBootApplication

public class AtlasAzureAppServiceDemoApplication {

 

  public static void main(String[] args) {

     SpringApplication.run(AtlasAzureAppServiceDemoApplication.class, args);

  }

 

  @Value("${mongodb.uri}")

  private String connectionString;

 

  @Bean

  public MongoClient mongoClient() {

 

     CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build());

     CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry);

     return MongoClients.create(MongoClientSettings.builder()

           .applyConnectionString(new ConnectionString(connectionString))

           .codecRegistry(codecRegistry)

           .build());

  }

 

}

 

 

 

  1. Let’s create a new package named “model” under our parent package and create a simple model class which can be used to hold the Person object.

 

 

 

package com.mongo.atlas.example.model;

 

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;

import org.bson.types.ObjectId;

import org.springframework.data.annotation.Id;

import org.springframework.data.mongodb.core.mapping.Document;

 

@Document("persons")

public class Person {

   @Id

   @JsonSerialize(using = ToStringSerializer.class)

   private ObjectId id;

 

   private String firstName;

 

   private String lastName;

 

   public Person() {

   }

 

   public Person(String firstName, String lastName) {

       this.firstName = firstName;

       this.lastName = lastName;

   }

   public String getFirstName() {

       return firstName;

   }

 

   public String getLastName() {

       return lastName;

   }

 

   public void setFirstName(String firstName) {

       this.firstName = firstName;

   }

 

   public void setLastName(String lastName) {

       this.lastName = lastName;

   }

 

   public ObjectId getId() {

       return id;

   }

 

   public void setId(ObjectId id) {

       this.id = id;

   }

 

 

}

 

 

 

  1. Also, add separate packages for controller, repository, and view — but please note that we are skipping the view for this tutorial. For our example, we have implemented only findAll and save methods.

Controller class: This will define different routes and fetch the data accordingly using the repository, and return it to the view.

 

 

 

package com.mongo.atlas.example.controller;



import com.mongo.atlas.example.model.Person;

import com.mongo.atlas.example.repository.PersonRepository;

import org.springframework.http.HttpStatus;

import org.springframework.web.bind.annotation.*;



import java.util.ArrayList;



@RestController

public class PersonController {



   private final PersonRepository personRepository;



   public PersonController(PersonRepository personRepository){

       this.personRepository = personRepository;

   }



   @GetMapping("/hello")

   public String hello() {

       return "hello azure!";

   }



   @GetMapping("/persons")

   public Object getAllPersons(){







      try {

          return this.personRepository.findAll();

      } catch(Exception exception){

          return exception;

      }

   }



   @PostMapping("/person")

   @ResponseStatus(HttpStatus.CREATED)

   public Person createPerson(@RequestBody Person person) {

       return this.personRepository.save(person);

   }

}

 

 

 

 

Repository interface: The Repository interface will be used by the controller’s routes to talk to MongoDB. It extends from MongoRepository to model the data as a Person object. For this tutorial, we haven’t done much in this interface, such as passing any filters or query parameters using the Query annotation or any custom implementation.

 

 

 

package com.mongo.atlas.example.repository;



import com.mongo.atlas.example.model.Person;

import org.springframework.data.mongodb.repository.MongoRepository;



public interface PersonRepository extends MongoRepository<Person,String> {



}

 

 

 

Note:

  • Spring data automatically detects the database either from the connection string (spring.data.mongodb.uri) or from spring.data.mongodb.database. If specified this value is taken as the database and overrides the database specified in the above key (URL).
  • The collection is taken by spring.data.mongodb.collection or @Document annotation, if this property is not specified

 

Connect the MongoDB Atlas cluster to your Java Spring Boot application

 

We have created a boilerplate Java Spring Boot application using Spring Initializr and set up our Atlas cluster. Let’s start making a simple application that will connect to our MongoDB Atlas database cluster.

 

Let’s try to create the files one by one and follow something like the following project structure:

 

  1. Make a new properties file under a resources directory under the main package, with all the secrets to run the project locally. (We made a new file named mongodb.properties. It can be added to application properties using optional so that we can add our secrets file to .gitignore.)

denverbrittain_12-1682365983332.png

 

We will see in a bit how we will add secrets to our App Configuration in Microsoft Azure after deploying the application.

 

Please note that we have specified the database name as well in the MongoDB connection string (mongodb.uri). MongoDB will create a new one, if that database doesn’t exist.

 

application.properties

spring.config.import=optional:mongodb.properties

mongodb.properties

spring.data.mongodb.uri=mongodb+srv://<<mapped username>>:<<mapped password>>@<<mapped cluster>>.wpeia.mongodb.net/<<databaseName>>?retryWrites=true&w=majority

spring.data.mongodb.database=<<DB>>

spring.data.mongodb.collection=<<Collection>>

 

However, we can skip spring.data.mongodb.collection as we are using @Document annotation on our model Person.java.

 

Note : In the case of multiple MongoDB databases and collections, we can use property names such as ‘spring.data.mongodb.db1.uri’, ‘spring.data.mongodb.db1.xxcollection’, and so on, use @Value annotations, and implement the Repository methods as required.

 

Make sure that the below file is added to .gitignore if you choose to keep your secrets for development purposes.

mongodb.properties

 

Running the Spring Boot application locally

 

Since we are done creating our database cluster and Java Spring Boot application, let’s run and test it locally.

 

1. Just click on the green play button near public class AtlasAzureAppServiceDemoApplication in the ProjectNameApplication file, and click Run Application.

 

denverbrittain_13-1682365983334.png

 

2. Try to access it locally once on port 8080, after Run Configuration executes successfully.

 

denverbrittain_14-1682365983335.png

 

3. Let’s insert some data into our collection.

 

We can also use our person POST route using Postman and the following curl:

 

 

 

curl --location --request POST 'localhost:8080/person' \

--header 'Content-Type: application/json' \

--data-raw '{

   "firstName": "ABC",

   "lastName": "DEF"

}'

 

 

 

denverbrittain_15-1682365983344.png

 

 

Alternatively, we can use MongoDB Atlas by going to our cluster deployed on Azure and clicking on Browse Collections.

 

denverbrittain_16-1682365983353.png

 

Then, click on Insert Document and insert the document.

 

denverbrittain_17-1682365983365.png

 

denverbrittain_18-1682365983378.png

 

We can also use MongoDB Compass to insert the document.

 

Deploy Microsoft Azure App Service with MongoDB support in the cloud

 

After our Java Spring Boot application runs well locally, we are ready to deploy it on Azure App Service. Let’s follow the steps below in order to do so:

 

1. Install the Azure Toolkit for IntelliJ plugin and sign into your Azure account using the Azure Explorer sidebar. Then, click the Azure Sign In. Or, navigate to Tools -> Azure -> click Azure Sign In.

 

denverbrittain_25-1682366102543.png

 

2. In the Azure Sign In window, select OAuth 2.0, and then click Sign in. For other sign-in options, see Sign-in instructions for the Azure Toolkit for IntelliJ.

 

denverbrittain_26-1682366102547.png

 

3. In the browser, sign in with your account and then go back to IntelliJ. In the Select Subscriptions dialog box, click on the subscription that you want to use, and then click Select.

 

4. Under the Project Explorer view, right-click your project, expand Azure, and click Deploy to Azure Web Apps.

 

denverbrittain_27-1682366102553.png

 

5. In the Deploy to Azure dialog box, Click + to create a new Azure web app. You can also choose Web App from the Web App dropdown, if there are existing web apps in your subscription.

 

6. In the Create WebApp dialog box, specify the following information and click OK:

  • Name: The Azure App Service’s domain name. This value should be unique across Azure.
  • Platform: Select Linux-Java 11-Java SE or as appropriate.

 

denverbrittain_28-1682366102579.png

 

7. Create the app settings to add your secrets (connection string, dbName, collections, etc.).

  • Name: name of the secret
  • Value: value of the secret

 

denverbrittain_29-1682366102599.png

 

denverbrittain_30-1682366102602.png

 

Or, you can add the same in Azure Portal by selecting the deployed App Service under App Services under Configuration -> Application Settings -> + New Application Setting after the application is deployed.

 

denverbrittain_31-1682366102615.png

8. Click on Apply and then Run to deploy the app service to Azure. The toolkit will start creating a:

    1. Resource Group.
    2. App Service plan.
    3. App Service.

 

And finally, deploy the Java Spring Boot application to the Microsoft Azure App Service and display the hosted URL. You can browse to the domain name selected to see your Azure App service up and running.

 

denverbrittain_32-1682366102617.png

 

denverbrittain_33-1682366102621.png

 

Configure network peering for an Azure-backed cluster

 

Since we mentioned Allow Access from Anywhere over the network is not a recommended practice because it might lead to unexpected security concerns for our data, we would need to configure virtual network peering for our Azure-backed cluster.

 

  1. In Atlas, add a new network peering connection for your project by clicking on the Network Access tab and then on the Peering button.

Choose Azure as the Cloud Provider on the peering connection popup.

 

denverbrittain_34-1682366102632.png

 

  1. To create the Network Peering connection, we need to allow access from both your Azure subscription and resource group using Virtual Private Networks and Azure Active Directory, before giving it access from the Atlas side.

  2. Create a virtual network in Microsoft Azure for the resource group. We name it atlas-vpc-test for our tutorial. Add the resource group, IPv4, IPv6, and subnet ranges, and click on Review + Create.

 

denverbrittain_35-1682366102640.png

 

Note: A resource group was created while deploying our Java Spring Boot application.

  

denverbrittain_36-1682366102646.png

 

denverbrittain_37-1682366102653.png

 

Open Azure Active Directory to get the Tenant ID

 

denverbrittain_38-1682366102667.png

 

Let’s move to next step under Peering Connection Popup, where we fill in the required details as below:

  1. Subscription ID: 32-character-long alphanumeric string which can be found as Subscription ID of the virtual network created in the resource group where the Java Spring Boot Application is deployed.
  2. Directory/Tenant ID: 32-character-long alphanumeric string which can be found in the Tenant ID field under Microsoft Azure Active Directory.
  3. Resource Group: Add the resource group in which the app service is deployed.
  4. VNet Name: Name of the virtual network that was newly created.
  5. Atlas CIDR: Keep this as is since our Atlas cluster is already deployed.
  6. VNet Region: Choose the region of your Atlas cluster that should be accessible by the peering connection.

 

denverbrittain_39-1682366162128.png

 

Now we have to do the final step of peering connection by granting access from Microsoft Azure. Follow the steps given in the Grant Access tab under the Peering Connection popup.

 

We need to execute the following commands one by one in Microsoft Azure CloudShell.

 

Please note: We can click on the power shell button in the top right toolbar in the Microsoft Azure portal.

 

denverbrittain_40-1682366162131.png

 

 

denverbrittain_41-1682366162139.png

 

4. Copy the command to create the service principal for MongoDB Atlas and execute as below in the Microsoft Azure CLI or CloudShell (the first icon on the right in the Microsoft Azure portal header).

 

denverbrittain_42-1682366162155.png

 

5. Create a JSON file locally in your local machine with the copied JSON given in Step 2. We can name the file anything we like. We just need to make sure that we reference it accordingly in further steps. For our example, we named it peering.json. Upload the file from your local machine to Azure Cloud Shell as shown below, and then execute the command given in Step 3 in the Grant Access tab with the correct role definition JSON file name.

 

denverbrittain_43-1682366162174.png

 

 6. Run the command in Step 4 of the Peering Connection Screenshot to assign the role to the service principal we created in Step 1.

 

denverbrittain_44-1682366162200.png

 

7. Now click on the Validate button as per Step 5 of the Grant Access tab. If the access grant from Microsoft Azure is successful, we will see the below message in green.

 

 

denverbrittain_45-1682366162213.png

 

8. Click on the Initiate Peering button, and the peering connection will be shown as below in Pending and then the Available state in a few minutes.

 

denverbrittain_46-1682366162221.png

 

denverbrittain_47-1682366162227.png

 

Conclusion

 

In this tutorial, we saw how to connect MongoDB Atlas with Azure App Services using the MongoDB Java driver to build scalable Java Spring Boot web applications.

While we didn't see it in this tutorial, there are many things you can do with the Java driver for MongoDB, such as complex queries with an aggregation pipeline as well as basic CRUD operations.

 

The code base used in this tutorial can be downloaded from the Github Repository.

To see more of what you can accomplish with MongoDB and Java, check out the MongoDB Developer Center.

 

With MongoDB Atlas on Microsoft Azure, developers receive access to the most comprehensive, secure, scalable, and cloud–based developer data platform in 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.

Version history
Last update:
‎Jun 28 2023 06:46 AM
Updated by: