Connecting a Spring Boot Application to Azure Cosmos DB for Caching

1. Overview

In this blog, we’ll learn about Azure Cosmos DB and how we can interact with it using Spring Data.

2. What is Azure Cosmos DB?

Azure Cosmos DB is a fully managed, NoSQL database service provided by Microsoft Azure. It supports multiple models, including DocumentDB, Cassandra, MongoDB, Gremlin, and Table APIs, which gives developers the flexibility to choose the right model for their applications. Its global distribution, automatic multi-region replication, and low-latency reads and writes make it ideal for use cases that require fast access to data, such as caching.

3. Setting up Azure Cosmos DB

  1. Create a Cosmos DB Account:

    • Go to the Azure Portal.

    • Navigate to Create a resource > Databases > Azure Cosmos DB.

    • Choose the appropriate API (e.g., SQL for document-based storage).

    • Select your subscription, resource group, and region, and give your Cosmos DB a name.

    • Click Review + Create and then Create.

  2. Create a Database and Container:

    • Once your Cosmos DB instance is created, go to the Data Explorer.

    • Create a new database (e.g., MyDatabase).

    • Inside the database, create a new container (e.g., MyCacheContainer) with a partition key (e.g., /id).

  3. Get the Cosmos DB Connection String:

    • In the Keys section of your Cosmos DB account, find the URI and Primary Key.

    • You will need these credentials to connect your Spring Boot application to Cosmos DB.

4. Using Azure Cosmos DB in Spring

4.1. Add Dependencies to Your Spring Boot Application

To connect your Spring Boot application to Azure Cosmos DB, you need to include the necessary dependencies in your pom.xml file.

<dependency>

<groupId>com.azure</groupId>

<artifactId>azure-spring-data-cosmos</artifactId>

<version>5.17.1</version>

</dependency>

4.2. Configure the Connection to Azure Cosmos DB

To access Azure Cosmos DB from our Spring application, we’ll need the URI of our database, its access keys and the database name. Then we’ll add the connection properties in our application.properties:

azure.cosmosdb.uri=cosmodb-uri

azure.cosmosdb.key=cosmodb-primary-key

azure.cosmosdb.secondaryKey=cosmodb-secondary-key

azure.cosmosdb.database=cosmodb-name

To connect to Azure Cosmos DB from our application, we need to create a client. For that, we need to extend AbstractCosmosConfiguration class in our configuration class and add the @EnableCosmosRepositories annotation.
We also need to configure a bean of type CosmosDBConfig i.e. CosmosDBConfig.java:

import com.azure.cosmos.CosmosClientBuilder;

import com.azure.cosmos.CosmosContainer;

import com.azure.cosmos.DirectConnectionConfig;

import com.azure.spring.data.cosmos.config.AbstractCosmosConfiguration;

import com.azure.spring.data.cosmos.config.CosmosConfig;

import com.azure.spring.data.cosmos.core.ResponseDiagnostics;

import com.azure.spring.data.cosmos.core.ResponseDiagnosticsProcessor;

import com.azure.spring.data.cosmos.repository.config.EnableCosmosRepositories;

import com.azure.spring.data.cosmos.repository.config.EnableReactiveCosmosRepositories;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.lang.Nullable;

We also need to configure a bean of type CosmosDBConfig:

@Configuration

@EnableCosmosRepositories

@EnableReactiveCosmosRepositories

public class CosmosDbConfig extends AbstractCosmosConfiguration {

private static final Logger logger = LoggerFactory.getLogger(CosmosDbConfig.class);

@Value("${azure.cosmosdb.uri}")

private String uri;

@Value("${azure.cosmosdb.key}")

private String key;

@Value("${azure.cosmosdb.database}")

private String dbName;

@Bean

public CosmosClientBuilder cosmosClientBuilder() {

DirectConnectionConfig directConnectionConfig = DirectConnectionConfig.getDefaultConfig();

return new CosmosClientBuilder()

.endpoint(uri)

.key(key)

.directMode(directConnectionConfig);

}

@Bean

public CosmosConfig cosmosConfig() {

return CosmosConfig.builder()

.responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())

.enableQueryMetrics(true)

.build();

}

@Bean

public CosmosContainer cosmosContainer() {

return cosmosClientBuilder().buildClient().getDatabase(dbName).getContainer("GroupTNs");

}

@Override

protected String getDatabaseName() {

return dbName;

}

private static class ResponseDiagnosticsProcessorImplementation implements ResponseDiagnosticsProcessor {

@Override

public void processResponseDiagnostics(@Nullable ResponseDiagnostics responseDiagnostics) {

logger.info("Response Diagnostics {}", responseDiagnostics);

}

}

}

4.3. Creating an Entity for Azure Cosmos DB

@Container(containerName = "products", ru = "400")

@Data

@Schema(description = "Product entity representing a group telephone number")

public class Product {

@Id

private String productid;

private String productName;

private double price;

@PartitionKey

private String productCategory;

}

4.4. Defining the Repository

Now let’s create a ProductRepository interface that extends CosmosRepository. Using this interface, we can perform CRUD operations on our Azure Cosmos DB:

package com.lumen.voice.feature.api.repository;

import com.azure.spring.data.cosmos.repository.CosmosRepository ;

import com.azure.spring.data.cosmos.repository.Query;

import org.springframework.data.repository.query.Param;

import org.springframework.stereotype.Repository;

@Repository

public interface ProductRepository extends CosmosRepository<Product, String> {

// Method to fetch data based on Id using a custom query

@Query("SELECT * FROM c WHERE c.Id = @Id")

List<Product> findById(@Param("Id") String Id);

}

4.5 Defining the Service
Now we need to create ProductService
// Method to get data based on networkCustomerId

public List<Product> getProductById(String Id) {

return productRepository.findById(Id);

}

Note: If you get any error related to bean creation then need to add below in after @SpringBootApplication in main class:
@EnableCosmosRepositories(basePackages = "com.example.your.repository")

5. Conclusion

In this blog, we've covered how to connect a Spring Boot application to Azure Cosmos DB for caching. By using Spring Data Cosmos DB, Spring Cache, and the powerful scalability of Cosmos DB, we can easily implement a fast, distributed caching solution for your application.

With Cosmos DB’s high availability, low latency, and scalability, it’s an excellent choice for caching frequently accessed data in cloud-native applications.

Happy coding! 🚀