Support of Azure Cosmos DB for Spring Data

CAST supports Azure Cosmos DB via its com.castsoftware.nosqljava extension. Details about how this support is provided for Spring Data source code is discussed below.

Supported Client Libraries

Library Version Supported
Azure spring data cosmos Up to: 3.10.0

Supported Operations

Operations Method Supported
Insert
org.springframework.data.repository
  • org.springframework.data.repository.CrudRepository.save
  • org.springframework.data.repository.CrudRepository.saveAll
  • org.springframework.data.repository.reactive.ReactiveCrudRepository.save
  • org.springframework.data.repository.reactive.ReactiveCrudRepository.saveAll
com.microsoft.azure.spring.data.cosmosdb.repository
  • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.save
  • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.saveAll
  • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.save
  • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.saveAll
  • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.save
  • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.saveAll
  • com.azure.spring.data.cosmos.repository
    • com.azure.spring.data.cosmos.repository.CosmosRepository.save
    • com.azure.spring.data.cosmos.repository.CosmosRepository.saveAll
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.save
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.saveAll
    com.microsoft.azure.spring.data.cosmosdb.core
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.insert
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.insert
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.insert
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.insert
    • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.insert
    • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.insert
    Select
    org.springframework.data.repository
    • org.springframework.data.repository.CrudRepository.existsById
    • org.springframework.data.repository.CrudRepository.findAll
    • org.springframework.data.repository.CrudRepository.findById
    • org.springframework.data.repository.PagingAndSortingRepository.findAll
    • org.springframework.data.repository.reactive.ReactiveCrudRepository.existsById
    • org.springframework.data.repository.reactive.ReactiveCrudRepository.findAll
    • org.springframework.data.repository.reactive.ReactiveCrudRepository.findAllById
    • org.springframework.data.repository.reactive.ReactiveCrudRepository.findById
    • org.springframework.data.repository.reactive.ReactiveSortingRepository.findAll
    com.azure.spring.data.cosmos.repository
    • com.azure.spring.data.cosmos.repository.CosmosRepository.findById
    • com.azure.spring.data.cosmos.repository.CosmosRepository.findAll
    • com.azure.spring.data.cosmos.repository.CosmosRepository.existsById
    • com.azure.spring.data.cosmos.repository.CosmosRepository.count
    • com.azure.spring.data.cosmos.repository.CosmosRepository.findAllById
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.findbyId
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.findAll
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.existsById
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.count
    • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.findAllById
    com.microsoft.azure.spring.data.cosmosdb.repository
    • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.findById
    • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.findAll
    • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.existsById
    • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.findAllById
    • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.count
    • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.findAll
    • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.existsById
    • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.findAllById
    • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.count
    • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveSortingRepository.findAll
    • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.findById
    • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.findAll
    • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.count
    • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.findAllById
    • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.existsById
    com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.findAll
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.find
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.findByIds
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.exists
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.count
    • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.findById
    com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate
  • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.findById
  • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.find
  • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.findAll
  • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.findByIds
  • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.count
  • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.exists
  • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.findAll
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.find
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.findByIds
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.exists
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.existsById
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.count
    • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.findById
      com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.findById
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.find
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.findAll
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.count
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.exists
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.existsById
      com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.count
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.exists
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.find
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.findAll
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.findById
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.count
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.exists
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.find
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.findAll
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.findById
      Delete
      org.springframework.data.repository
      • org.springframework.data.repository.CrudRepository.delete
      • org.springframework.data.repository.CrudRepository.deleteById
      • org.springframework.data.repository.CrudRepository.deleteAllById
      • org.springframework.data.repository.CrudRepository.deleteAll
      • org.springframework.data.repository.reactive.ReactiveCrudRepository.delete
      • org.springframework.data.repository.reactive.ReactiveCrudRepository.deleteAll
      • org.springframework.data.repository.reactive.ReactiveCrudRepository.deleteAllById
      • org.springframework.data.repository.reactive.ReactiveCrudRepository.deleteById
      com.azure.spring.data.cosmos.repository
      • com.azure.spring.data.cosmos.repository.CosmosRepository.deleteById
      • com.azure.spring.data.cosmos.repository.CosmosRepository.delete
      • com.azure.spring.data.cosmos.repository.CosmosRepository.deleteAll
      • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.deletebyId
      • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.deleteAll
      • com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository.delete
      com.microsoft.azure.spring.data.cosmosdb.core
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.delete
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.deleteCollection
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.delete
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.deleteCollection
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.delete
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.deleteCollection
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.delete
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.deleteCollection
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.delete
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.delete
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.deleteCollection
      com.microsoft.azure.spring.data.cosmosdb.repository
      • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository.delete
      • com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository.deleteById
      • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.deletebyId
      • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.deleteAll
      • com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository.delete
      Upsert
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations.upsert
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations.upsert
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations.upsert
      • com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate.upsert
      • com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate.upsert
      • com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate.upsert

      Above mentioned methods are supported for both Synchronous and Asynchronous clients.

      Objects

      Icon Description
      Java CosmosDB Database
      Java CosmosDB Collection
      Java Unknown CosmosDB Database
      Java Unknown CosmosDB Collection
      Link type Source and destination of link Methods Supported
      parentLink Between CosmosDB Database object and CosmosDB Collection -
      useInsertLink Between the caller Java Method objects and CosmosDB Collection save
      saveAll
      useSelectLink Between the caller Java Method objects and CosmosDB Collection existsById
      findById
      findAll
      findAllById
      count
      useDeleteLink Between the caller Java Method objects and CosmosDB Collection delete
      deleteAll
      deleteById
      deleteAllById

      What results can you expect?

      Some example scenarios are shown below:

      CosmosDB Database Connection from Properties File

      application.properties

      application.properties

      azure.cosmosdb.uri=https://cosmoswithspring.documents.azure.com:443/
      azure.cosmosdb.key=2VanbwRYNeJKCUjb5StsnBKaatDcKGRUckHnlSUVSJXifWL3exjwjP2o6rJpt8fY24MRmtnctzcE8hWAlBsRZw==
      azure.cosmosdb.database=cosmoswithspring
      

      Cosmos DB Client Creation

      @Configuration
      @EnableDocumentDbRepositories
      public class AppConfig extends AbstractDocumentDbConfiguration {
       
          @Value("${azure.documentdb.uri}")
          private String uri;
       
          @Value("${azure.documentdb.key}")
          private String key;
       
          @Value("${azure.documentdb.database}")
          private String dbName;
       
          public DocumentClient documentClient() {
              return new DocumentClient(uri, key, ConnectionPolicy.GetDefault(), ConsistencyLevel.Session);
          }
       
          public String getDatabase() {
              return dbName;
          }
      }
      

      Select Operation

      CreateDocument

         @Autowired
          private AlertRepository alertRepository;
      
          @GetMapping("/all")
          public Iterable getAllAlerts() {
              if (StreamSupport.stream(alertRepository.findAll().spliterator(), false).count() > 0) {
                  return alertRepository.findAll();
              } else {
                  throw new ValidationException("No records found.");
              }
          }
      
       @GetMapping("/count")
          public long countAlert() {
              if (StreamSupport.stream(alertRepository.findAll().spliterator(), false).count() > 0) {
                  return alertRepository.count();
              } else {
                  throw new ValidationException("No records found.");
              }
          }
      

      Insert Operation

      QueryDocuments

       @PostMapping("/add")
          public StatusMessage addAlert(@Valid @RequestBody Alert alert) {
              Alert returnedAlert = alertRepository.save(alert);
              if (returnedAlert.getAlertId().isEmpty()) {
                  throw new ValidationException("Error accessing Cosmos database.");
              }
              return new StatusMessage("200", "Alert Added");
          }
      

      Delete Operation

      DeleteDocument

      @GetMapping("/deleteall")
          public StatusMessage deleteAllAlert() {
              alertRepository.deleteAll();
              
              return new StatusMessage("200", "Alert Deleted");
          }
      
       @DeleteMapping("/delete/{id}")
          public StatusMessage deleteAlert(@PathVariable String id) throws NotFoundException {
              //Optional<Alert> returnedAlert = alertRepository.findById(id);
              if (!alertRepository.existsById(id)) {
                  throw new NotFoundException("No alert found with id: " + id);
              }
              alertRepository.deleteById(id);
              return new StatusMessage("200", "alert deleted.");
          }
      

      Query Method Support

      Repo with query method

      @Repository
      public interface AlertRepository extends CosmosRepository<Alert, String> {
      // repo for alert
          List<Alert> findById(String priority);
      }
      

      Controller

      @GetMapping("find/{id}")
          public Alert findAlert(@PathVariable String id) throws NotFoundException {
              return alertRepository.findById(id).orElseThrow(
                      () -> new NotFoundException("No alert found with id: " + id)
              );
      }
      

      Query Methods with @Query annotation

      Repository with @query methods

      @Repository
      public interface AddressRepository extends CosmosRepository<Address, String> {
          void deleteByPostalCodeAndCity(String postalCode, String city);
      
          void deleteByCity(String city);
      
          Iterable<Address> findByPostalCodeAndCity(String postalCode, String city);
      
          Iterable<Address> findByCity(String city);
      
          Iterable<Address> findByCityIn(List<String> cities);
      
          Iterable<Address> findByPostalCode(String postalCode);
      
          Iterable<Address> findByPostalCodeInAndCity(List<String> postalCodes, String city);
      
          Iterable<Address> findByStreetOrCity(String street, String city);
      
          @Query("select * from a where a.city = @city")
          List<Address> annotatedFindListByCity(@Param("city") String city);
      
          @Query("select * from a where a.city = @city")
          Page<Address> annotatedFindByCity(@Param("city") String city, Pageable pageable);
      }
      
      public void testAnnotatedQuery() {
              addressRepository.saveAll(Arrays.asList(Address.TEST_ADDRESS1_PARTITION1, Address.TEST_ADDRESS1_PARTITION2));
      
              final List<Address> result = addressRepository.annotatedFindListByCity(Address.TEST_ADDRESS1_PARTITION1.getCity());
              assertThat(result).isNotNull();
              assertThat(result.size()).isEqualTo(1);
              assertThat(result.get(0)).isEqualTo(Address.TEST_ADDRESS1_PARTITION1);
          }
      

      Asynchronous API

      All corresponding methods are represented and results are very similar to its Synchronous counterpart. Async Client creation:

      import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository;
      
      import info.hayslip.AlertHoarder.models.Alert;
      import org.springframework.stereotype.Repository;
      
      @Repository
      public interface AlertReactRepository extends ReactiveCosmosRepository<Alert, String> {
      // repo for alert
      }
      

      Known Limitations

      • Database/Collection is created as unknown, if the name is not retrieved from the properties file or if the name could not be resolved.