How to use the Spring Boot Starter with the Azure Cosmos DB SQL API

Azure Cosmos DB is a globally-distributed database service that allows developers to work with data using a variety of standard APIs, such as SQL, MongoDB, Graph, and Table APIs. Microsoft's Spring Boot Starter enables developers to use Spring Boot applications that easily integrate with Azure Cosmos DB by using the SQL API.

This article demonstrates creating an Azure Cosmos DB using the Azure portal, then using the Spring Initializr to create a custom Spring Boot application, and then add the Spring Boot Cosmos DB Starter for Azure to your custom application to store data in and retrieve data from your Azure Cosmos DB by using Spring Data and the Cosmos DB SQL API.

Prerequisites

The following prerequisites are required in order to follow the steps in this article:

Create an Azure Cosmos DB by using the Azure portal

  1. Browse to the Azure portal at https://portal.azure.com/ and click Create a resource.

  2. Click Databases, and then click Azure Cosmos DB.

    Azure portal

  3. On the Azure Cosmos DB page, enter the following information:

    • Choose the Subscription you want to use for your database.
    • Specify whether to create a new Resource group for your database, or choose an existing resource group.
    • Enter a unique Account Name, which you will use as the URI for your database. For example: wingtiptoysdata.
    • Choose Core (SQL) for the API.
    • Specify the Location for your database.

    When you have specified these options, click Review + create, review your specifications, and click Create.

    Azure portal

  4. When your database has been created, it is listed on your Azure Dashboard, as well as under the All Resources and Azure Cosmos DB pages. You can click on your database on any of those locations to open the properties page for your cache.

  5. When the properties page for your database is displayed, click Keys and copy your URI and access keys for your database; you will use these values in your Spring Boot application.

    Azure portal

Create a simple Spring Boot application with the Spring Initializr

Use the following steps to create a new Spring Boot application project with Azure support. As an alternative, you can use the azure-cosmosdb-spring-boot-sample sample in the azure-spring-boot repo. Then, you can skip directly to Build and test your app.

  1. Browse to https://start.spring.io/.

  2. Specify that you want to generate a Maven Project with Java, specify your Spring Boot version, enter the Group and Artifact names for your application, add Azure Support in the dependencies, and then click the button to Generate Project.

    Basic Spring Initializr options

    Note

    The Spring Initializr uses the Group and Artifact names to create the package name; for example: com.example.wintiptoysdata.

  3. When prompted, download the project to a path on your local computer and extract the files.

Your simple Spring Boot application is now ready for editing.

Configure your Spring Boot application to use the Azure Spring Boot Starter

  1. Locate the pom.xml file in the directory of your app; for example:

    C:\SpringBoot\wingtiptoysdata\pom.xml

    -or-

    /users/example/home/wingtiptoysdata/pom.xml

  2. Open the pom.xml file in a text editor, and add the following to the <dependencies> element:

    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-cosmosdb-spring-boot-starter</artifactId>
    </dependency>
    
  3. Verify that the properties element indicates the required versions of Java and Azure:

    <properties>
       <java.version>1.8</java.version>
       <azure.version>2.2.0</azure.version>
    </properties>
    
  4. Save and close the pom.xml file.

Configure your Spring Boot application to use your Azure Cosmos DB

  1. Locate the application.properties file in the resources directory of your app; for example:

    C:\SpringBoot\wingtiptoysdata\src\main\resources\application.properties

    -or-

    /users/example/home/wingtiptoysdata/src/main/resources/application.properties

  2. Open the application.properties file in a text editor, and add the following lines to the file, and replace the sample values with the appropriate properties for your database:

    # Specify the DNS URI of your Azure Cosmos DB.
    azure.cosmosdb.uri=https://wingtiptoys.documents.azure.com:443/
    
    # Specify the access key for your database.
    azure.cosmosdb.key=57686f6120447564652c20426f6220526f636b73==
    
    # Specify the name of your database.
    azure.cosmosdb.database=wingtiptoysdata
    
  3. Save and close the application.properties file.

Add sample code to implement basic database functionality

In this section you create two Java classes for storing user data, and then you modify your main application class to create an instance of the User class and save it to your database.

Define a base class for storing user data

  1. Create a new file named User.java in the same directory as your main application Java file.

  2. Open the User.java file in a text editor, and add the following lines to the file to define a generic user class that stores and retrieve values in your database:

    package com.example.wingtiptoysdata;
    
    import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
    import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey;
    import org.springframework.data.annotation.Id;
    
    @Document(collection = "mycollection")
    public class User {
    
        @Id
        private String id;
        private String firstName;
    
        @PartitionKey
        private String lastName;
        private String address;
    
        public User(String id, String firstName, String lastName, String address) {
            this.id = id;
            this.firstName = firstName;
            this.lastName = lastName;
            this.address = address;
        }
    
        public User() {
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getFirstName() {
            return firstName;
        }
    
        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return String.format("%s %s, %s", firstName, lastName, address);
        }
    }
    
  3. Save and close the User.java file.

Define a data repository interface

  1. Create a new file named UserRepository.java in the same directory as your main application Java file.

  2. Open the UserRepository.java file in a text editor, and add the following lines to the file to define a user repository interface that extends the default ReactiveCosmosRepository interface:

    package com.example.wingtiptoysdata;
    
    import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository;
    import org.springframework.stereotype.Repository;
    import reactor.core.publisher.Flux;
    
    @Repository
    public interface UserRepository extends ReactiveCosmosRepository<User, String> {
        Flux<User> findByFirstName(String firstName);
    }
    

    The ReactiveCosmosRepository interface replaces the DocumentDbRepository interface from the previous version of the starter. The new interface provides synchronous and reactive APIs for basic save, delete, and find operations.

  3. Save and close the UserRepository.java file.

Modify the main application class

  1. Locate the main application Java file in the package directory of your application, for example:

    C:\SpringBoot\wingtiptoysdata\src\main\java\com\example\wingtiptoysdata\WingtiptoysdataApplication.java

    -or-

    /users/example/home/wingtiptoysdata/src/main/java/com/example/wingtiptoysdata/WingtiptoysdataApplication.java

  2. Open the main application Java file in a text editor, and add the following lines to the file:

    package com.example.wingtiptoysdata;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.util.Assert;
    import reactor.core.publisher.Flux;
    import reactor.core.publisher.Mono;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    import java.util.Optional;
    
    @SpringBootApplication
    public class WingtiptoysdataApplication implements CommandLineRunner {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(WingtiptoysdataApplication.class);
    
        @Autowired
        private UserRepository repository;
    
        public static void main(String[] args) {
            SpringApplication.run(WingtiptoysdataApplication.class, args);
        }
    
        public void run(String... var1) throws Exception {
            final User testUser = new User("1", "Tasha", "Calderon", "4567 Main St Buffalo, NY 98052");
    
            LOGGER.info("Saving user: {}", testUser);
    
            // Save the User class to Azure CosmosDB database.
            final Mono<User> saveUserMono = repository.save(testUser);
    
            final Flux<User> firstNameUserFlux = repository.findByFirstName("testFirstName");
    
            //  Nothing happens until we subscribe to these Monos.
            //  findById will not return the user as user is not present.
            final Mono<User> findByIdMono = repository.findById(testUser.getId());
            final User findByIdUser = findByIdMono.block();
            Assert.isNull(findByIdUser, "User must be null");
    
            final User savedUser = saveUserMono.block();
            Assert.state(savedUser != null, "Saved user must not be null");
            Assert.state(savedUser.getFirstName().equals(testUser.getFirstName()), "Saved user first name doesn't match");
    
            LOGGER.info("Saved user");
    
            firstNameUserFlux.collectList().block();
    
            final Optional<User> optionalUserResult = repository.findById(testUser.getId()).blockOptional();
            Assert.isTrue(optionalUserResult.isPresent(), "Cannot find user.");
    
            final User result = optionalUserResult.get();
            Assert.state(result.getFirstName().equals(testUser.getFirstName()), "query result firstName doesn't match!");
            Assert.state(result.getLastName().equals(testUser.getLastName()), "query result lastName doesn't match!");
    
            LOGGER.info("Found user by findById : {}", result);
        }
    
        @PostConstruct
        public void setup() {
            LOGGER.info("Clear the database");
            this.repository.deleteAll().block();
        }
    
        @PreDestroy
        public void cleanup() {
            LOGGER.info("Cleaning up users");
            this.repository.deleteAll().block();
        }
    }
    
  3. Save and close the main application Java file.

Build and test your app

  1. Open a command prompt and navigate to the folder where your pom.xml file is located; for example:

    cd C:\SpringBoot\wingtiptoysdata

    -or-

    cd /users/example/home/wingtiptoysdata

  2. Use the following command to build and run your application:

    mvnw clean test
    

    This command runs the application automatically as part of the test phase. You can also use:

    mvnw clean spring-boot:run
    

    After some build and test output, your console window will display a message similar to the following:

      .   ____          _            __ _ _
     /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
     \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::            (v2.2.0.RC1)
    >
    > 2019-10-04 15:19:06.817  INFO 30013 --- [           main] c.e.w.WingtiptoysdataApplicationTests    : Starting WingtiptoysdataApplicationTests on devmachine03 with PID 30013 (started by <user> in /d/source/repos/wingtiptoysdata)
    > 2019-10-04 15:19:06.818  INFO 30013 --- [           main] c.e.w.WingtiptoysdataApplicationTests    : No active profile set, falling back to default profiles: default
    > 2019-10-04 15:19:08.329  INFO 30013 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
    > 2019-10-04 15:19:09.720  INFO 30013 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 1369ms. Found 1 repository interfaces.
    > 2019-10-04 15:19:09.734  INFO 30013 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
    > 2019-10-04 15:19:09.748  INFO 30013 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 13ms. Found 0 repository interfaces.
    
    ... (omitting Cosmos DB connection output) ...
    
    > 2019-10-04 15:19:46.584  INFO 30013 --- [           main] c.e.w.WingtiptoysdataApplicationTests    : Started WingtiptoysdataApplicationTests in 40.702 seconds (JVM running for 44.647)
    > 2019-10-04 15:19:46.587  INFO 30013 --- [           main] c.e.w.WingtiptoysdataApplication         : Saving user: Tasha Calderon, 4567 Main St Buffalo, NY 98052
    > 2019-10-04 15:19:47.122  INFO 30013 --- [           main] c.e.w.WingtiptoysdataApplication         : Saved user
    > 2019-10-04 15:19:47.289  INFO 30013 --- [           main] c.e.w.WingtiptoysdataApplication         : Found user by findById : Tasha Calderon, 4567 Main St Buffalo, NY 98052
    > [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 44.003 s - in com.example.wingtiptoysdata.WingtiptoysdataApplicationTests
    > 2019-10-04 15:19:48.124  INFO 30013 --- [extShutdownHook] c.a.d.c.internal.RxDocumentClientImpl    : Shutting down ...
    > 2019-10-04 15:19:48.194  INFO 30013 --- [extShutdownHook] c.a.d.c.internal.RxDocumentClientImpl    : Shutting down ...
    > 2019-10-04 15:19:48.200  INFO 30013 --- [extShutdownHook] c.e.w.WingtiptoysdataApplication         : Cleaning up users
    > [INFO]
    > [INFO] Results:
    > [INFO]
    > [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    > [INFO]
    > [INFO]
    > [INFO] --- maven-jar-plugin:3.1.2:jar (default-jar) @ wingtiptoysdata ---
    > [INFO] Building jar: /d/source/repos/wingtiptoysdata/target/wingtiptoysdata-0.0.1-SNAPSHOT.jar
    > [INFO]
    > [INFO] --- spring-boot-maven-plugin:2.2.0.RC1:repackage (repackage) @ wingtiptoysdata ---
    > [INFO] Replacing main artifact with repackaged archive
    > [INFO] ------------------------------------------------------------------------
    > [INFO] BUILD SUCCESS
    > [INFO] ------------------------------------------------------------------------
    > [INFO] Total time:  02:18 min
    > [INFO] Finished at: 2019-10-04T15:20:05-07:00
    > [INFO] ------------------------------------------------------------------------
    

    Successful output from the application

    The Saved user and Found user messages indicate that the data was successfully saved to Cosmos DB and then retrieved again.

Clean up resources

If you're not going to continue to use this application, be sure to delete the resource group containing the Cosmos DB you created earlier. You can do this from the Azure portal.

Next steps

To learn more about Spring and Azure, continue to the Spring on Azure documentation center.

Additional Resources

For more information about using Azure Cosmos DB and Java, see the following articles:

For more information about using Spring Boot applications on Azure, see the following articles:

For more information about using Azure with Java, see the Azure for Java Developers and the Working with Azure DevOps and Java.

The Spring Framework is an open-source solution that helps Java developers create enterprise-level applications. One of the more-popular projects that is built on top of that platform is Spring Boot, which provides a simplified approach for creating stand-alone Java applications. To help developers get started with Spring Boot, several sample Spring Boot packages are available at https://github.com/spring-guides/. In addition to choosing from the list of basic Spring Boot projects, the Spring Initializr helps developers get started with creating custom Spring Boot applications.