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
- A supported Java Development Kit (JDK). For more information about the JDKs available when developing on Azure, see Java support on Azure and Azure Stack.
- An IDE. We will be using IntelliJ IDEA, Ultimate Edition
- The Azure Toolkit for IntelliJ. For more information, see Install the Azure Toolkit for IntelliJ.
- A MongoDB Atlas cluster deployed with appropriate network rules and database users. Try it for free, if you don’t have a MongoDB Atlas account. We will see how to do this step by step.
- The code can be downloaded from the Github repository.
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.
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.
3. Load a sample data set, if you’d like, when the cluster is ready by clicking on the ellipsis button.
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.
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.
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.
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.
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.
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.
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.
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.
- 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);
}
}
- 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());
}
}
- 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;
}
}
- 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:
- 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.)
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.
2. Try to access it locally once on port 8080, after Run Configuration executes successfully.
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"
}'
Alternatively, we can use MongoDB Atlas by going to our cluster deployed on Azure and clicking on Browse Collections.
Then, click on Insert Document and insert the document.
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.
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.
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.
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.
7. Create the app settings to add your secrets (connection string, dbName, collections, etc.).
- Name: name of the secret
- Value: value of the secret
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.
8. Click on Apply and then Run to deploy the app service to Azure. The toolkit will start creating a:
- Resource Group.
- App Service plan.
- 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.
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.
- 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.
- 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.
- 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.
Note: A resource group was created while deploying our Java Spring Boot application.
Open Azure Active Directory to get the Tenant ID
Let’s move to next step under Peering Connection Popup, where we fill in the required details as below:
- 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.
- Directory/Tenant ID: 32-character-long alphanumeric string which can be found in the Tenant ID field under Microsoft Azure Active Directory.
- Resource Group: Add the resource group in which the app service is deployed.
- VNet Name: Name of the virtual network that was newly created.
- Atlas CIDR: Keep this as is since our Atlas cluster is already deployed.
- VNet Region: Choose the region of your Atlas cluster that should be accessible by the peering connection.
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.
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).
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.
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.
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.
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.
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.