Full Reactive Repository Support, Rebranding DocumentDb to CosmosDb (#434)

* Addind reactive repository support

* deleteAll fix

* Fixing deleteAll issue
Rebranding DocumentDB types to Cosmos
Removing docdb dependency
Upgrading SDK to 3.2
Changing perf tests to use 3.2 sync api
Other refactoring

* Upgraded pom.xml to use new spring RC versions. Made other changes to support new versions

* Updated pom.xml to milestone version

* Removing unused imports

* Renaming bean method

* Renamed documentdb to cosmosdb

* updated pom.xml with correct file name

* Added new APIs for find by id with partitionkey

* Updated cosmos factory to take in connection policy and consistency level in account while creating cosmos client

* Removed and implemented some of the TODOs from spring feedback

* Updated readme to reflect CosmosRepository

* Updated Reactive Cosmos Entity MetaData to be used in Reactive Cosmos Query pipeline

* Updated sample to full reactive support.
Updated error handlers for reactive cosmos template to throw CosmosDbAccessException
This commit is contained in:
Kushagra Thapar 2019-09-27 00:27:39 -07:00 коммит произвёл GitHub
Родитель 6c207219a5
Коммит d028e00ab9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
132 изменённых файлов: 2182 добавлений и 1590 удалений

Просмотреть файл

@ -1,3 +1,3 @@
exclude_paths:
- 'src/test/java/com/microsoft/azure/spring/data/cosmosdb/domain/Person.java'
- 'src/test/java/com/microsoft/azure/spring/data/cosmosdb/repository/support/DocumentDbEntityInformationUnitTest.java'
- 'src/test/java/com/microsoft/azure/spring/data/cosmosdb/repository/support/CosmosEntityInformationUnitTest.java'

Просмотреть файл

@ -29,7 +29,7 @@ Please refer to [sample project here](./samplecode).
This repository supports both Spring Data 1.x and 2.x. Please see [this document](https://github.com/Microsoft/spring-data-cosmosdb/wiki/Spring-Data-dependency-version-management) about more details and corresponding branch mapping.
## Feature List
- Spring Data CRUDRepository basic CRUD functionality
- Spring Data ReactiveCrudRepository CrudRepository basic CRUD functionality
- save
- findAll
- findOne by Id
@ -73,7 +73,7 @@ If you are using Maven, add the following dependency.
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-data-cosmosdb</artifactId>
<version>2.1.7</version>
<version>2.2.0.M1</version>
</dependency>
```
@ -83,10 +83,17 @@ Setup configuration class.
CosmosKeyCredential feature provides capability to rotate keys on the fly. You can switch keys using switchToSecondaryKey().
For more information on this, see the Sample Application code.
### Sync and Reactive Repository support
2.2.x supports both sync and reactive repository support.
Use `@EnableCosmosRepositories` to enable sync repository support.
For reactive repository support, use `@EnableReactiveCosmosRepositories`
```java
@Configuration
@EnableDocumentDbRepositories
public class AppConfiguration extends AbstractDocumentDbConfiguration {
@EnableCosmosRepositories
public class AppConfiguration extends AbstractCosmosConfiguration {
@Value("${azure.cosmosdb.uri}")
private String uri;
@ -102,9 +109,9 @@ public class AppConfiguration extends AbstractDocumentDbConfiguration {
private CosmosKeyCredential cosmosKeyCredential;
public DocumentDBConfig getConfig() {
public CosmosDBConfig getConfig() {
this.cosmosKeyCredential = new CosmosKeyCredential(key);
return DocumentDBConfig.builder(uri, this.cosmosKeyCredential, dbName).build();
return CosmosDBConfig.builder(uri, this.cosmosKeyCredential, dbName).build();
}
public void switchToSecondaryKey() {
@ -114,19 +121,19 @@ public class AppConfiguration extends AbstractDocumentDbConfiguration {
```
Or if you want to customize your config:
```java
public DocumentDBConfig getConfig() {
public CosmosDBConfig getConfig() {
this.cosmosKeyCredential = new CosmosKeyCredential(key);
DocumentDBConfig dbConfig = DocumentDBConfig.builder(uri, this.cosmosKeyCredential, dbName).build();
dbConfig.getConnectionPolicy().setConnectionMode(ConnectionMode.DirectHttps);
dbConfig.getConnectionPolicy().setMaxPoolSize(1000);
return dbConfig;
CosmosDBConfig cosmosDbConfig = CosmosDBConfig.builder(uri, this.cosmosKeyCredential, dbName).build();
cosmosDbConfig.getConnectionPolicy().setConnectionMode(ConnectionMode.DIRECT);
cosmosDbConfig.getConnectionPolicy().setMaxPoolSize(1000);
return cosmosDbConfig;
}
```
By default, `@EnableDocumentDbRepositories` will scan the current package for any interfaces that extend one of Spring Data's repository interfaces. Using it to annotate your Configuration class to scan a different root package by type if your project layout has multiple projects and it's not finding your repositories.
By default, `@EnableCosmosRepositories` will scan the current package for any interfaces that extend one of Spring Data's repository interfaces. Using it to annotate your Configuration class to scan a different root package by type if your project layout has multiple projects and it's not finding your repositories.
```java
@Configuration
@EnableDocumentDbRepositories(basePackageClass=UserRepository.class)
public class AppConfiguration extends AbstractDocumentDbConfiguration {
@EnableCosmosRepositories(basePackageClass=UserRepository.class)
public class AppConfiguration extends AbstractCosmosConfiguration {
// configuration code
}
```
@ -140,6 +147,7 @@ Define a simple entity as Document in Azure Cosmos DB.
public class User {
private String id;
private String firstName;
@PartitionKey
private String lastName;
@ -178,14 +186,14 @@ public class User {
```
### Create repositories
Extends DocumentDbRepository interface, which provides Spring Data repository support.
Extends CosmosRepository interface, which provides Spring Data repository support.
```java
import DocumentDbRepository;
import CosmosRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends DocumentDbRepository<User, String> {
public interface UserRepository extends CosmosRepository<User, String> {
List<User> findByFirstName(String firstName);
}
```
@ -232,7 +240,7 @@ public class SampleApplication implements CommandLineRunner {
}
}
```
Autowired UserRepository interface, then can do save, delete and find operations. Spring Data Azure Cosmos DB uses the DocumentTemplate to execute the queries behind *find*, *save* methods. You can use the template yourself for more complex queries.
Autowired UserRepository interface, then can do save, delete and find operations. Spring Data Azure Cosmos DB uses the CosmosTemplate to execute the queries behind *find*, *save* methods. You can use the template yourself for more complex queries.
## Snapshots
[![Nexus OSS](https://img.shields.io/nexus/snapshots/https/oss.sonatype.org/com.microsoft.azure/spring-data-cosmosdb.svg)](https://oss.sonatype.org/content/repositories/snapshots/com/microsoft/azure/spring-data-cosmosdb/)

32
pom.xml
Просмотреть файл

@ -6,7 +6,7 @@
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-data-cosmosdb</artifactId>
<version>2.1.8-SNAPSHOT</version>
<version>2.2.0.M1</version>
<name>Spring Data for Azure Cosmos DB SQL API</name>
<description>Spring Data for Azure Cosmos DB SQL API</description>
@ -45,8 +45,8 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.build.timestamp.format>MM-dd-HH-mm-ss</maven.build.timestamp.format>
<spring.springframework.version>5.1.9.RELEASE</spring.springframework.version>
<spring.data.version>2.1.10.RELEASE</spring.data.version>
<spring.springframework.version>5.2.0.RC2</spring.springframework.version>
<spring.data.version>2.2.0.RC3</spring.data.version>
<fasterxml.jackson.version>2.9.5</fasterxml.jackson.version>
<mockito.core.version>2.8.9</mockito.core.version>
@ -58,8 +58,7 @@
<gson.version>2.8.4</gson.version>
<project.reactor.test.version>3.2.5.RELEASE</project.reactor.test.version>
<azure.documentdb.version>1.16.2</azure.documentdb.version>
<azure.cosmos.version>3.1.0</azure.cosmos.version>
<azure.cosmos.version>3.2.0</azure.cosmos.version>
<azure.test.resourcegroup>spring-data-cosmosdb-test</azure.test.resourcegroup>
<azure.test.dbname>testdb-${maven.build.timestamp}</azure.test.dbname>
<skip.integration.tests>true</skip.integration.tests>
@ -67,6 +66,14 @@
<test.on.emualator>false</test.on.emualator>
</properties>
<repositories>
<repository>
<id>spring-milestone</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/libs-milestone</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
@ -115,13 +122,6 @@
<artifactId>spring-expression</artifactId>
<version>${spring.springframework.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-documentdb</artifactId>
<version>${azure.documentdb.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-cosmos</artifactId>
@ -143,7 +143,11 @@
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${fasterxml.jackson.version}</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20140107</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@ -232,7 +236,7 @@
<failOnError>false</failOnError>
<sourceFileExcludes>
<exclude>
com/microsoft/azure/spring/data/cosmosdb/documentdb/core/mapping/BasicDocumentDbPersistentProperty.java
com/microsoft/azure/spring/data/cosmosdb/documentdb/core/mapping/BasicCosmosPersistentProperty.java
</exclude>
</sourceFileExcludes>
</configuration>

Просмотреть файл

@ -5,7 +5,7 @@
<parent>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-data-cosmosdb-samples</artifactId>
<version>2.1.8-SNAPSHOT</version>
<version>2.2.0.M1</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -20,7 +20,7 @@
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-data-cosmosdb</artifactId>
<version>2.1.8-SNAPSHOT</version>
<version>2.2.0.M1</version>
</dependency>
<dependency>

Просмотреть файл

@ -15,13 +15,11 @@
*/
package example.springdata.cosmosdb;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
import org.assertj.core.util.Lists;
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.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import javax.annotation.PostConstruct;
@ -67,40 +65,28 @@ public class Application implements CommandLineRunner{
@Override
public void run(String... args) throws Exception {
printList(this.repository.findByEmailOrName(this.user_1.getEmail(), this.user_1.getName()));
printList(this.repository.findByEmailOrName(this.user_1.getEmail(),
this.user_1.getName()).collectList().block());
printList(this.repository.findByCount(COUNT, Sort.by(new Sort.Order(Sort.Direction.ASC, "count"))));
printList(this.repository.findByCount(COUNT,
Sort.by(new Sort.Order(Sort.Direction.ASC, "count"))).collectList().block());
printList(this.repository.findByNameIn(Arrays.asList(this.user_1.getName(), "fake-name")));
queryByPageable();
}
private void queryByPageable() {
final int pageSize = 2;
final Pageable pageable = new DocumentDbPageRequest(0, pageSize, null);
final Page<User> page = this.repository.findByAddress(address, pageable);
System.out.println("***** Printing Page 1 *****");
printList(page.getContent());
final Page<User> nextPage = this.repository.findByAddress(address, page.getPageable());
System.out.println("***** Printing Page 2 *****");
printList(nextPage.getContent());
printList(this.repository.findByNameIn(Arrays.asList(this.user_1.getName(),
"fake-name")).collectList().block());
}
@PostConstruct
public void setup() {
this.repository.save(user_1);
this.repository.save(user_2);
this.repository.save(user_3);
this.repository.save(user_1).block();
this.repository.saveAll(Lists.newArrayList(user_2, user_3)).collectList().block();
}
@PreDestroy
public void cleanup() {
this.repository.deleteAll();
this.repository.deleteAll().block();
}
private void printList(List<User> users) {
users.forEach(user -> System.out.println(user));
users.forEach(System.out::println);
}
}

Просмотреть файл

@ -22,7 +22,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@Getter
@Setter
@ConfigurationProperties(prefix = "azure.cosmosdb")
public class DocumentDbProperties {
public class CosmosDbProperties {
private String uri;

Просмотреть файл

@ -17,6 +17,7 @@
package example.springdata.cosmosdb;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@ -37,6 +38,7 @@ public class User {
private String email;
@PartitionKey
private String name;
private Long count;

Просмотреть файл

@ -16,30 +16,28 @@
package example.springdata.cosmosdb;
import com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository;
import org.springframework.data.domain.Sort;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import java.util.Collection;
import java.util.List;
@Repository
@RepositoryRestResource(collectionResourceRel = "user", path = "user")
public interface UserRepository extends DocumentDbRepository<User, String> {
public interface UserRepository extends ReactiveCosmosRepository<User, String> {
List<User> findByName(String firstName);
Flux<User> findByName(String firstName);
List<User> findByEmailAndAddress(String email, Address address);
Flux<User> findByEmailAndAddress(String email, Address address);
List<User> findByEmailOrName(String email, String Name);
Flux<User> findByEmailOrName(String email, String name);
List<User> findByCount(Long count, Sort sort);
Flux<User> findByCount(Long count, Sort sort);
List<User> findByNameIn(Collection<String> names);
Flux<User> findByNameIn(Collection<String> names);
Page<User> findByAddress(Address address, Pageable pageable);
Flux<User> findByAddress(Address address);
}

Просмотреть файл

@ -16,9 +16,9 @@
package example.springdata.cosmosdb;
import com.azure.data.cosmos.CosmosKeyCredential;
import com.microsoft.azure.spring.data.cosmosdb.config.AbstractDocumentDbConfiguration;
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableDocumentDbRepositories;
import com.microsoft.azure.spring.data.cosmosdb.config.AbstractCosmosConfiguration;
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableReactiveCosmosRepositories;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@ -27,20 +27,20 @@ import org.springframework.context.annotation.PropertySource;
@Configuration
@EnableDocumentDbRepositories
@EnableConfigurationProperties(DocumentDbProperties.class)
@EnableConfigurationProperties(CosmosDbProperties.class)
@EnableReactiveCosmosRepositories
@PropertySource("classpath:application.properties")
public class UserRepositoryConfiguration extends AbstractDocumentDbConfiguration {
public class UserRepositoryConfiguration extends AbstractCosmosConfiguration {
@Autowired
private DocumentDbProperties properties;
private CosmosDbProperties properties;
private CosmosKeyCredential cosmosKeyCredential;
@Bean
public DocumentDBConfig documentDBConfig() {
public CosmosDBConfig cosmosDbConfig() {
this.cosmosKeyCredential = new CosmosKeyCredential(properties.getKey());
return DocumentDBConfig.builder(properties.getUri(), cosmosKeyCredential, properties.getDatabase()).build();
return CosmosDBConfig.builder(properties.getUri(), cosmosKeyCredential, properties.getDatabase()).build();
}
public void switchToSecondaryKey() {

Просмотреть файл

@ -0,0 +1 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=example.springdata.cosmosdb.UserRepositoryConfiguration

Просмотреть файл

@ -15,20 +15,18 @@
*/
package example.springdata.cosmosdb;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
import reactor.core.publisher.Flux;
import java.util.Arrays;
import java.util.List;
@ -55,11 +53,6 @@ public class UserRepositoryIntegrationTest {
@Autowired
private ApplicationContext applicationContext;
@Before
public void setup() {
this.repository.deleteAll();
}
@After
public void cleanup() {
// Switch back to primary key to reset the invalid key
@ -67,7 +60,7 @@ public class UserRepositoryIntegrationTest {
final UserRepositoryConfiguration bean =
applicationContext.getBean(UserRepositoryConfiguration.class);
bean.switchToPrimaryKey();
this.repository.deleteAll();
this.repository.deleteAll().block();
}
@Test
@ -77,15 +70,15 @@ public class UserRepositoryIntegrationTest {
final Role contributor = new Role(ROLE_CONTRIBUTOR, COST_CONTRIBUTOR);
final User user = new User(ID, EMAIL, NAME, COUNT, address, Arrays.asList(creator, contributor));
this.repository.save(user);
this.repository.save(user).block();
// Test for findById
User result = this.repository.findById(ID).get();
User result = this.repository.findById(ID).block();
Assert.notNull(result, "should be exist in database");
Assert.isTrue(result.getId().equals(ID), "should be the same id");
// Test for findByName
List<User> resultList = this.repository.findByName(user.getName());
List<User> resultList = this.repository.findByName(user.getName()).collectList().block();
Assert.isTrue(resultList.size() == 1, "should be only one user here");
Assert.isTrue(resultList.get(0).getName().equals(user.getName()), "should be same Name");
Assert.notNull(result.getRoleList(), "roleList should not be null");
@ -100,7 +93,7 @@ public class UserRepositoryIntegrationTest {
}
// Test for findByEmailAndAddress
resultList = this.repository.findByEmailAndAddress(user.getEmail(), user.getAddress());
resultList = this.repository.findByEmailAndAddress(user.getEmail(), user.getAddress()).collectList().block();
Assert.isTrue(resultList.size() == 1, "should be only one user here");
result = resultList.get(0);
@ -110,22 +103,22 @@ public class UserRepositoryIntegrationTest {
Assert.isTrue(result.getAddress().getCity().equals(user.getAddress().getCity()), "should be same City");
Assert.isTrue(result.getAddress().getStreet().equals(user.getAddress().getStreet()), "should be same street");
resultList = this.repository.findByEmailOrName(user.getEmail(), user.getName());
resultList = this.repository.findByEmailOrName(user.getEmail(), user.getName()).collectList().block();
result = resultList.get(0);
Assert.isTrue(result.getId().equals(user.getId()), "should be the same Id");
resultList = this.repository.findByCount(COUNT, Sort.by(new Sort.Order(Sort.Direction.ASC, "count")));
resultList = this.repository.findByCount(COUNT,
Sort.by(new Sort.Order(Sort.Direction.ASC, "count"))).collectList().block();
result = resultList.get(0);
Assert.isTrue(result.getId().equals(user.getId()), "should be the same Id");
resultList = this.repository.findByNameIn(Arrays.asList(user.getName(), "fake-name"));
resultList = this.repository.findByNameIn(Arrays.asList(user.getName(), "fake-name")).collectList().block();
result = resultList.get(0);
Assert.isTrue(result.getId().equals(user.getId()), "should be the same Id");
// Test for findByAddress
final Pageable pageable = new DocumentDbPageRequest(0, 2, null);
Page<User> page = this.repository.findByAddress(address, pageable);
resultList = page.getContent();
final Flux<User> findByAddressFlux = this.repository.findByAddress(address);
resultList = findByAddressFlux.collectList().block();
result = resultList.get(0);
Assert.isTrue(result.getId().equals(user.getId()), "should be the same Id");
}
@ -143,32 +136,32 @@ public class UserRepositoryIntegrationTest {
final Role contributor = new Role(ROLE_CONTRIBUTOR, COST_CONTRIBUTOR);
final User user = new User(ID, EMAIL, NAME, COUNT, address, Arrays.asList(creator, contributor));
this.repository.save(user);
this.repository.save(user).block();
// Test for findById
final User result = this.repository.findById(ID).get();
final User result = this.repository.findById(ID).block();
Assert.notNull(result, "should be exist in database");
Assert.isTrue(result.getId().equals(ID), "should be the same id");
// Test for findByName
final List<User> resultList = this.repository.findByName(user.getName());
final List<User> resultList = this.repository.findByName(user.getName()).collectList().block();
Assert.isTrue(resultList.size() == 1, "should be only one user here");
Assert.isTrue(resultList.get(0).getName().equals(user.getName()), "should be same Name");
Assert.notNull(result.getRoleList(), "roleList should not be null");
Assert.isTrue(result.getRoleList().size() == user.getRoleList().size(), "must be the same list size");
}
@Test(expected = DocumentDBAccessException.class)
@Test(expected = CosmosDBAccessException.class)
public void testInvalidSecondaryKey() {
final Address address = new Address(POSTAL_CODE, STREET, CITY);
final Role creator = new Role(ROLE_CREATOR, COST_CREATOR);
final Role contributor = new Role(ROLE_CONTRIBUTOR, COST_CONTRIBUTOR);
final User user = new User(ID, EMAIL, NAME, COUNT, address, Arrays.asList(creator, contributor));
this.repository.save(user);
this.repository.save(user).block();
// Test for findById
final User result = this.repository.findById(ID).get();
final User result = this.repository.findById(ID).block();
Assert.notNull(result, "should be exist in database");
Assert.isTrue(result.getId().equals(ID), "should be the same id");
@ -178,7 +171,7 @@ public class UserRepositoryIntegrationTest {
bean.switchKey("Invalid key");
// Test for findByName
this.repository.findByName(user.getName());
this.repository.findById(user.getId()).block();
}
}

Просмотреть файл

@ -8,7 +8,7 @@
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-data-cosmosdb-samples</artifactId>
<version>2.1.8-SNAPSHOT</version>
<version>2.2.0.M1</version>
<packaging>pom</packaging>
<parent>

Просмотреть файл

@ -5,7 +5,7 @@
*/
package com.microsoft.azure.spring.data.cosmosdb;
import com.microsoft.azure.documentdb.IndexingMode;
import com.azure.data.cosmos.IndexingMode;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@ -15,15 +15,15 @@ public class Constants {
public static final String DEFAULT_COLLECTION_NAME = "";
public static final String DEFAULT_REQUEST_UNIT = "4000";
public static final boolean DEFAULT_INDEXINGPOLICY_AUTOMATIC = true;
public static final IndexingMode DEFAULT_INDEXINGPOLICY_MODE = IndexingMode.Consistent;
public static final IndexingMode DEFAULT_INDEXINGPOLICY_MODE = IndexingMode.CONSISTENT;
public static final String DEFAULT_REPOSITORY_IMPLEMENT_POSTFIX = "Impl";
public static final int DEFAULT_TIME_TO_LIVE = -1; // Indicates never expire
public static final String ID_PROPERTY_NAME = "id";
public static final String DOCUMENTDB_MODULE_NAME = "cosmosdb";
public static final String DOCUMENTDB_MODULE_PREFIX = "cosmosdb";
public static final String DOCUMENTDB_MAPPING_CONTEXT_NAME = "documentDbMappingContext";
public static final String COSMOSDB_MODULE_NAME = "cosmosdb";
public static final String COSMOSDB_MODULE_PREFIX = "cosmosdb";
public static final String COSMOS_MAPPING_CONTEXT = "cosmosMappingContext";
public static final String USER_AGENT_SUFFIX = "spring-data/";

Просмотреть файл

@ -6,12 +6,13 @@
package com.microsoft.azure.spring.data.cosmosdb;
import com.azure.data.cosmos.ConnectionPolicy;
import com.azure.data.cosmos.CosmosClient;
import com.microsoft.azure.documentdb.ConnectionPolicy;
import com.azure.data.cosmos.sync.CosmosSyncClient;
import com.microsoft.azure.spring.data.cosmosdb.common.MacAddress;
import com.microsoft.azure.spring.data.cosmosdb.common.PropertyLoader;
import com.microsoft.azure.spring.data.cosmosdb.common.TelemetrySender;
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
import lombok.Getter;
import lombok.NonNull;
import org.springframework.util.Assert;
@ -22,7 +23,7 @@ import javax.annotation.PostConstruct;
public class CosmosDbFactory {
@Getter
private final DocumentDBConfig config;
private final CosmosDBConfig config;
private static final boolean IS_TELEMETRY_ALLOWED = PropertyLoader.isApplicationTelemetryAllowed();
@ -38,7 +39,7 @@ public class CosmosDbFactory {
return suffix;
}
public CosmosDbFactory(@NonNull DocumentDBConfig config) {
public CosmosDbFactory(@NonNull CosmosDBConfig config) {
validateConfig(config);
this.config = config;
@ -46,17 +47,33 @@ public class CosmosDbFactory {
public CosmosClient getCosmosClient() {
final ConnectionPolicy policy = config.getConnectionPolicy();
final String userAgent = getUserAgentSuffix() + ";" + policy.getUserAgentSuffix();
final String userAgent = getUserAgentSuffix() + ";" + policy.userAgentSuffix();
policy.setUserAgentSuffix(userAgent);
policy.userAgentSuffix(userAgent);
return CosmosClient.builder()
.endpoint(config.getUri())
.key(config.getKey())
.cosmosKeyCredential(config.getCosmosKeyCredential())
.connectionPolicy(policy)
.consistencyLevel(config.getConsistencyLevel())
.build();
}
private void validateConfig(@NonNull DocumentDBConfig config) {
public CosmosSyncClient getCosmosSyncClient() {
final ConnectionPolicy policy = config.getConnectionPolicy();
final String userAgent = getUserAgentSuffix() + ";" + policy.userAgentSuffix();
policy.userAgentSuffix(userAgent);
return CosmosClient.builder()
.endpoint(config.getUri())
.key(config.getKey())
.cosmosKeyCredential(config.getCosmosKeyCredential())
.connectionPolicy(policy)
.consistencyLevel(config.getConsistencyLevel())
.buildSyncClient();
}
private void validateConfig(@NonNull CosmosDBConfig config) {
Assert.hasText(config.getUri(), "cosmosdb host url should have text!");
if (config.getCosmosKeyCredential() == null) {
Assert.hasText(config.getKey(), "cosmosdb host key should have text!");

Просмотреть файл

@ -1,83 +0,0 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb;
import com.microsoft.azure.documentdb.ConnectionPolicy;
import com.microsoft.azure.documentdb.DocumentClient;
import com.microsoft.azure.spring.data.cosmosdb.common.MacAddress;
import com.microsoft.azure.spring.data.cosmosdb.common.PropertyLoader;
import com.microsoft.azure.spring.data.cosmosdb.common.TelemetrySender;
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
import lombok.Getter;
import lombok.NonNull;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
public class DocumentDbFactory {
@Getter
private final DocumentDBConfig config;
private static final boolean IS_TELEMETRY_ALLOWED = PropertyLoader.isApplicationTelemetryAllowed();
private static final String USER_AGENT_SUFFIX = Constants.USER_AGENT_SUFFIX + PropertyLoader.getProjectVersion();
private String getUserAgentSuffix() {
String suffix = ";" + USER_AGENT_SUFFIX;
if (IS_TELEMETRY_ALLOWED) {
suffix += ";" + MacAddress.getHashMac();
}
return suffix;
}
public DocumentDbFactory(@NonNull DocumentDBConfig config) {
validateConfig(config);
this.config = config;
}
public DocumentClient getDocumentClient() {
final ConnectionPolicy policy = config.getConnectionPolicy();
final String userAgent = getUserAgentSuffix() + ";" + policy.getUserAgentSuffix();
policy.setUserAgentSuffix(userAgent);
// With introduction to com.azure.data.cosmos.CosmosKeyCredential,
// we are giving preference to config.getCosmosKeyCredential()
if (config.getCosmosKeyCredential() != null &&
!StringUtils.isEmpty(config.getCosmosKeyCredential().key())) {
return new DocumentClient(config.getUri(), config.getCosmosKeyCredential().key(),
policy, config.getConsistencyLevel());
}
return new DocumentClient(config.getUri(), config.getKey(), policy, config.getConsistencyLevel());
}
private void validateConfig(@NonNull DocumentDBConfig config) {
Assert.hasText(config.getUri(), "cosmosdb host url should have text!");
if (config.getCosmosKeyCredential() == null) {
Assert.hasText(config.getKey(), "cosmosdb host key should have text!");
} else if (StringUtils.isEmpty(config.getKey())) {
Assert.hasText(config.getCosmosKeyCredential().key(),
"cosmosdb credential host key should have text!");
}
Assert.hasText(config.getDatabase(), "cosmosdb database should have text!");
Assert.notNull(config.getConnectionPolicy(), "cosmosdb connection policy should not be null!");
}
@PostConstruct
private void sendTelemetry() {
if (IS_TELEMETRY_ALLOWED) {
final TelemetrySender sender = new TelemetrySender();
sender.send(this.getClass().getSimpleName());
}
}
}

Просмотреть файл

@ -6,24 +6,30 @@
package com.microsoft.azure.spring.data.cosmosdb.config;
import com.azure.data.cosmos.CosmosClient;
import com.azure.data.cosmos.sync.CosmosSyncClient;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.azure.documentdb.DocumentClient;
import com.microsoft.azure.spring.data.cosmosdb.Constants;
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
import com.microsoft.azure.spring.data.cosmosdb.DocumentDbFactory;
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate;
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate;
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public abstract class AbstractDocumentDbConfiguration extends DocumentDbConfigurationSupport {
public abstract class AbstractCosmosConfiguration extends CosmosConfigurationSupport {
@Bean
public DocumentClient documentClient(DocumentDBConfig config) {
return this.documentDbFactory(config).getDocumentClient();
public CosmosClient cosmosClient(CosmosDBConfig config) {
return this.cosmosDbFactory(config).getCosmosClient();
}
@Bean
public CosmosSyncClient cosmosSyncClient(CosmosDBConfig config) {
return this.cosmosDbFactory(config).getCosmosSyncClient();
}
@Qualifier(Constants.OBJECTMAPPER_BEAN_NAME)
@ -31,29 +37,24 @@ public abstract class AbstractDocumentDbConfiguration extends DocumentDbConfigur
private ObjectMapper objectMapper;
@Bean
public DocumentDbFactory documentDbFactory(DocumentDBConfig config) {
return new DocumentDbFactory(config);
}
@Bean
public CosmosDbFactory cosmosDbFactory(DocumentDBConfig config) {
public CosmosDbFactory cosmosDbFactory(CosmosDBConfig config) {
return new CosmosDbFactory(config);
}
@Bean
public DocumentDbTemplate documentDbTemplate(DocumentDBConfig config) throws ClassNotFoundException {
return new DocumentDbTemplate(this.cosmosDbFactory(config), this.mappingDocumentDbConverter(),
public CosmosTemplate cosmosTemplate(CosmosDBConfig config) throws ClassNotFoundException {
return new CosmosTemplate(this.cosmosDbFactory(config), this.mappingCosmosConverter(),
config.getDatabase());
}
@Bean
public ReactiveCosmosTemplate cosmosDbTemplate(DocumentDBConfig config) throws ClassNotFoundException {
return new ReactiveCosmosTemplate(this.cosmosDbFactory(config), this.mappingDocumentDbConverter(),
public ReactiveCosmosTemplate reactiveCosmosTemplate(CosmosDBConfig config) throws ClassNotFoundException {
return new ReactiveCosmosTemplate(this.cosmosDbFactory(config), this.mappingCosmosConverter(),
config.getDatabase());
}
@Bean
public MappingDocumentDbConverter mappingDocumentDbConverter() throws ClassNotFoundException {
return new MappingDocumentDbConverter(this.documentDbMappingContext(), objectMapper);
public MappingCosmosConverter mappingCosmosConverter() throws ClassNotFoundException {
return new MappingCosmosConverter(this.cosmosMappingContext(), objectMapper);
}
}

Просмотреть файл

@ -7,30 +7,23 @@
package com.microsoft.azure.spring.data.cosmosdb.config;
import com.microsoft.azure.spring.data.cosmosdb.common.ExpressionResolver;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.data.support.CachingIsNewStrategyFactory;
import org.springframework.data.support.IsNewStrategyFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public abstract class DocumentDbConfigurationSupport {
public abstract class CosmosConfigurationSupport {
@Bean
public ExpressionResolver expressionResolver(BeanFactory beanFactory) {
@ -38,8 +31,8 @@ public abstract class DocumentDbConfigurationSupport {
}
@Bean
public DocumentDbMappingContext documentDbMappingContext() throws ClassNotFoundException {
final DocumentDbMappingContext mappingContext = new DocumentDbMappingContext();
public CosmosMappingContext cosmosMappingContext() throws ClassNotFoundException {
final CosmosMappingContext mappingContext = new CosmosMappingContext();
mappingContext.setInitialEntitySet(getInitialEntitySet());
return mappingContext;
@ -50,13 +43,6 @@ public abstract class DocumentDbConfigurationSupport {
return Collections.singleton(mappingBasePackage == null ? null : mappingBasePackage.getName());
}
@Bean
public IsNewStrategyFactory isNewStrategyFactory() throws ClassNotFoundException {
return new CachingIsNewStrategyFactory(new MappingContextIsNewStrategyFactory(
new PersistentEntities(Arrays.<MappingContext<?, ?>>asList(
new MappingContext[]{documentDbMappingContext()}))));
}
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
final Set<Class<?>> initialEntitySet = new HashSet<>();
@ -85,7 +71,7 @@ public abstract class DocumentDbConfigurationSupport {
Assert.notNull(className, "Bean class name is null.");
initialEntitySet
.add(ClassUtils.forName(className, DocumentDbConfigurationSupport.class.getClassLoader()));
.add(ClassUtils.forName(className, CosmosConfigurationSupport.class.getClassLoader()));
}
}

Просмотреть файл

@ -5,18 +5,18 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.config;
import com.azure.data.cosmos.ConnectionPolicy;
import com.azure.data.cosmos.ConsistencyLevel;
import com.azure.data.cosmos.CosmosKeyCredential;
import com.microsoft.azure.documentdb.ConnectionPolicy;
import com.microsoft.azure.documentdb.ConsistencyLevel;
import com.microsoft.azure.documentdb.RequestOptions;
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
import com.azure.data.cosmos.internal.RequestOptions;
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
import lombok.Builder;
import lombok.Getter;
import org.springframework.util.Assert;
@Getter
@Builder(builderMethodName = "defaultBuilder")
public class DocumentDBConfig {
public class CosmosDBConfig {
private String uri;
private String key;
@ -33,35 +33,35 @@ public class DocumentDBConfig {
private CosmosKeyCredential cosmosKeyCredential;
public static DocumentDBConfigBuilder builder(String uri, CosmosKeyCredential cosmosKeyCredential,
public static CosmosDBConfigBuilder builder(String uri, CosmosKeyCredential cosmosKeyCredential,
String database) {
return defaultBuilder()
.uri(uri)
.cosmosKeyCredential(cosmosKeyCredential)
.database(database)
.connectionPolicy(ConnectionPolicy.GetDefault())
.consistencyLevel(ConsistencyLevel.Session)
.connectionPolicy(ConnectionPolicy.defaultPolicy())
.consistencyLevel(ConsistencyLevel.SESSION)
.requestOptions(new RequestOptions());
}
public static DocumentDBConfigBuilder builder(String uri, String key, String database) {
public static CosmosDBConfigBuilder builder(String uri, String key, String database) {
return defaultBuilder()
.uri(uri)
.key(key)
.database(database)
.connectionPolicy(ConnectionPolicy.GetDefault())
.consistencyLevel(ConsistencyLevel.Session)
.connectionPolicy(ConnectionPolicy.defaultPolicy())
.consistencyLevel(ConsistencyLevel.SESSION)
.requestOptions(new RequestOptions());
}
public static DocumentDBConfigBuilder builder(String connectionString, String database) {
public static CosmosDBConfigBuilder builder(String connectionString, String database) {
Assert.hasText(connectionString, "connection string should have text!");
try {
final String uri = connectionString.split(";")[0].split("=")[1];
final String key = connectionString.split(";")[1].split("=")[1];
return builder(uri, key, database);
} catch (ArrayIndexOutOfBoundsException e) {
throw new DocumentDBAccessException("could not parse connection string");
throw new CosmosDBAccessException("could not parse connection string");
}
}
}

Просмотреть файл

@ -6,22 +6,21 @@
package com.microsoft.azure.spring.data.cosmosdb.core;
import com.microsoft.azure.documentdb.DocumentCollection;
import com.microsoft.azure.documentdb.PartitionKey;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
import com.azure.data.cosmos.CosmosContainerProperties;
import com.azure.data.cosmos.PartitionKey;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.util.List;
public interface DocumentDbOperations {
public interface CosmosOperations {
String getCollectionName(Class<?> entityClass);
DocumentCollection createCollectionIfNotExists(DocumentDbEntityInformation<?, ?> information);
CosmosContainerProperties createCollectionIfNotExists(CosmosEntityInformation<?, ?> information);
<T> List<T> findAll(Class<T> entityClass);
@ -63,5 +62,5 @@ public interface DocumentDbOperations {
<T> long count(DocumentQuery query, Class<T> domainClass, String collectionName);
MappingDocumentDbConverter getConverter();
MappingCosmosConverter getConverter();
}

Просмотреть файл

@ -9,26 +9,26 @@ package com.microsoft.azure.spring.data.cosmosdb.core;
import com.azure.data.cosmos.AccessCondition;
import com.azure.data.cosmos.AccessConditionType;
import com.azure.data.cosmos.CosmosClient;
import com.azure.data.cosmos.CosmosContainerProperties;
import com.azure.data.cosmos.CosmosContainerResponse;
import com.azure.data.cosmos.CosmosItemProperties;
import com.azure.data.cosmos.CosmosItemRequestOptions;
import com.azure.data.cosmos.CosmosItemResponse;
import com.azure.data.cosmos.FeedOptions;
import com.azure.data.cosmos.FeedResponse;
import com.azure.data.cosmos.PartitionKey;
import com.azure.data.cosmos.SqlQuerySpec;
import com.microsoft.azure.documentdb.DocumentCollection;
import com.microsoft.azure.documentdb.PartitionKey;
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
import com.microsoft.azure.spring.data.cosmosdb.common.Memoizer;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.generator.CountQueryGenerator;
import com.microsoft.azure.spring.data.cosmosdb.core.generator.FindQuerySpecGenerator;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest;
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@ -50,30 +50,25 @@ import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
*
* @author Domenico Sibilio
*
*/
@Slf4j
public class DocumentDbTemplate implements DocumentDbOperations, ApplicationContextAware {
public class CosmosTemplate implements CosmosOperations, ApplicationContextAware {
private static final String COUNT_VALUE_KEY = "_aggregate";
private final MappingDocumentDbConverter mappingDocumentDbConverter;
private final MappingCosmosConverter mappingCosmosConverter;
private final String databaseName;
private final CosmosClient cosmosClient;
private Function<Class<?>, DocumentDbEntityInformation<?, ?>> entityInfoCreator =
Memoizer.memoize(this::getDocumentDbEntityInformation);
private Function<Class<?>, CosmosEntityInformation<?, ?>> entityInfoCreator =
Memoizer.memoize(this::getCosmosEntityInformation);
public DocumentDbTemplate(CosmosDbFactory cosmosDbFactory,
MappingDocumentDbConverter mappingDocumentDbConverter,
public CosmosTemplate(CosmosDbFactory cosmosDbFactory,
MappingCosmosConverter mappingCosmosConverter,
String dbName) {
Assert.notNull(cosmosDbFactory, "CosmosDbFactory must not be null!");
Assert.notNull(mappingDocumentDbConverter, "MappingDocumentDbConverter must not be null!");
Assert.notNull(mappingCosmosConverter, "MappingCosmosConverter must not be null!");
this.mappingDocumentDbConverter = mappingDocumentDbConverter;
this.mappingCosmosConverter = mappingCosmosConverter;
this.databaseName = dbName;
this.cosmosClient = cosmosDbFactory.getCosmosClient();
@ -92,13 +87,13 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
Assert.hasText(collectionName, "collectionName should not be null, empty or only whitespaces");
Assert.notNull(objectToSave, "objectToSave should not be null");
final CosmosItemProperties originalItem = mappingDocumentDbConverter.writeCosmosItemProperties(objectToSave);
final CosmosItemProperties originalItem = mappingCosmosConverter.writeCosmosItemProperties(objectToSave);
log.debug("execute createDocument in database {} collection {}", this.databaseName, collectionName);
try {
final CosmosItemRequestOptions options = new CosmosItemRequestOptions();
options.partitionKey(toCosmosPartitionKey(partitionKey));
options.partitionKey(partitionKey);
@SuppressWarnings("unchecked")
final Class<T> domainClass = (Class<T>) objectToSave.getClass();
@ -110,13 +105,13 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
.block();
if (response == null) {
throw new DocumentDBAccessException("Failed to insert item");
throw new CosmosDBAccessException("Failed to insert item");
}
return mappingDocumentDbConverter.read(domainClass, response.properties());
return mappingCosmosConverter.read(domainClass, response.properties());
} catch (Exception e) {
throw new DocumentDBAccessException("insert exception", e);
throw new CosmosDBAccessException("insert exception", e);
}
}
@ -126,6 +121,29 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
return findById(getCollectionName(entityClass), id, entityClass);
}
@Override
public <T> T findById(Object id, Class<T> entityClass, PartitionKey partitionKey) {
Assert.notNull(entityClass, "entityClass should not be null");
Assert.notNull(partitionKey, "partitionKey should not be null");
assertValidId(id);
try {
final String collectionName = getCollectionName(entityClass);
return cosmosClient
.getDatabase(databaseName)
.getContainer(collectionName)
.getItem(id.toString(), partitionKey)
.read()
.flatMap(cosmosItemResponse -> Mono.justOrEmpty(toDomainObject(entityClass,
cosmosItemResponse.properties())))
.onErrorResume(Mono::error)
.block();
} catch (Exception e) {
throw new CosmosDBAccessException("findById exception", e);
}
}
public <T> T findById(String collectionName, Object id, Class<T> domainClass) {
Assert.hasText(collectionName, "collectionName should not be null, empty or only whitespaces");
Assert.notNull(domainClass, "entityClass should not be null");
@ -143,42 +161,16 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
.flatMap(cosmosItemFeedResponse -> Mono.justOrEmpty(cosmosItemFeedResponse
.results()
.stream()
.map(cosmosItem -> mappingDocumentDbConverter.read(domainClass, cosmosItem))
.map(cosmosItem -> mappingCosmosConverter.read(domainClass, cosmosItem))
.findFirst()))
.onErrorResume(Mono::error)
.blockFirst();
} catch (Exception e) {
throw new DocumentDBAccessException("findById exception", e);
throw new CosmosDBAccessException("findById exception", e);
}
}
@Override
public <T> T findById(Object id, Class<T> entityClass, PartitionKey partitionKey) {
Assert.notNull(entityClass, "entityClass should not be null");
Assert.notNull(partitionKey, "partitionKey should not be null");
assertValidId(id);
final com.azure.data.cosmos.PartitionKey pk = toCosmosPartitionKey(partitionKey);
try {
final String collectionName = getCollectionName(entityClass);
return cosmosClient
.getDatabase(databaseName)
.getContainer(collectionName)
.getItem(id.toString(), pk)
.read()
.flatMap(cosmosItemResponse -> Mono.justOrEmpty(toDomainObject(entityClass,
cosmosItemResponse.properties())))
.onErrorResume(Mono::error)
.block();
} catch (Exception e) {
throw new DocumentDBAccessException("findById exception", e);
}
}
public <T> void upsert(T object, PartitionKey partitionKey) {
Assert.notNull(object, "Upsert object should not be null");
@ -190,12 +182,12 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
Assert.notNull(object, "Upsert object should not be null");
try {
final CosmosItemProperties originalItem = mappingDocumentDbConverter.writeCosmosItemProperties(object);
final CosmosItemProperties originalItem = mappingCosmosConverter.writeCosmosItemProperties(object);
log.debug("execute upsert document in database {} collection {}", this.databaseName, collectionName);
final CosmosItemRequestOptions options = new CosmosItemRequestOptions();
options.partitionKey(toCosmosPartitionKey(partitionKey));
options.partitionKey(partitionKey);
applyVersioning(object.getClass(), originalItem, options);
final CosmosItemResponse cosmosItemResponse = cosmosClient.getDatabase(this.databaseName)
@ -205,10 +197,10 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
.block();
if (cosmosItemResponse == null) {
throw new DocumentDBAccessException("Failed to upsert item");
throw new CosmosDBAccessException("Failed to upsert item");
}
} catch (Exception ex) {
throw new DocumentDBAccessException("Failed to upsert document to database.", ex);
throw new CosmosDBAccessException("Failed to upsert document to database.", ex);
}
}
@ -244,7 +236,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
try {
cosmosClient.getDatabase(this.databaseName).getContainer(collectionName).delete().block();
} catch (Exception e) {
throw new DocumentDBAccessException("failed to delete collection: " + collectionName,
throw new CosmosDBAccessException("failed to delete collection: " + collectionName,
e);
}
}
@ -256,7 +248,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
}
@Override
public DocumentCollection createCollectionIfNotExists(@NonNull DocumentDbEntityInformation<?, ?> information) {
public CosmosContainerProperties createCollectionIfNotExists(@NonNull CosmosEntityInformation<?, ?> information) {
final CosmosContainerResponse response = cosmosClient
.createDatabaseIfNotExists(this.databaseName)
.flatMap(cosmosDatabaseResponse -> cosmosDatabaseResponse
@ -266,9 +258,9 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
.map(cosmosContainerResponse -> cosmosContainerResponse))
.block();
if (response == null) {
throw new DocumentDBAccessException("Failed to create collection");
throw new CosmosDBAccessException("Failed to create collection");
}
return new DocumentCollection(response.properties().toJson());
return response.properties();
}
public void deleteById(String collectionName, Object id, PartitionKey partitionKey) {
@ -277,13 +269,12 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
log.debug("execute deleteById in database {} collection {}", this.databaseName, collectionName);
com.azure.data.cosmos.PartitionKey pk = toCosmosPartitionKey(partitionKey);
if (pk == null) {
pk = com.azure.data.cosmos.PartitionKey.None;
if (partitionKey == null) {
partitionKey = PartitionKey.None;
}
try {
final CosmosItemRequestOptions options = new CosmosItemRequestOptions();
options.partitionKey(pk);
options.partitionKey(partitionKey);
cosmosClient.getDatabase(this.databaseName)
.getContainer(collectionName)
.getItem(id.toString(), partitionKey)
@ -292,7 +283,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
.then()
.block();
} catch (Exception e) {
throw new DocumentDBAccessException("deleteById exception", e);
throw new CosmosDBAccessException("deleteById exception", e);
}
}
@ -318,7 +309,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
.map(cosmosItemProperties -> toDomainObject(domainClass, cosmosItemProperties))
.collect(Collectors.toList());
} catch (Exception e) {
throw new DocumentDBAccessException("Failed to execute find operation from " + collectionName, e);
throw new CosmosDBAccessException("Failed to execute find operation from " + collectionName, e);
}
}
@ -371,8 +362,8 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
final Pageable pageable = query.getPageable();
final FeedOptions feedOptions = new FeedOptions();
if (pageable instanceof DocumentDbPageRequest) {
feedOptions.requestContinuation(((DocumentDbPageRequest) pageable).getRequestContinuation());
if (pageable instanceof CosmosPageRequest) {
feedOptions.requestContinuation(((CosmosPageRequest) pageable).getRequestContinuation());
}
feedOptions.maxItemCount(pageable.getPageSize());
@ -387,7 +378,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
.block();
if (feedResponse == null) {
throw new DocumentDBAccessException("Failed to query documents");
throw new CosmosDBAccessException("Failed to query documents");
}
final Iterator<CosmosItemProperties> it = feedResponse.results().iterator();
@ -400,11 +391,11 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
continue;
}
final T entity = mappingDocumentDbConverter.read(domainClass, cosmosItemProperties);
final T entity = mappingCosmosConverter.read(domainClass, cosmosItemProperties);
result.add(entity);
}
final DocumentDbPageRequest pageRequest = DocumentDbPageRequest.of(pageable.getPageNumber(),
final CosmosPageRequest pageRequest = CosmosPageRequest.of(pageable.getPageNumber(),
pageable.getPageSize(),
feedResponse.continuationToken(),
query.getSort());
@ -419,7 +410,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
final DocumentQuery query = new DocumentQuery(Criteria.getInstance(CriteriaType.ALL));
final Long count = getCountValue(query, true, collectionName);
if (count == null) {
throw new DocumentDBAccessException("Failed to get count for collectionName: " + collectionName);
throw new CosmosDBAccessException("Failed to get count for collectionName: " + collectionName);
}
return count;
}
@ -433,14 +424,14 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
query.isCrossPartitionQuery(getPartitionKeyNames(domainClass));
final Long count = getCountValue(query, isCrossPartitionQuery, collectionName);
if (count == null) {
throw new DocumentDBAccessException("Failed to get count for collectionName: " + collectionName);
throw new CosmosDBAccessException("Failed to get count for collectionName: " + collectionName);
}
return count;
}
@Override
public MappingDocumentDbConverter getConverter() {
return this.mappingDocumentDbConverter;
public MappingCosmosConverter getConverter() {
return this.mappingCosmosConverter;
}
private Long getCountValue(DocumentQuery query, boolean isCrossPartitionQuery, String containerName) {
@ -457,7 +448,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
}
private <T> Mono<T> databaseAccessExceptionHandler(Throwable e) {
throw new DocumentDBAccessException("failed to access cosmosdb database", e);
throw new CosmosDBAccessException("failed to access cosmosdb database", e);
}
private Flux<FeedResponse<CosmosItemProperties>> executeQuery(SqlQuerySpec sqlQuerySpec, String collectionName,
@ -468,7 +459,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
}
private List<String> getPartitionKeyNames(Class<?> domainClass) {
final DocumentDbEntityInformation<?, ?> entityInfo = entityInfoCreator.apply(domainClass);
final CosmosEntityInformation<?, ?> entityInfo = entityInfoCreator.apply(domainClass);
if (entityInfo.getPartitionKeyFieldName() == null) {
return new ArrayList<>();
@ -477,13 +468,6 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
return Collections.singletonList(entityInfo.getPartitionKeyFieldName());
}
private com.azure.data.cosmos.PartitionKey toCosmosPartitionKey(PartitionKey partitionKey) {
if (partitionKey == null) {
return null;
}
return com.azure.data.cosmos.PartitionKey.fromJsonString(partitionKey.getInternalPartitionKey().toJson());
}
private void assertValidId(Object id) {
Assert.notNull(id, "id should not be null");
if (id instanceof String) {
@ -520,13 +504,11 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
partitionKey = new PartitionKey(cosmosItemProperties.get(partitionKeyNames.get(0)));
}
com.azure.data.cosmos.PartitionKey pk = toCosmosPartitionKey(partitionKey);
if (pk == null) {
pk = com.azure.data.cosmos.PartitionKey.None;
if (partitionKey == null) {
partitionKey = PartitionKey.None;
}
final CosmosItemRequestOptions options = new CosmosItemRequestOptions(pk);
final CosmosItemRequestOptions options = new CosmosItemRequestOptions(partitionKey);
applyVersioning(domainClass, cosmosItemProperties, options);
return cosmosClient
@ -538,7 +520,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
}
private <T> T toDomainObject(@NonNull Class<T> domainClass, CosmosItemProperties cosmosItemProperties) {
return mappingDocumentDbConverter.read(domainClass, cosmosItemProperties);
return mappingCosmosConverter.read(domainClass, cosmosItemProperties);
}
private void applyVersioning(Class<?> domainClass,
@ -553,8 +535,8 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
}
}
private DocumentDbEntityInformation<?, ?> getDocumentDbEntityInformation(Class<?> domainClass) {
return new DocumentDbEntityInformation<>(domainClass);
private CosmosEntityInformation<?, ?> getCosmosEntityInformation(Class<?> domainClass) {
return new CosmosEntityInformation<>(domainClass);
}
}

Просмотреть файл

@ -8,15 +8,17 @@ package com.microsoft.azure.spring.data.cosmosdb.core;
import com.azure.data.cosmos.CosmosContainerResponse;
import com.azure.data.cosmos.PartitionKey;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface ReactiveCosmosOperations {
Mono<CosmosContainerResponse> createCollectionIfNotExists(DocumentDbEntityInformation information);
String getContainerName(Class<?> domainClass);
Mono<CosmosContainerResponse> createCollectionIfNotExists(CosmosEntityInformation information);
<T> Flux<T> findAll(String collectionName, Class<T> entityClass);
@ -42,7 +44,7 @@ public interface ReactiveCosmosOperations {
void deleteContainer(String collectionName);
<T> Mono<T> delete(DocumentQuery query, Class<T> entityClass, String collectionName);
<T> Flux<T> delete(DocumentQuery query, Class<T> entityClass, String collectionName);
<T> Flux<T> find(DocumentQuery query, Class<T> entityClass, String collectionName);
@ -54,5 +56,5 @@ public interface ReactiveCosmosOperations {
Mono<Long> count(DocumentQuery query, String containerName);
MappingDocumentDbConverter getConverter();
MappingCosmosConverter getConverter();
}

Просмотреть файл

@ -15,14 +15,14 @@ import com.azure.data.cosmos.FeedResponse;
import com.azure.data.cosmos.PartitionKey;
import com.azure.data.cosmos.SqlQuerySpec;
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.generator.CountQueryGenerator;
import com.microsoft.azure.spring.data.cosmosdb.core.generator.FindQuerySpecGenerator;
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
@ -41,10 +41,9 @@ import java.util.List;
public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, ApplicationContextAware {
private static final String COUNT_VALUE_KEY = "_aggregate";
private final MappingCosmosConverter mappingCosmosConverter;
private final String databaseName;
private final MappingDocumentDbConverter mappingDocumentDbConverter;
private final CosmosClient cosmosClient;
private final List<String> collectionCache;
@ -53,18 +52,18 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
* Constructor
*
* @param cosmosDbFactory the cosmosdbfactory
* @param mappingDocumentDbConverter the mappingDocumentDbConverter
* @param mappingCosmosConverter the mappingCosmosConverter
* @param dbName database name
*/
public ReactiveCosmosTemplate(CosmosDbFactory cosmosDbFactory,
MappingDocumentDbConverter mappingDocumentDbConverter,
MappingCosmosConverter mappingCosmosConverter,
String dbName) {
Assert.notNull(cosmosDbFactory, "CosmosDbFactory must not be null!");
Assert.notNull(mappingDocumentDbConverter, "MappingDocumentDbConverter must not be null!");
Assert.notNull(mappingCosmosConverter, "MappingCosmosConverter must not be null!");
this.mappingCosmosConverter = mappingCosmosConverter;
this.databaseName = dbName;
this.collectionCache = new ArrayList<>();
this.mappingDocumentDbConverter = mappingDocumentDbConverter;
this.cosmosClient = cosmosDbFactory.getCosmosClient();
}
@ -77,19 +76,14 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
// NOTE: When application context instance variable gets introduced, assign it here.
}
@Override
public MappingDocumentDbConverter getConverter() {
return this.mappingDocumentDbConverter;
}
/**
* Creates a collection if it doesn't already exist
*
* @param information the DocumentDbEntityInformation
* @param information the CosmosEntityInformation
* @return Mono containing CosmosContainerResponse
*/
@Override
public Mono<CosmosContainerResponse> createCollectionIfNotExists(DocumentDbEntityInformation information) {
public Mono<CosmosContainerResponse> createCollectionIfNotExists(CosmosEntityInformation information) {
return cosmosClient
.createDatabaseIfNotExists(this.databaseName)
@ -167,7 +161,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
.stream()
.map(cosmosItem -> toDomainObject(entityClass, cosmosItem))
.findFirst()))
.onErrorResume(Mono::error)
.onErrorResume(this::databaseAccessExceptionHandler)
.next();
}
@ -191,10 +185,9 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
.read()
.flatMap(cosmosItemResponse -> Mono.justOrEmpty(toDomainObject(entityClass,
cosmosItemResponse.properties())))
.onErrorResume(Mono::error);
.onErrorResume(this::databaseAccessExceptionHandler);
}
/**
* Insert
*
@ -221,7 +214,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
return cosmosClient.getDatabase(this.databaseName)
.getContainer(getContainerName(objectToSave.getClass()))
.createItem(objectToSave, new CosmosItemRequestOptions())
.onErrorResume(Mono::error)
.onErrorResume(this::databaseAccessExceptionHandler)
.flatMap(cosmosItemResponse -> Mono.just(toDomainObject(domainClass, cosmosItemResponse.properties())));
}
@ -246,7 +239,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
return cosmosClient.getDatabase(this.databaseName)
.getContainer(containerName)
.createItem(objectToSave, options)
.onErrorResume(Mono::error)
.onErrorResume(this::databaseAccessExceptionHandler)
.flatMap(cosmosItemResponse -> Mono.just(toDomainObject(domainClass, cosmosItemResponse.properties())));
}
@ -282,7 +275,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
.getContainer(containerName)
.upsertItem(object, options)
.flatMap(cosmosItemResponse -> Mono.just(toDomainObject(domainClass, cosmosItemResponse.properties())))
.onErrorResume(Mono::error);
.onErrorResume(this::databaseAccessExceptionHandler);
}
/**
@ -305,7 +298,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
.getContainer(containerName)
.getItem(id.toString(), partitionKey)
.delete(options)
.onErrorResume(Mono::error)
.onErrorResume(this::databaseAccessExceptionHandler)
.then();
}
@ -349,7 +342,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
* @return Mono
*/
@Override
public <T> Mono<T> delete(DocumentQuery query, Class<T> entityClass, String containerName) {
public <T> Flux<T> delete(DocumentQuery query, Class<T> entityClass, String containerName) {
Assert.notNull(query, "DocumentQuery should not be null.");
Assert.notNull(entityClass, "domainClass should not be null.");
Assert.hasText(containerName, "container name should not be null, empty or only whitespaces");
@ -357,9 +350,8 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
final Flux<CosmosItemProperties> results = findDocuments(query, entityClass, containerName);
final List<String> partitionKeyName = getPartitionKeyNames(entityClass);
results.flatMap(d -> deleteDocument(d, partitionKeyName, containerName));
return null;
return results.flatMap(d -> deleteDocument(d, partitionKeyName, containerName))
.flatMap(cosmosItemProperties -> Mono.just(toDomainObject(entityClass, cosmosItemProperties)));
}
/**
@ -425,6 +417,11 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
return count(query, true, containerName);
}
@Override
public MappingCosmosConverter getConverter() {
return mappingCosmosConverter;
}
public Mono<Long> count(DocumentQuery query, boolean isCrossPartitionQuery, String containerName) {
return getCountValue(query, isCrossPartitionQuery, containerName);
}
@ -450,7 +447,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
}
private <T> Mono<T> databaseAccessExceptionHandler(Throwable e) {
throw new DocumentDBAccessException("failed to access cosmosdb database", e);
throw new CosmosDBAccessException("failed to access cosmosdb database", e);
}
/**
@ -465,7 +462,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
cosmosClient.getDatabase(this.databaseName).getContainer(containerName).delete().block();
this.collectionCache.remove(containerName);
} catch (Exception e) {
throw new DocumentDBAccessException("failed to delete collection: " + containerName, e);
throw new CosmosDBAccessException("failed to delete collection: " + containerName, e);
}
}
@ -476,7 +473,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
public String getContainerName(Class<?> domainClass) {
Assert.notNull(domainClass, "domainClass should not be null");
return new DocumentDbEntityInformation<>(domainClass).getCollectionName();
return new CosmosEntityInformation<>(domainClass).getCollectionName();
}
private Flux<CosmosItemProperties> findDocuments(@NonNull DocumentQuery query, @NonNull Class<?> domainClass,
@ -500,7 +497,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
}
private List<String> getPartitionKeyNames(Class<?> domainClass) {
final DocumentDbEntityInformation entityInfo = new DocumentDbEntityInformation(domainClass);
final CosmosEntityInformation<?, ?> entityInfo = new CosmosEntityInformation<>(domainClass);
if (entityInfo.getPartitionKeyFieldName() == null) {
return new ArrayList<>();
@ -531,8 +528,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
}
private <T> T toDomainObject(@NonNull Class<T> domainClass, CosmosItemProperties cosmosItemProperties) {
return this.mappingDocumentDbConverter.read(domainClass, cosmosItemProperties);
return mappingCosmosConverter.read(domainClass, cosmosItemProperties);
}
}

Просмотреть файл

@ -7,14 +7,11 @@ package com.microsoft.azure.spring.data.cosmosdb.core.convert;
import com.azure.data.cosmos.CosmosItemProperties;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.microsoft.azure.documentdb.Document;
import com.microsoft.azure.spring.data.cosmosdb.Constants;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbPersistentEntity;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbPersistentProperty;
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentEntity;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty;
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
@ -35,19 +32,19 @@ import java.util.Date;
import static com.microsoft.azure.spring.data.cosmosdb.Constants.ISO_8601_COMPATIBLE_DATE_PATTERN;
public class MappingDocumentDbConverter
implements EntityConverter<DocumentDbPersistentEntity<?>, DocumentDbPersistentProperty,
public class MappingCosmosConverter
implements EntityConverter<CosmosPersistentEntity<?>, CosmosPersistentProperty,
Object, CosmosItemProperties>,
ApplicationContextAware {
protected final MappingContext<? extends DocumentDbPersistentEntity<?>,
DocumentDbPersistentProperty> mappingContext;
protected final MappingContext<? extends CosmosPersistentEntity<?>,
CosmosPersistentProperty> mappingContext;
protected GenericConversionService conversionService;
private ApplicationContext applicationContext;
private ObjectMapper objectMapper;
public MappingDocumentDbConverter(
MappingContext<? extends DocumentDbPersistentEntity<?>, DocumentDbPersistentProperty> mappingContext,
public MappingCosmosConverter(
MappingContext<? extends CosmosPersistentEntity<?>, CosmosPersistentProperty> mappingContext,
@Qualifier(Constants.OBJECTMAPPER_BEAN_NAME) ObjectMapper objectMapper) {
this.mappingContext = mappingContext;
this.conversionService = new GenericConversionService();
@ -61,18 +58,17 @@ public class MappingDocumentDbConverter
return null;
}
final DocumentDbPersistentEntity<?> entity = mappingContext.getPersistentEntity(type);
final CosmosPersistentEntity<?> entity = mappingContext.getPersistentEntity(type);
Assert.notNull(entity, "Entity is null.");
return readInternal(entity, type, cosmosItemProperties);
}
private <R> R readInternal(final DocumentDbPersistentEntity<?> entity, Class<R> type,
private <R> R readInternal(final CosmosPersistentEntity<?> entity, Class<R> type,
final CosmosItemProperties cosmosItemProperties) {
try {
final DocumentDbPersistentProperty idProperty = entity.getIdProperty();
final CosmosPersistentProperty idProperty = entity.getIdProperty();
final Object idValue = cosmosItemProperties.id();
final JSONObject jsonObject = new JSONObject(cosmosItemProperties.toJson());
@ -95,12 +91,12 @@ public class MappingDocumentDbConverter
throw new UnsupportedOperationException("The feature is not implemented yet");
}
public Document writeDoc(Object sourceEntity) {
public CosmosItemProperties writeDoc(Object sourceEntity) {
if (sourceEntity == null) {
return null;
}
final DocumentDbPersistentEntity<?> persistentEntity =
final CosmosPersistentEntity<?> persistentEntity =
mappingContext.getPersistentEntity(sourceEntity.getClass());
if (persistentEntity == null) {
@ -108,19 +104,19 @@ public class MappingDocumentDbConverter
}
final ConvertingPropertyAccessor accessor = getPropertyAccessor(sourceEntity);
final DocumentDbPersistentProperty idProperty = persistentEntity.getIdProperty();
final Document document;
final CosmosPersistentProperty idProperty = persistentEntity.getIdProperty();
final CosmosItemProperties document;
try {
document = new Document(objectMapper.writeValueAsString(sourceEntity));
document = new CosmosItemProperties(objectMapper.writeValueAsString(sourceEntity));
} catch (JsonProcessingException e) {
throw new DocumentDBAccessException("Failed to map document value.", e);
throw new CosmosDBAccessException("Failed to map document value.", e);
}
if (idProperty != null) {
final Object value = accessor.getProperty(idProperty);
final String id = value == null ? null : value.toString();
document.setId(id);
document.id(id);
}
return document;
@ -131,7 +127,7 @@ public class MappingDocumentDbConverter
return null;
}
final DocumentDbPersistentEntity<?> persistentEntity =
final CosmosPersistentEntity<?> persistentEntity =
mappingContext.getPersistentEntity(sourceEntity.getClass());
if (persistentEntity == null) {
@ -139,14 +135,14 @@ public class MappingDocumentDbConverter
}
final ConvertingPropertyAccessor accessor = getPropertyAccessor(sourceEntity);
final DocumentDbPersistentProperty idProperty = persistentEntity.getIdProperty();
final CosmosPersistentProperty idProperty = persistentEntity.getIdProperty();
final CosmosItemProperties cosmosItemProperties;
try {
cosmosItemProperties =
new CosmosItemProperties(objectMapper.writeValueAsString(sourceEntity));
} catch (JsonProcessingException e) {
throw new DocumentDBAccessException("Failed to map document value.", e);
throw new CosmosDBAccessException("Failed to map document value.", e);
}
if (idProperty != null) {
@ -172,13 +168,13 @@ public class MappingDocumentDbConverter
return conversionService;
}
public MappingContext<? extends DocumentDbPersistentEntity<?>, DocumentDbPersistentProperty> getMappingContext() {
public MappingContext<? extends CosmosPersistentEntity<?>, CosmosPersistentProperty> getMappingContext() {
return mappingContext;
}
private ConvertingPropertyAccessor getPropertyAccessor(Object entity) {
final DocumentDbPersistentEntity<?> entityInformation =
final CosmosPersistentEntity<?> entityInformation =
mappingContext.getPersistentEntity(entity.getClass());
Assert.notNull(entityInformation, "EntityInformation should not be null.");
@ -192,15 +188,17 @@ public class MappingDocumentDbConverter
* @param fromPropertyValue
* @return
*/
public static Object toDocumentDBValue(Object fromPropertyValue) {
public static Object toCosmosDbValue(Object fromPropertyValue) {
if (fromPropertyValue == null) {
return null;
}
// com.microsoft.azure.documentdb.JsonSerializable#set(String, T) cannot set values for Date and Enum correctly
// com.microsoft.azure.data.cosmos.JsonSerializable#set(String, T) cannot set values for Date and Enum correctly
if (fromPropertyValue instanceof Date) {
fromPropertyValue = ((Date) fromPropertyValue).getTime();
} else if (fromPropertyValue instanceof ZonedDateTime) {
} else
if (fromPropertyValue instanceof ZonedDateTime) {
fromPropertyValue = ((ZonedDateTime) fromPropertyValue)
.format(DateTimeFormatter.ofPattern(ISO_8601_COMPATIBLE_DATE_PATTERN));
} else if (fromPropertyValue instanceof Enum) {

Просмотреть файл

@ -5,9 +5,7 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.core.generator;
import com.microsoft.azure.documentdb.SqlParameter;
import com.microsoft.azure.documentdb.SqlParameterCollection;
import com.microsoft.azure.documentdb.SqlQuerySpec;
import com.azure.data.cosmos.SqlQuerySpec;
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
@ -25,7 +23,7 @@ import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import static com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter.toDocumentDBValue;
import static com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter.toCosmosDbValue;
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public abstract class AbstractQueryGenerator {
@ -51,7 +49,7 @@ public abstract class AbstractQueryGenerator {
Assert.isTrue(CriteriaType.isBinary(criteria.getType()), "Criteria type should be binary operation");
final String subject = criteria.getSubject();
final Object subjectValue = toDocumentDBValue(criteria.getSubjectValues().get(0));
final Object subjectValue = toCosmosDbValue(criteria.getSubjectValues().get(0));
final String parameter = generateQueryParameter(subject);
parameters.add(Pair.with(parameter, subjectValue));
@ -65,8 +63,8 @@ public abstract class AbstractQueryGenerator {
private String generateBetween(@NonNull Criteria criteria, @NonNull List<Pair<String, Object>> parameters) {
final String subject = criteria.getSubject();
final Object value1 = toDocumentDBValue(criteria.getSubjectValues().get(0));
final Object value2 = toDocumentDBValue(criteria.getSubjectValues().get(1));
final Object value1 = toCosmosDbValue(criteria.getSubjectValues().get(0));
final Object value2 = toCosmosDbValue(criteria.getSubjectValues().get(1));
final String subject1 = "start";
final String subject2 = "end";
final String parameter1 = generateQueryParameter(subject1);
@ -200,32 +198,8 @@ public abstract class AbstractQueryGenerator {
return String.join(" ", queryTails.stream().filter(StringUtils::hasText).collect(Collectors.toList()));
}
/**
* Generate SqlQuerySpec with given DocumentQuery and query head.
*
* @param query DocumentQuery represent one query method.
* @param queryHead
* @return The SqlQuerySpec for DocumentClient.
*/
protected SqlQuerySpec generateQuery(@NonNull DocumentQuery query, @NonNull String queryHead) {
Assert.hasText(queryHead, "query head should have text.");
final Pair<String, List<Pair<String, Object>>> queryBody = generateQueryBody(query);
final String queryString = String.join(" ", queryHead, queryBody.getValue0(), generateQueryTail(query));
final List<Pair<String, Object>> parameters = queryBody.getValue1();
final SqlParameterCollection sqlParameters = new SqlParameterCollection();
sqlParameters.addAll(
parameters.stream()
.map(p -> new SqlParameter("@" + p.getValue0(), toDocumentDBValue(p.getValue1())))
.collect(Collectors.toList())
);
return new SqlQuerySpec(queryString, sqlParameters);
}
protected com.azure.data.cosmos.SqlQuerySpec generateCosmosQuery(@NonNull DocumentQuery query,
protected SqlQuerySpec generateCosmosQuery(@NonNull DocumentQuery query,
@NonNull String queryHead) {
final Pair<String, List<Pair<String, Object>>> queryBody = generateQueryBody(query);
final String queryString = String.join(" ", queryHead, queryBody.getValue0(), generateQueryTail(query));
@ -236,7 +210,7 @@ public abstract class AbstractQueryGenerator {
sqlParameters.addAll(
parameters.stream()
.map(p -> new com.azure.data.cosmos.SqlParameter("@" + p.getValue0(),
toDocumentDBValue(p.getValue1())))
toCosmosDbValue(p.getValue1())))
.collect(Collectors.toList())
);

Просмотреть файл

@ -5,16 +5,10 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.core.generator;
import com.microsoft.azure.documentdb.SqlQuerySpec;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
public class CountQueryGenerator extends AbstractQueryGenerator implements QuerySpecGenerator {
@Override
public SqlQuerySpec generate(DocumentQuery query) {
return super.generateQuery(query, "SELECT VALUE COUNT(1) FROM r");
}
@Override
public com.azure.data.cosmos.SqlQuerySpec generateCosmos(DocumentQuery query) {
return super.generateCosmosQuery(query, "SELECT VALUE COUNT(1) FROM r");

Просмотреть файл

@ -5,19 +5,12 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.core.generator;
import com.microsoft.azure.documentdb.SqlQuerySpec;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import lombok.NoArgsConstructor;
import org.springframework.lang.NonNull;
@NoArgsConstructor
public class FindQuerySpecGenerator extends AbstractQueryGenerator implements QuerySpecGenerator {
@Override
public SqlQuerySpec generate(@NonNull DocumentQuery query) {
return super.generateQuery(query, "SELECT * FROM ROOT r");
}
@Override
public com.azure.data.cosmos.SqlQuerySpec generateCosmos(DocumentQuery query) {
return super.generateCosmosQuery(query, "SELECT * FROM ROOT r");

Просмотреть файл

@ -5,23 +5,14 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.core.generator;
import com.microsoft.azure.documentdb.SqlQuerySpec;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
public interface QuerySpecGenerator {
/**
* Generate find/delete/update SqlQuerySpec for documentDb client.
*
* @param query tree structured query condition.
* @return SqlQuerySpec executed by documentDb client.
*/
SqlQuerySpec generate(DocumentQuery query);
/**
* Generate the SqlQuerySpec for cosmosDB client.
* @param query tree structured query condition.
* @return SqlQuerySpec executed by documentDb client.
* @return SqlQuerySpec executed by cosmos client.
*/
com.azure.data.cosmos.SqlQuerySpec generateCosmos(DocumentQuery query);
}

Просмотреть файл

@ -16,12 +16,12 @@ import org.springframework.data.util.TypeInformation;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class BasicDocumentDbPersistentEntity<T> extends BasicPersistentEntity<T, DocumentDbPersistentProperty>
implements DocumentDbPersistentEntity<T>, ApplicationContextAware {
public class BasicCosmosPersistentEntity<T> extends BasicPersistentEntity<T, CosmosPersistentProperty>
implements CosmosPersistentEntity<T>, ApplicationContextAware {
private final StandardEvaluationContext context;
public BasicDocumentDbPersistentEntity(TypeInformation<T> typeInformation) {
public BasicCosmosPersistentEntity(TypeInformation<T> typeInformation) {
super(typeInformation);
this.context = new StandardEvaluationContext();
}

Просмотреть файл

@ -13,16 +13,16 @@ import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
public class BasicDocumentDbPersistentProperty extends AnnotationBasedPersistentProperty<DocumentDbPersistentProperty>
implements DocumentDbPersistentProperty {
public class BasicCosmosPersistentProperty extends AnnotationBasedPersistentProperty<CosmosPersistentProperty>
implements CosmosPersistentProperty {
public BasicDocumentDbPersistentProperty(Property property, DocumentDbPersistentEntity<?> owner,
public BasicCosmosPersistentProperty(Property property, CosmosPersistentEntity<?> owner,
SimpleTypeHolder simpleTypeHolder) {
super(property, owner, simpleTypeHolder);
}
@Override
protected Association<DocumentDbPersistentProperty> createAssociation() {
protected Association<CosmosPersistentProperty> createAssociation() {
return new Association<>(this, null);
}

Просмотреть файл

@ -13,14 +13,14 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.TypeInformation;
public class DocumentDbMappingContext
extends AbstractMappingContext<BasicDocumentDbPersistentEntity<?>, DocumentDbPersistentProperty> {
public class CosmosMappingContext
extends AbstractMappingContext<BasicCosmosPersistentEntity<?>, CosmosPersistentProperty> {
private ApplicationContext context;
@Override
protected <T> BasicDocumentDbPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
final BasicDocumentDbPersistentEntity<T> entity = new BasicDocumentDbPersistentEntity<>(typeInformation);
protected <T> BasicCosmosPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
final BasicCosmosPersistentEntity<T> entity = new BasicCosmosPersistentEntity<>(typeInformation);
if (context != null) {
entity.setApplicationContext(context);
@ -29,10 +29,10 @@ public class DocumentDbMappingContext
}
@Override
public DocumentDbPersistentProperty createPersistentProperty(Property property,
BasicDocumentDbPersistentEntity<?> owner,
public CosmosPersistentProperty createPersistentProperty(Property property,
BasicCosmosPersistentEntity<?> owner,
SimpleTypeHolder simpleTypeHolder) {
return new BasicDocumentDbPersistentProperty(property, owner, simpleTypeHolder);
return new BasicCosmosPersistentProperty(property, owner, simpleTypeHolder);
}
@Override

Просмотреть файл

@ -9,7 +9,7 @@ package com.microsoft.azure.spring.data.cosmosdb.core.mapping;
import org.springframework.data.mapping.PersistentEntity;
public interface DocumentDbPersistentEntity<T> extends PersistentEntity<T, DocumentDbPersistentProperty> {
public interface CosmosPersistentEntity<T> extends PersistentEntity<T, CosmosPersistentProperty> {
String getCollection();

Просмотреть файл

@ -9,5 +9,5 @@ package com.microsoft.azure.spring.data.cosmosdb.core.mapping;
import org.springframework.data.mapping.PersistentProperty;
public interface DocumentDbPersistentProperty extends PersistentProperty<DocumentDbPersistentProperty> {
public interface CosmosPersistentProperty extends PersistentProperty<CosmosPersistentProperty> {
}

Просмотреть файл

@ -5,7 +5,7 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.core.mapping;
import com.microsoft.azure.documentdb.IndexingMode;
import com.azure.data.cosmos.IndexingMode;
import com.microsoft.azure.spring.data.cosmosdb.Constants;
import org.springframework.data.annotation.Persistent;
@ -18,7 +18,7 @@ import java.lang.annotation.*;
public @interface DocumentIndexingPolicy {
boolean automatic() default Constants.DEFAULT_INDEXINGPOLICY_AUTOMATIC;
IndexingMode mode() default IndexingMode.Consistent; // Enum is not really compile time constant
IndexingMode mode() default IndexingMode.CONSISTENT; // Enum is not really compile time constant
String[] includePaths() default {};

Просмотреть файл

@ -5,38 +5,39 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.core.query;
import com.azure.data.cosmos.FeedResponse;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
/**
* DocumentDbPageRequest representing page request during pagination query, field
* {@link com.microsoft.azure.documentdb.FeedResponse#getResponseContinuation response continuation token} is saved
* CosmosPageRequest representing page request during pagination query, field
* {@link FeedResponse#continuationToken()} response continuation token} is saved
* to help query next page.
* <p>
* The requestContinuation token should be saved after each request and reused in later queries.
*/
public class DocumentDbPageRequest extends PageRequest {
public class CosmosPageRequest extends PageRequest {
private static final long serialVersionUID = 6093304300037688375L;
// Request continuation token used to resume query
private String requestContinuation;
public DocumentDbPageRequest(int page, int size, String requestContinuation) {
super(page, size);
public CosmosPageRequest(int page, int size, String requestContinuation) {
super(page, size, Sort.unsorted());
this.requestContinuation = requestContinuation;
}
public static DocumentDbPageRequest of(int page, int size, String requestContinuation) {
return new DocumentDbPageRequest(page, size, requestContinuation);
public static CosmosPageRequest of(int page, int size, String requestContinuation) {
return new CosmosPageRequest(page, size, requestContinuation);
}
public DocumentDbPageRequest(int page, int size, String requestContinuation, Sort sort) {
public CosmosPageRequest(int page, int size, String requestContinuation, Sort sort) {
super(page, size, sort);
this.requestContinuation = requestContinuation;
}
public static DocumentDbPageRequest of(int page, int size, String requestContinuation, Sort sort) {
return new DocumentDbPageRequest(page, size, requestContinuation, sort);
public static CosmosPageRequest of(int page, int size, String requestContinuation, Sort sort) {
return new CosmosPageRequest(page, size, requestContinuation, sort);
}
public String getRequestContinuation() {
@ -58,11 +59,11 @@ public class DocumentDbPageRequest extends PageRequest {
return true;
}
if (!(obj instanceof DocumentDbPageRequest)) {
if (!(obj instanceof CosmosPageRequest)) {
return false;
}
final DocumentDbPageRequest that = (DocumentDbPageRequest) obj;
final CosmosPageRequest that = (CosmosPageRequest) obj;
final boolean continuationTokenEquals = requestContinuation != null ?
requestContinuation.equals(that.requestContinuation) : that.requestContinuation == null;

Просмотреть файл

@ -42,7 +42,6 @@ public enum CriteriaType {
@Getter
private String sqlKeyword;
// Map Part.Type to CriteriaType
private static final Map<Part.Type, CriteriaType> PART_TREE_TYPE_TO_CRITERIA;
static {

Просмотреть файл

@ -8,12 +8,12 @@ package com.microsoft.azure.spring.data.cosmosdb.exception;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
public class DocumentDBAccessException extends DataAccessException {
public DocumentDBAccessException(String msg) {
public class CosmosDBAccessException extends DataAccessException {
public CosmosDBAccessException(String msg) {
super(msg);
}
public DocumentDBAccessException(@Nullable String msg, @Nullable Throwable cause) {
public CosmosDBAccessException(@Nullable String msg, @Nullable Throwable cause) {
super(msg, cause);
}
}

Просмотреть файл

@ -6,7 +6,7 @@
package com.microsoft.azure.spring.data.cosmosdb.repository;
import com.microsoft.azure.documentdb.PartitionKey;
import com.azure.data.cosmos.PartitionKey;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
@ -14,7 +14,7 @@ import java.io.Serializable;
import java.util.Optional;
@NoRepositoryBean
public interface DocumentDbRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
public interface CosmosRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
/**
* Retrieves an entity by its id.

Просмотреть файл

@ -12,16 +12,16 @@ import org.springframework.data.repository.config.RepositoryConfigurationExtensi
import java.lang.annotation.Annotation;
public class DocumentDbRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
public class CosmosRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
@Override
protected Class<? extends Annotation> getAnnotation() {
return EnableDocumentDbRepositories.class;
return EnableCosmosRepositories.class;
}
@Override
protected RepositoryConfigurationExtension getExtension() {
return new DocumentDbRepositoryConfigurationExtension();
return new CosmosRepositoryConfigurationExtension();
}

Просмотреть файл

@ -0,0 +1,78 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.config;
import com.microsoft.azure.spring.data.cosmosdb.Constants;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosRepositoryFactoryBean;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
import org.springframework.data.repository.config.RepositoryConfigurationSource;
import org.springframework.data.repository.core.RepositoryMetadata;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Collections;
public class CosmosRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
@Override
public String getModuleName() {
return Constants.COSMOSDB_MODULE_NAME;
}
@Override
public String getModulePrefix() {
return Constants.COSMOSDB_MODULE_PREFIX;
}
public String getRepositoryFactoryBeanClassName() {
return CosmosRepositoryFactoryBean.class.getName();
}
@Override
protected Collection<Class<?>> getIdentifyingTypes() {
return Collections.<Class<?>>singleton(CosmosRepository.class);
}
@Override
protected Collection<Class<? extends Annotation>> getIdentifyingAnnotations() {
return Collections.emptyList();
}
@Override
public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource config) {
super.registerBeansForRoot(registry, config);
if (!registry.containsBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT)) {
final RootBeanDefinition definition = new RootBeanDefinition(CosmosMappingContext.class);
definition.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE);
definition.setSource(config.getSource());
registry.registerBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT, definition);
}
}
@Override
public void postProcess(BeanDefinitionBuilder builder, RepositoryConfigurationSource source) {
super.postProcess(builder, source);
}
// Overriding this to provide reactive repository support.
@Override
protected boolean useRepositoryConfiguration(RepositoryMetadata metadata) {
// CosmosRepository is the sync repository, and hence returning !isReactiveRepository.
// ReactiveCosmosRepository is reactive repository.
return !metadata.isReactiveRepository();
}
}

Просмотреть файл

@ -7,7 +7,7 @@
package com.microsoft.azure.spring.data.cosmosdb.repository.config;
import com.microsoft.azure.spring.data.cosmosdb.Constants;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbRepositoryFactoryBean;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosRepositoryFactoryBean;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Import;
import org.springframework.data.repository.config.DefaultRepositoryBaseClass;
@ -20,8 +20,8 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(DocumentDbRepositoriesRegistrar.class)
public @interface EnableDocumentDbRepositories {
@Import(CosmosRepositoriesRegistrar.class)
public @interface EnableCosmosRepositories {
String[] value() default {};
@ -39,7 +39,7 @@ public @interface EnableDocumentDbRepositories {
QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND;
Class<?> repositoryFactoryBeanClass() default DocumentDbRepositoryFactoryBean.class;
Class<?> repositoryFactoryBeanClass() default CosmosRepositoryFactoryBean.class;
Class<?> repositoryBaseClass() default DefaultRepositoryBaseClass.class;

Просмотреть файл

@ -0,0 +1,53 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.config;
import com.microsoft.azure.spring.data.cosmosdb.Constants;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.ReactiveCosmosRepositoryFactoryBean;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Import;
import org.springframework.data.repository.config.DefaultRepositoryBaseClass;
import org.springframework.data.repository.query.QueryLookupStrategy;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(ReactiveCosmosRepositoriesRegistrar.class)
public @interface EnableReactiveCosmosRepositories {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Filter[] includeFilters() default {};
Filter[] excludeFilters() default {};
String repositoryImplementationPostfix() default Constants.DEFAULT_REPOSITORY_IMPLEMENT_POSTFIX;
String namedQueriesLocation() default "";
QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND;
Class<?> repositoryFactoryBeanClass() default ReactiveCosmosRepositoryFactoryBean.class;
Class<?> repositoryBaseClass() default DefaultRepositoryBaseClass.class;
boolean considerNestedRepositories() default false;
}

Просмотреть файл

@ -0,0 +1,28 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.config;
import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
import java.lang.annotation.Annotation;
public class ReactiveCosmosRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
@Override
protected Class<? extends Annotation> getAnnotation() {
return EnableReactiveCosmosRepositories.class;
}
@Override
protected RepositoryConfigurationExtension getExtension() {
return new ReactiveCosmosRepositoryConfigurationExtension();
}
}

Просмотреть файл

@ -7,40 +7,41 @@
package com.microsoft.azure.spring.data.cosmosdb.repository.config;
import com.microsoft.azure.spring.data.cosmosdb.Constants;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbRepositoryFactoryBean;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.ReactiveCosmosRepositoryFactoryBean;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
import org.springframework.data.repository.config.RepositoryConfigurationSource;
import org.springframework.data.repository.core.RepositoryMetadata;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Collections;
public class DocumentDbRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
public class ReactiveCosmosRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
@Override
public String getModuleName() {
return Constants.DOCUMENTDB_MODULE_NAME;
return Constants.COSMOSDB_MODULE_NAME;
}
@Override
public String getModulePrefix() {
return Constants.DOCUMENTDB_MODULE_PREFIX;
return Constants.COSMOSDB_MODULE_PREFIX;
}
public String getRepositoryFactoryBeanClassName() {
return DocumentDbRepositoryFactoryBean.class.getName();
return ReactiveCosmosRepositoryFactoryBean.class.getName();
}
@Override
protected Collection<Class<?>> getIdentifyingTypes() {
return Collections.<Class<?>>singleton(DocumentDbRepository.class);
return Collections.<Class<?>>singleton(ReactiveCosmosRepository.class);
}
@Override
@ -53,12 +54,12 @@ public class DocumentDbRepositoryConfigurationExtension extends RepositoryConfig
public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource config) {
super.registerBeansForRoot(registry, config);
if (!registry.containsBeanDefinition(Constants.DOCUMENTDB_MAPPING_CONTEXT_NAME)) {
final RootBeanDefinition definition = new RootBeanDefinition(DocumentDbMappingContext.class);
if (!registry.containsBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT)) {
final RootBeanDefinition definition = new RootBeanDefinition(CosmosMappingContext.class);
definition.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE);
definition.setSource(config.getSource());
registry.registerBeanDefinition(Constants.DOCUMENTDB_MAPPING_CONTEXT_NAME, definition);
registry.registerBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT, definition);
}
}
@ -66,4 +67,10 @@ public class DocumentDbRepositoryConfigurationExtension extends RepositoryConfig
public void postProcess(BeanDefinitionBuilder builder, RepositoryConfigurationSource source) {
super.postProcess(builder, source);
}
// Overriding this to provide reactive repository support.
@Override
protected boolean useRepositoryConfiguration(RepositoryMetadata metadata) {
return metadata.isReactiveRepository();
}
}

Просмотреть файл

@ -0,0 +1,57 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.ResultProcessor;
public abstract class AbstractCosmosQuery implements RepositoryQuery {
private final CosmosQueryMethod method;
private final CosmosOperations operations;
public AbstractCosmosQuery(CosmosQueryMethod method, CosmosOperations operations) {
this.method = method;
this.operations = operations;
}
public Object execute(Object[] parameters) {
final CosmosParameterAccessor accessor = new CosmosParameterParameterAccessor(method, parameters);
final DocumentQuery query = createQuery(accessor);
final ResultProcessor processor = method.getResultProcessor().withDynamicProjection(accessor);
final String collection = ((CosmosEntityMetadata) method.getEntityInformation()).getCollectionName();
final CosmosQueryExecution execution = getExecution(accessor);
return execution.execute(query, processor.getReturnedType().getDomainType(), collection);
}
private CosmosQueryExecution getExecution(CosmosParameterAccessor accessor) {
if (isDeleteQuery()) {
return new CosmosQueryExecution.DeleteExecution(operations);
} else if (method.isPageQuery()) {
return new CosmosQueryExecution.PagedExecution(operations, accessor.getPageable());
} else if (isExistsQuery()) {
return new CosmosQueryExecution.ExistsExecution(operations);
} else {
return new CosmosQueryExecution.MultiEntityExecution(operations);
}
}
public CosmosQueryMethod getQueryMethod() {
return method;
}
protected abstract DocumentQuery createQuery(CosmosParameterAccessor accessor);
protected abstract boolean isDeleteQuery();
protected abstract boolean isExistsQuery();
}

Просмотреть файл

@ -1,57 +0,0 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.ResultProcessor;
public abstract class AbstractDocumentDbQuery implements RepositoryQuery {
private final DocumentDbQueryMethod method;
private final DocumentDbOperations operations;
public AbstractDocumentDbQuery(DocumentDbQueryMethod method, DocumentDbOperations operations) {
this.method = method;
this.operations = operations;
}
public Object execute(Object[] parameters) {
final DocumentDbParameterAccessor accessor = new DocumentDbParameterParameterAccessor(method, parameters);
final DocumentQuery query = createQuery(accessor);
final ResultProcessor processor = method.getResultProcessor().withDynamicProjection(accessor);
final String collection = ((DocumentDbEntityMetadata) method.getEntityInformation()).getCollectionName();
final DocumentDbQueryExecution execution = getExecution(accessor);
return execution.execute(query, processor.getReturnedType().getDomainType(), collection);
}
private DocumentDbQueryExecution getExecution(DocumentDbParameterAccessor accessor) {
if (isDeleteQuery()) {
return new DocumentDbQueryExecution.DeleteExecution(operations);
} else if (method.isPageQuery()) {
return new DocumentDbQueryExecution.PagedExecution(operations, accessor.getPageable());
} else if (isExistsQuery()) {
return new DocumentDbQueryExecution.ExistsExecution(operations);
} else {
return new DocumentDbQueryExecution.MultiEntityExecution(operations);
}
}
public DocumentDbQueryMethod getQueryMethod() {
return method;
}
protected abstract DocumentQuery createQuery(DocumentDbParameterAccessor accessor);
protected abstract boolean isDeleteQuery();
protected abstract boolean isExistsQuery();
}

Просмотреть файл

@ -0,0 +1,62 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.ResultProcessor;
public abstract class AbstractReactiveCosmosQuery implements RepositoryQuery {
private final ReactiveCosmosQueryMethod method;
private final ReactiveCosmosOperations operations;
public AbstractReactiveCosmosQuery(ReactiveCosmosQueryMethod method,
ReactiveCosmosOperations operations) {
this.method = method;
this.operations = operations;
}
public Object execute(Object[] parameters) {
final ReactiveCosmosParameterAccessor accessor =
new ReactiveCosmosParameterParameterAccessor(method, parameters);
final DocumentQuery query = createQuery(accessor);
final ResultProcessor processor =
method.getResultProcessor().withDynamicProjection(accessor);
final String collection =
((ReactiveCosmosEntityMetadata) method.getEntityInformation()).getCollectionName();
final ReactiveCosmosQueryExecution execution = getExecution(accessor);
return execution.execute(query, processor.getReturnedType().getDomainType(), collection);
}
private ReactiveCosmosQueryExecution getExecution(ReactiveCosmosParameterAccessor accessor) {
if (isDeleteQuery()) {
return new ReactiveCosmosQueryExecution.DeleteExecution(operations);
} else if (method.isPageQuery()) {
throw new IllegalArgumentException("Paged Query is not supported by reactive cosmos " +
"db");
} else if (isExistsQuery()) {
return new ReactiveCosmosQueryExecution.ExistsExecution(operations);
} else {
return new ReactiveCosmosQueryExecution.MultiEntityExecution(operations);
}
}
public ReactiveCosmosQueryMethod getQueryMethod() {
return method;
}
protected abstract DocumentQuery createQuery(ReactiveCosmosParameterAccessor accessor);
protected abstract boolean isDeleteQuery();
protected abstract boolean isExistsQuery();
}

Просмотреть файл

@ -7,6 +7,6 @@ package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import org.springframework.data.repository.core.EntityMetadata;
public interface DocumentDbEntityMetadata<T> extends EntityMetadata {
public interface CosmosEntityMetadata<T> extends EntityMetadata {
String getCollectionName();
}

Просмотреть файл

@ -8,9 +8,9 @@ package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import org.springframework.core.MethodParameter;
import org.springframework.data.repository.query.Parameter;
public class DocumentDbParameter extends Parameter {
public class CosmosParameter extends Parameter {
public DocumentDbParameter(MethodParameter parameter) {
public CosmosParameter(MethodParameter parameter) {
super(parameter);
}

Просмотреть файл

@ -7,6 +7,6 @@ package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import org.springframework.data.repository.query.ParameterAccessor;
public interface DocumentDbParameterAccessor extends ParameterAccessor {
public interface CosmosParameterAccessor extends ParameterAccessor {
Object[] getValues();
}

Просмотреть файл

@ -10,12 +10,12 @@ import org.springframework.data.repository.query.ParametersParameterAccessor;
import java.util.Arrays;
import java.util.List;
public class DocumentDbParameterParameterAccessor extends ParametersParameterAccessor
implements DocumentDbParameterAccessor {
public class CosmosParameterParameterAccessor extends ParametersParameterAccessor
implements CosmosParameterAccessor {
private final List<Object> values;
public DocumentDbParameterParameterAccessor(DocumentDbQueryMethod method, Object[] values) {
public CosmosParameterParameterAccessor(CosmosQueryMethod method, Object[] values) {
super(method.getParameters(), values);
this.values = Arrays.asList(values);

Просмотреть файл

@ -11,23 +11,23 @@ import org.springframework.data.repository.query.Parameters;
import java.lang.reflect.Method;
import java.util.List;
public class DocumentDbParameters extends Parameters<DocumentDbParameters, DocumentDbParameter> {
public class CosmosParameters extends Parameters<CosmosParameters, CosmosParameter> {
public DocumentDbParameters(Method method) {
public CosmosParameters(Method method) {
super(method);
}
private DocumentDbParameters(List<DocumentDbParameter> parameters) {
private CosmosParameters(List<CosmosParameter> parameters) {
super(parameters);
}
@Override
protected DocumentDbParameters createFrom(List<DocumentDbParameter> parameters) {
return new DocumentDbParameters(parameters);
protected CosmosParameters createFrom(List<CosmosParameter> parameters) {
return new CosmosParameters(parameters);
}
@Override
protected DocumentDbParameter createParameter(MethodParameter parameter) {
return new DocumentDbParameter(parameter);
protected CosmosParameter createParameter(MethodParameter parameter) {
return new CosmosParameter(parameter);
}
}

Просмотреть файл

@ -0,0 +1,88 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.Constants;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty;
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.data.repository.query.parser.Part;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
// TODO: String based query, based on how cosmosdb provides.
// StringCosmosQuery class,
// How to bind values to the query. if CosmosDb already has binding capability, if not we would have to do it here in
// some creative way.query creator are associated with part tree queries,
public class CosmosQueryCreator extends AbstractQueryCreator<DocumentQuery, Criteria> {
private final MappingContext<?, CosmosPersistentProperty> mappingContext;
public CosmosQueryCreator(PartTree tree, CosmosParameterAccessor accessor,
MappingContext<?, CosmosPersistentProperty> mappingContext) {
super(tree, accessor);
this.mappingContext = mappingContext;
}
private String getSubject(@NonNull Part part) {
String subject = mappingContext.getPersistentPropertyPath(part.getProperty()).toDotPath();
final Class<?> domainClass = part.getProperty().getOwningType().getType();
@SuppressWarnings("unchecked") final CosmosEntityInformation information =
new CosmosEntityInformation(domainClass);
if (information.getIdField().getName().equals(subject)) {
subject = Constants.ID_PROPERTY_NAME;
}
return subject;
}
@Override // Note (panli): side effect here, this method will change the iterator status of parameters.
protected Criteria create(Part part, Iterator<Object> parameters) {
final Part.Type type = part.getType();
final String subject = getSubject(part);
final List<Object> values = new ArrayList<>();
if (CriteriaType.isPartTypeUnSupported(type)) {
throw new UnsupportedOperationException("Unsupported keyword: " + type);
}
for (int i = 0; i < part.getNumberOfArguments(); i++) {
Assert.isTrue(parameters.hasNext(), "should not reach the end of iterator");
values.add(parameters.next());
}
return Criteria.getInstance(CriteriaType.toCriteriaType(type), subject, values);
}
@Override
protected Criteria and(@NonNull Part part, @NonNull Criteria base, @NonNull Iterator<Object> parameters) {
final Criteria right = this.create(part, parameters);
return Criteria.getInstance(CriteriaType.AND, base, right);
}
@Override
protected Criteria or(@NonNull Criteria base, @NonNull Criteria criteria) {
return Criteria.getInstance(CriteriaType.OR, base, criteria);
}
@Override
protected DocumentQuery complete(@NonNull Criteria criteria, @NonNull Sort sort) {
return new DocumentQuery(criteria).with(sort);
}
}

Просмотреть файл

@ -5,19 +5,19 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import org.springframework.data.domain.Pageable;
public interface DocumentDbQueryExecution {
public interface CosmosQueryExecution {
Object execute(DocumentQuery query, Class<?> type, String collection);
final class CollectionExecution implements DocumentDbQueryExecution {
final class CollectionExecution implements CosmosQueryExecution {
private final DocumentDbOperations operations;
private final CosmosOperations operations;
public CollectionExecution(DocumentDbOperations operations) {
public CollectionExecution(CosmosOperations operations) {
this.operations = operations;
}
@ -27,11 +27,11 @@ public interface DocumentDbQueryExecution {
}
}
final class MultiEntityExecution implements DocumentDbQueryExecution {
final class MultiEntityExecution implements CosmosQueryExecution {
private final DocumentDbOperations operations;
private final CosmosOperations operations;
public MultiEntityExecution(DocumentDbOperations operations) {
public MultiEntityExecution(CosmosOperations operations) {
this.operations = operations;
}
@ -41,11 +41,11 @@ public interface DocumentDbQueryExecution {
}
}
final class ExistsExecution implements DocumentDbQueryExecution {
final class ExistsExecution implements CosmosQueryExecution {
private final DocumentDbOperations operations;
private final CosmosOperations operations;
public ExistsExecution(DocumentDbOperations operations) {
public ExistsExecution(CosmosOperations operations) {
this.operations = operations;
}
@ -55,11 +55,11 @@ public interface DocumentDbQueryExecution {
}
}
final class DeleteExecution implements DocumentDbQueryExecution {
final class DeleteExecution implements CosmosQueryExecution {
private final DocumentDbOperations operations;
private final CosmosOperations operations;
public DeleteExecution(DocumentDbOperations operations) {
public DeleteExecution(CosmosOperations operations) {
this.operations = operations;
}
@ -69,20 +69,20 @@ public interface DocumentDbQueryExecution {
}
}
final class PagedExecution implements DocumentDbQueryExecution {
private final DocumentDbOperations operations;
final class PagedExecution implements CosmosQueryExecution {
private final CosmosOperations operations;
private final Pageable pageable;
public PagedExecution(DocumentDbOperations operations, Pageable pageable) {
public PagedExecution(CosmosOperations operations, Pageable pageable) {
this.operations = operations;
this.pageable = pageable;
}
@Override
public Object execute(DocumentQuery query, Class<?> type, String collection) {
if (pageable.getPageNumber() != 0 && !(pageable instanceof DocumentDbPageRequest)) {
if (pageable.getPageNumber() != 0 && !(pageable instanceof CosmosPageRequest)) {
throw new IllegalStateException("Not the first page but Pageable is not a valid " +
"DocumentDbPageRequest, requestContinuation is required for non first page request");
"CosmosPageRequest, requestContinuation is required for non first page request");
}
query.with(pageable);

Просмотреть файл

@ -5,7 +5,7 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.EntityMetadata;
import org.springframework.data.repository.core.RepositoryMetadata;
@ -13,11 +13,11 @@ import org.springframework.data.repository.query.QueryMethod;
import java.lang.reflect.Method;
public class DocumentDbQueryMethod extends QueryMethod {
public class CosmosQueryMethod extends QueryMethod {
private DocumentDbEntityMetadata<?> metadata;
private CosmosEntityMetadata<?> metadata;
public DocumentDbQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
public CosmosQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
super(method, metadata, factory);
}
@ -25,10 +25,10 @@ public class DocumentDbQueryMethod extends QueryMethod {
@SuppressWarnings("unchecked")
public EntityMetadata<?> getEntityInformation() {
final Class<Object> domainClass = (Class<Object>) getDomainClass();
final DocumentDbEntityInformation entityInformation =
new DocumentDbEntityInformation<Object, String>(domainClass);
final CosmosEntityInformation entityInformation =
new CosmosEntityInformation<Object, String>(domainClass);
this.metadata = new SimpleDocumentDbEntityMetadata<Object>(domainClass, entityInformation);
this.metadata = new SimpleCosmosEntityMetadata<Object>(domainClass, entityInformation);
return this.metadata;
}
}

Просмотреть файл

@ -5,21 +5,21 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbPersistentProperty;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty;
import org.apache.commons.lang3.NotImplementedException;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.repository.query.ResultProcessor;
import org.springframework.data.repository.query.parser.PartTree;
public class PartTreeDocumentDbQuery extends AbstractDocumentDbQuery {
public class PartTreeCosmosQuery extends AbstractCosmosQuery {
private final PartTree tree;
private final MappingContext<?, DocumentDbPersistentProperty> mappingContext;
private final MappingContext<?, CosmosPersistentProperty> mappingContext;
private final ResultProcessor processor;
public PartTreeDocumentDbQuery(DocumentDbQueryMethod method, DocumentDbOperations operations) {
public PartTreeCosmosQuery(CosmosQueryMethod method, CosmosOperations operations) {
super(method, operations);
this.processor = method.getResultProcessor();
@ -28,8 +28,8 @@ public class PartTreeDocumentDbQuery extends AbstractDocumentDbQuery {
}
@Override
protected DocumentQuery createQuery(DocumentDbParameterAccessor accessor) {
final DocumentDbQueryCreator creator = new DocumentDbQueryCreator(tree, accessor, mappingContext);
protected DocumentQuery createQuery(CosmosParameterAccessor accessor) {
final CosmosQueryCreator creator = new CosmosQueryCreator(tree, accessor, mappingContext);
final DocumentQuery query = creator.createQuery();

Просмотреть файл

@ -0,0 +1,52 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import org.apache.commons.lang3.NotImplementedException;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.repository.query.ResultProcessor;
import org.springframework.data.repository.query.parser.PartTree;
public class PartTreeReactiveCosmosQuery extends AbstractReactiveCosmosQuery {
private final PartTree tree;
private final MappingContext<?, CosmosPersistentProperty> mappingContext;
private final ResultProcessor processor;
public PartTreeReactiveCosmosQuery(ReactiveCosmosQueryMethod method, ReactiveCosmosOperations operations) {
super(method, operations);
this.processor = method.getResultProcessor();
this.tree = new PartTree(method.getName(), processor.getReturnedType().getDomainType());
this.mappingContext = operations.getConverter().getMappingContext();
}
@Override
protected DocumentQuery createQuery(ReactiveCosmosParameterAccessor accessor) {
final ReactiveCosmosQueryCreator creator = new ReactiveCosmosQueryCreator(tree, accessor, mappingContext);
final DocumentQuery query = creator.createQuery();
if (tree.isLimiting()) {
throw new NotImplementedException("Limiting is not supported.");
}
return query;
}
@Override
protected boolean isDeleteQuery() {
return tree.isDelete();
}
@Override
protected boolean isExistsQuery() {
return tree.isExistsProjection();
}
}

Просмотреть файл

@ -0,0 +1,12 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import org.springframework.data.repository.core.EntityMetadata;
public interface ReactiveCosmosEntityMetadata<T> extends EntityMetadata {
String getCollectionName();
}

Просмотреть файл

@ -0,0 +1,12 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import org.springframework.data.repository.query.ParameterAccessor;
public interface ReactiveCosmosParameterAccessor extends ParameterAccessor {
Object[] getValues();
}

Просмотреть файл

@ -0,0 +1,28 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import java.util.Arrays;
import java.util.List;
public class ReactiveCosmosParameterParameterAccessor extends ParametersParameterAccessor
implements ReactiveCosmosParameterAccessor {
private final List<Object> values;
public ReactiveCosmosParameterParameterAccessor(ReactiveCosmosQueryMethod method, Object[] values) {
super(method.getParameters(), values);
this.values = Arrays.asList(values);
}
@Override
public Object[] getValues() {
return values.toArray();
}
}

Просмотреть файл

@ -6,11 +6,11 @@
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.Constants;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbPersistentProperty;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty;
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
@ -23,12 +23,12 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class DocumentDbQueryCreator extends AbstractQueryCreator<DocumentQuery, Criteria> {
public class ReactiveCosmosQueryCreator extends AbstractQueryCreator<DocumentQuery, Criteria> {
private final MappingContext<?, DocumentDbPersistentProperty> mappingContext;
private final MappingContext<?, CosmosPersistentProperty> mappingContext;
public DocumentDbQueryCreator(PartTree tree, DocumentDbParameterAccessor accessor,
MappingContext<?, DocumentDbPersistentProperty> mappingContext) {
public ReactiveCosmosQueryCreator(PartTree tree, ReactiveCosmosParameterAccessor accessor,
MappingContext<?, CosmosPersistentProperty> mappingContext) {
super(tree, accessor);
this.mappingContext = mappingContext;
@ -38,8 +38,8 @@ public class DocumentDbQueryCreator extends AbstractQueryCreator<DocumentQuery,
String subject = mappingContext.getPersistentPropertyPath(part.getProperty()).toDotPath();
final Class<?> domainClass = part.getProperty().getOwningType().getType();
@SuppressWarnings("unchecked") final DocumentDbEntityInformation information =
new DocumentDbEntityInformation(domainClass);
@SuppressWarnings("unchecked") final CosmosEntityInformation information =
new CosmosEntityInformation(domainClass);
if (information.getIdField().getName().equals(subject)) {
subject = Constants.ID_PROPERTY_NAME;

Просмотреть файл

@ -0,0 +1,69 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
public interface ReactiveCosmosQueryExecution {
Object execute(DocumentQuery query, Class<?> type, String collection);
final class CollectionExecution implements ReactiveCosmosQueryExecution {
private final ReactiveCosmosOperations operations;
public CollectionExecution(ReactiveCosmosOperations operations) {
this.operations = operations;
}
@Override
public Object execute(DocumentQuery query, Class<?> type, String collection) {
return operations.getContainerName(type);
}
}
final class MultiEntityExecution implements ReactiveCosmosQueryExecution {
private final ReactiveCosmosOperations operations;
public MultiEntityExecution(ReactiveCosmosOperations operations) {
this.operations = operations;
}
@Override
public Object execute(DocumentQuery query, Class<?> type, String collection) {
return operations.find(query, type, collection);
}
}
final class ExistsExecution implements ReactiveCosmosQueryExecution {
private final ReactiveCosmosOperations operations;
public ExistsExecution(ReactiveCosmosOperations operations) {
this.operations = operations;
}
@Override
public Object execute(DocumentQuery query, Class<?> type, String collection) {
return operations.exists(query, type, collection);
}
}
final class DeleteExecution implements ReactiveCosmosQueryExecution {
private final ReactiveCosmosOperations operations;
public DeleteExecution(ReactiveCosmosOperations operations) {
this.operations = operations;
}
@Override
public Object execute(DocumentQuery query, Class<?> type, String collection) {
return operations.delete(query, type, collection);
}
}
}

Просмотреть файл

@ -0,0 +1,34 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.EntityMetadata;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.QueryMethod;
import java.lang.reflect.Method;
public class ReactiveCosmosQueryMethod extends QueryMethod {
private ReactiveCosmosEntityMetadata<?> metadata;
public ReactiveCosmosQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
super(method, metadata, factory);
}
@Override
@SuppressWarnings("unchecked")
public EntityMetadata<?> getEntityInformation() {
final Class<Object> domainClass = (Class<Object>) getDomainClass();
final CosmosEntityInformation entityInformation =
new CosmosEntityInformation<Object, String>(domainClass);
this.metadata = new SimpleReactiveCosmosEntityMetadata<Object>(domainClass, entityInformation);
return this.metadata;
}
}

Просмотреть файл

@ -5,15 +5,15 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import org.springframework.util.Assert;
public class SimpleDocumentDbEntityMetadata<T> implements DocumentDbEntityMetadata<T> {
public class SimpleCosmosEntityMetadata<T> implements CosmosEntityMetadata<T> {
private final Class<T> type;
private final DocumentDbEntityInformation<T, String> entityInformation;
private final CosmosEntityInformation<T, String> entityInformation;
public SimpleDocumentDbEntityMetadata(Class<T> type, DocumentDbEntityInformation<T, String> entityInformation) {
public SimpleCosmosEntityMetadata(Class<T> type, CosmosEntityInformation<T, String> entityInformation) {
Assert.notNull(type, "type must not be null!");
Assert.notNull(entityInformation, "entityInformation must not be null!");

Просмотреть файл

@ -0,0 +1,32 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import org.springframework.util.Assert;
public class SimpleReactiveCosmosEntityMetadata<T> implements ReactiveCosmosEntityMetadata<T> {
private final Class<T> type;
private final CosmosEntityInformation<T, String> entityInformation;
public SimpleReactiveCosmosEntityMetadata(Class<T> type, CosmosEntityInformation<T,
String> entityInformation) {
Assert.notNull(type, "type must not be null!");
Assert.notNull(entityInformation, "entityInformation must not be null!");
this.type = type;
this.entityInformation = entityInformation;
}
public Class<T> getJavaType() {
return type;
}
public String getCollectionName() {
return entityInformation.getCollectionName();
}
}

Просмотреть файл

@ -6,16 +6,17 @@
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
import com.microsoft.azure.documentdb.ExcludedPath;
import com.microsoft.azure.documentdb.IncludedPath;
import com.microsoft.azure.documentdb.IndexingMode;
import com.microsoft.azure.documentdb.IndexingPolicy;
import com.azure.data.cosmos.ExcludedPath;
import com.azure.data.cosmos.IncludedPath;
import com.azure.data.cosmos.IndexingMode;
import com.azure.data.cosmos.IndexingPolicy;
import com.microsoft.azure.spring.data.cosmosdb.Constants;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.json.JSONObject;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Version;
import org.springframework.data.repository.core.support.AbstractEntityInformation;
@ -26,11 +27,10 @@ import static com.microsoft.azure.spring.data.cosmosdb.common.ExpressionResolver
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class DocumentDbEntityInformation<T, ID> extends AbstractEntityInformation<T, ID> {
public class CosmosEntityInformation<T, ID> extends AbstractEntityInformation<T, ID> {
private static final String ETAG = "_etag";
private Field id;
@ -41,7 +41,7 @@ public class DocumentDbEntityInformation<T, ID> extends AbstractEntityInformatio
private IndexingPolicy indexingPolicy;
private boolean isVersioned;
public DocumentDbEntityInformation(Class<T> domainClass) {
public CosmosEntityInformation(Class<T> domainClass) {
super(domainClass);
this.id = getIdField(domainClass);
@ -110,10 +110,10 @@ public class DocumentDbEntityInformation<T, ID> extends AbstractEntityInformatio
private IndexingPolicy getIndexingPolicy(Class<?> domainClass) {
final IndexingPolicy policy = new IndexingPolicy();
policy.setAutomatic(this.getIndexingPolicyAutomatic(domainClass));
policy.setIndexingMode(this.getIndexingPolicyMode(domainClass));
policy.automatic(this.getIndexingPolicyAutomatic(domainClass));
policy.indexingMode(this.getIndexingPolicyMode(domainClass));
policy.setIncludedPaths(this.getIndexingPolicyIncludePaths(domainClass));
policy.setExcludedPaths(this.getIndexingPolicyExcludePaths(domainClass));
policy.excludedPaths(this.getIndexingPolicyExcludePaths(domainClass));
return policy;
}
@ -214,8 +214,8 @@ public class DocumentDbEntityInformation<T, ID> extends AbstractEntityInformatio
return mode;
}
private Collection<IncludedPath> getIndexingPolicyIncludePaths(Class<?> domainClass) {
final Collection<IncludedPath> pathsCollection = new ArrayList<>();
private List<IncludedPath> getIndexingPolicyIncludePaths(Class<?> domainClass) {
final List<IncludedPath> pathArrayList = new ArrayList<>();
final DocumentIndexingPolicy annotation = domainClass.getAnnotation(DocumentIndexingPolicy.class);
if (annotation == null || annotation.includePaths() == null || annotation.includePaths().length == 0) {
@ -225,27 +225,27 @@ public class DocumentDbEntityInformation<T, ID> extends AbstractEntityInformatio
final String[] rawPaths = annotation.includePaths();
for (final String path : rawPaths) {
pathsCollection.add(new IncludedPath(path));
pathArrayList.add(new IncludedPath(path));
}
return pathsCollection;
return pathArrayList;
}
private Collection<ExcludedPath> getIndexingPolicyExcludePaths(Class<?> domainClass) {
final Collection<ExcludedPath> pathsCollection = new ArrayList<>();
private List<ExcludedPath> getIndexingPolicyExcludePaths(Class<?> domainClass) {
final List<ExcludedPath> pathArrayList = new ArrayList<>();
final DocumentIndexingPolicy annotation = domainClass.getAnnotation(DocumentIndexingPolicy.class);
if (annotation == null || annotation.excludePaths() == null || annotation.excludePaths().length == 0) {
if (annotation == null || annotation.excludePaths().length == 0) {
return null; // Align the default value of IndexingPolicy
}
final String[] rawPaths = annotation.excludePaths();
for (final String path : rawPaths) {
pathsCollection.add(new ExcludedPath(path));
final JSONObject obj = new JSONObject(path);
pathArrayList.add(new ExcludedPath().path(obj.get("path").toString()));
}
return pathsCollection;
return pathArrayList;
}
private boolean getIsVersioned(Class<T> domainClass) {

Просмотреть файл

@ -6,9 +6,9 @@
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
import com.microsoft.azure.spring.data.cosmosdb.repository.query.DocumentDbQueryMethod;
import com.microsoft.azure.spring.data.cosmosdb.repository.query.PartTreeDocumentDbQuery;
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.repository.query.CosmosQueryMethod;
import com.microsoft.azure.spring.data.cosmosdb.repository.query.PartTreeCosmosQuery;
import org.springframework.context.ApplicationContext;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.EntityInformation;
@ -26,19 +26,19 @@ import java.lang.reflect.Method;
import java.util.Optional;
public class DocumentDbRepositoryFactory extends RepositoryFactorySupport {
public class CosmosRepositoryFactory extends RepositoryFactorySupport {
private final ApplicationContext applicationContext;
private final DocumentDbOperations dbOperations;
private final CosmosOperations cosmosOperations;
public DocumentDbRepositoryFactory(DocumentDbOperations dbOperations, ApplicationContext applicationContext) {
this.dbOperations = dbOperations;
public CosmosRepositoryFactory(CosmosOperations cosmosOperations, ApplicationContext applicationContext) {
this.cosmosOperations = cosmosOperations;
this.applicationContext = applicationContext;
}
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return SimpleDocumentDbRepository.class;
return SimpleCosmosRepository.class;
}
@Override
@ -49,31 +49,31 @@ public class DocumentDbRepositoryFactory extends RepositoryFactorySupport {
@Override
public <T, ID> EntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
return new DocumentDbEntityInformation<>(domainClass);
return new CosmosEntityInformation<>(domainClass);
}
@Override
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(
QueryLookupStrategy.Key key, QueryMethodEvaluationContextProvider evaluationContextProvider) {
return Optional.of(new DocumentDbQueryLookupStrategy(dbOperations, evaluationContextProvider));
return Optional.of(new CosmosDbQueryLookupStrategy(cosmosOperations, evaluationContextProvider));
}
private static class DocumentDbQueryLookupStrategy implements QueryLookupStrategy {
private final DocumentDbOperations dbOperations;
private static class CosmosDbQueryLookupStrategy implements QueryLookupStrategy {
private final CosmosOperations dbOperations;
public DocumentDbQueryLookupStrategy(
DocumentDbOperations operations, QueryMethodEvaluationContextProvider provider) {
public CosmosDbQueryLookupStrategy(
CosmosOperations operations, QueryMethodEvaluationContextProvider provider) {
this.dbOperations = operations;
}
@Override
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata,
ProjectionFactory factory, NamedQueries namedQueries) {
final DocumentDbQueryMethod queryMethod = new DocumentDbQueryMethod(method, metadata, factory);
final CosmosQueryMethod queryMethod = new CosmosQueryMethod(method, metadata, factory);
Assert.notNull(queryMethod, "queryMethod must not be null!");
Assert.notNull(dbOperations, "dbOperations must not be null!");
return new PartTreeDocumentDbQuery(queryMethod, dbOperations);
return new PartTreeCosmosQuery(queryMethod, dbOperations);
}
}

Просмотреть файл

@ -6,8 +6,8 @@
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
@ -20,21 +20,21 @@ import org.springframework.data.repository.core.support.RepositoryFactorySupport
import java.io.Serializable;
public class DocumentDbRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
public class CosmosRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
extends RepositoryFactoryBeanSupport<T, S, ID>
implements ApplicationContextAware {
private ApplicationContext applicationContext;
private DocumentDbOperations operations;
private CosmosOperations operations;
private boolean mappingContextConfigured = false;
public DocumentDbRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
public CosmosRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
super(repositoryInterface);
}
@Autowired
public void setDocumentDbOperations(DocumentDbOperations operations) {
public void setCosmosOperations(CosmosOperations operations) {
this.operations = operations;
}
@ -44,7 +44,7 @@ public class DocumentDbRepositoryFactoryBean<T extends Repository<S, ID>, S, ID
}
protected RepositoryFactorySupport getFactoryInstance(ApplicationContext applicationContext) {
return new DocumentDbRepositoryFactory(operations, applicationContext);
return new CosmosRepositoryFactory(operations, applicationContext);
}
@Override
@ -66,7 +66,7 @@ public class DocumentDbRepositoryFactoryBean<T extends Repository<S, ID>, S, ID
if (operations != null) {
setMappingContext(operations.getConverter().getMappingContext());
} else {
setMappingContext(new DocumentDbMappingContext());
setMappingContext(new CosmosMappingContext());
}
}
}

Просмотреть файл

@ -5,34 +5,47 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.repository.query.PartTreeReactiveCosmosQuery;
import com.microsoft.azure.spring.data.cosmosdb.repository.query.ReactiveCosmosQueryMethod;
import org.springframework.context.ApplicationContext;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.EntityInformation;
import org.springframework.data.repository.core.NamedQueries;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.ReactiveRepositoryFactorySupport;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.util.Assert;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Optional;
public class ReactiveCosmosRepositoryFactory extends ReactiveRepositoryFactorySupport {
private final ApplicationContext applicationContext;
private final ReactiveCosmosOperations cosmosOperations;
public ReactiveCosmosRepositoryFactory(ApplicationContext applicationContext) {
public ReactiveCosmosRepositoryFactory(ReactiveCosmosOperations cosmosOperations,
ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.cosmosOperations = cosmosOperations;
}
@Override
public <T, ID> EntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
return new DocumentDbEntityInformation<>(domainClass);
return new CosmosEntityInformation<>(domainClass);
}
@Override
protected Object getTargetRepository(RepositoryInformation information) {
final EntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType());
return getTargetRepositoryViaReflection(information, entityInformation, this.applicationContext);
final EntityInformation<?, Serializable> entityInformation =
getEntityInformation(information.getDomainType());
return getTargetRepositoryViaReflection(information, entityInformation,
this.applicationContext);
}
@Override
@ -42,8 +55,31 @@ public class ReactiveCosmosRepositoryFactory extends ReactiveRepositoryFactorySu
@Override
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(
QueryLookupStrategy.Key key, QueryMethodEvaluationContextProvider evaluationContextProvider) {
return super.getQueryLookupStrategy(key, evaluationContextProvider);
QueryLookupStrategy.Key key,
QueryMethodEvaluationContextProvider evaluationContextProvider) {
return Optional.of(new ReactiveCosmosQueryLookupStrategy(cosmosOperations,
evaluationContextProvider));
}
private static class ReactiveCosmosQueryLookupStrategy implements QueryLookupStrategy {
private final ReactiveCosmosOperations cosmosOperations;
public ReactiveCosmosQueryLookupStrategy(
ReactiveCosmosOperations operations, QueryMethodEvaluationContextProvider provider) {
this.cosmosOperations = operations;
}
@Override
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata,
ProjectionFactory factory, NamedQueries namedQueries) {
final ReactiveCosmosQueryMethod queryMethod = new ReactiveCosmosQueryMethod(method,
metadata, factory);
Assert.notNull(queryMethod, "queryMethod must not be null!");
Assert.notNull(cosmosOperations, "dbOperations must not be null!");
return new PartTreeReactiveCosmosQuery(queryMethod, cosmosOperations);
}
}
}

Просмотреть файл

@ -5,7 +5,10 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.mapping.context.MappingContext;
@ -15,33 +18,55 @@ import org.springframework.data.repository.core.support.RepositoryFactorySupport
import java.io.Serializable;
public class ReactiveCosmosRepositoryFactoryBean<T extends Repository<S, K>, S, K extends Serializable>
public class ReactiveCosmosRepositoryFactoryBean<T extends Repository<S, K>, S,
K extends Serializable>
extends RepositoryFactoryBeanSupport<T, S, K>
implements ApplicationContextAware {
private ApplicationContext applicationContext;
private ReactiveCosmosOperations cosmosOperations;
private boolean mappingContextConfigured = false;
public ReactiveCosmosRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
super(repositoryInterface);
}
@Autowired
public void setReactiveCosmosOperations(ReactiveCosmosOperations operations) {
this.cosmosOperations = operations;
}
@Override
protected RepositoryFactorySupport createRepositoryFactory() {
protected final RepositoryFactorySupport createRepositoryFactory() {
return getFactoryInstance(applicationContext);
}
protected RepositoryFactorySupport getFactoryInstance(ApplicationContext applicationContext) {
return new ReactiveCosmosRepositoryFactory(cosmosOperations, applicationContext);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
protected RepositoryFactorySupport getFactoryInstance(ApplicationContext applicationContext) {
return new ReactiveCosmosRepositoryFactory(applicationContext);
}
@Override
protected void setMappingContext(MappingContext<?, ?> mappingContext) {
super.setMappingContext(mappingContext);
this.mappingContextConfigured = true;
}
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
if (!this.mappingContextConfigured) {
if (cosmosOperations != null) {
setMappingContext(cosmosOperations.getConverter().getMappingContext());
} else {
setMappingContext(new CosmosMappingContext());
}
}
}
}

Просмотреть файл

@ -6,14 +6,13 @@
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
import com.microsoft.azure.documentdb.DocumentCollection;
import com.microsoft.azure.documentdb.PartitionKey;
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
import com.azure.data.cosmos.CosmosContainerProperties;
import com.azure.data.cosmos.PartitionKey;
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository;
import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
@ -27,29 +26,28 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.StreamSupport;
public class SimpleDocumentDbRepository<T, ID extends Serializable> implements DocumentDbRepository<T, ID> {
public class SimpleCosmosRepository<T, ID extends Serializable> implements CosmosRepository<T, ID> {
private final DocumentDbOperations operation;
private final DocumentDbEntityInformation<T, ID> information;
private final DocumentCollection collection;
private final CosmosOperations operation;
private final CosmosEntityInformation<T, ID> information;
public SimpleDocumentDbRepository(DocumentDbEntityInformation<T, ID> metadata,
public SimpleCosmosRepository(CosmosEntityInformation<T, ID> metadata,
ApplicationContext applicationContext) {
this.operation = applicationContext.getBean(DocumentDbOperations.class);
this.operation = applicationContext.getBean(CosmosOperations.class);
this.information = metadata;
collection = createCollectionIfNotExists();
createCollectionIfNotExists();
}
public SimpleDocumentDbRepository(DocumentDbEntityInformation<T, ID> metadata,
DocumentDbOperations dbOperations) {
public SimpleCosmosRepository(CosmosEntityInformation<T, ID> metadata,
CosmosOperations dbOperations) {
this.operation = dbOperations;
this.information = metadata;
collection = createCollectionIfNotExists();
createCollectionIfNotExists();
}
private DocumentCollection createCollectionIfNotExists() {
private CosmosContainerProperties createCollectionIfNotExists() {
return this.operation.createCollectionIfNotExists(this.information);
}
@ -79,7 +77,7 @@ public class SimpleDocumentDbRepository<T, ID extends Serializable> implements D
private PartitionKey createKey(String partitionKeyValue) {
if (StringUtils.isEmpty(partitionKeyValue)) {
return null;
return PartitionKey.None;
}
return new PartitionKey(partitionKeyValue);
@ -141,12 +139,6 @@ public class SimpleDocumentDbRepository<T, ID extends Serializable> implements D
return Optional.ofNullable(operation.findById(information.getCollectionName(), id, information.getJavaType()));
}
/**
* find one entity per id without partitions
*
* @param id
* @return
*/
@Override
public Optional<T> findById(ID id, PartitionKey partitionKey) {
Assert.notNull(id, "id must not be null");
@ -158,7 +150,6 @@ public class SimpleDocumentDbRepository<T, ID extends Serializable> implements D
return Optional.ofNullable(operation.findById(id, information.getJavaType(), partitionKey));
}
/**
* return count of documents in one collection without partitions
*

Просмотреть файл

@ -5,14 +5,15 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
import com.azure.data.cosmos.CosmosContainerResponse;
import com.azure.data.cosmos.PartitionKey;
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository;
import lombok.RequiredArgsConstructor;
import org.reactivestreams.Publisher;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
@ -22,19 +23,40 @@ import reactor.core.publisher.Mono;
import java.io.Serializable;
@RequiredArgsConstructor
public class SimpleReactiveCosmosRepository<T, K extends Serializable> implements ReactiveCosmosRepository<T, K> {
public final DocumentDbEntityInformation<T, K> entityInformation;
public final ReactiveCosmosOperations cosmosOperations;
private final CosmosEntityInformation<T, K> entityInformation;
private final ReactiveCosmosOperations cosmosOperations;
public SimpleReactiveCosmosRepository(CosmosEntityInformation<T, K> metadata,
ApplicationContext applicationContext) {
this.cosmosOperations = applicationContext.getBean(ReactiveCosmosOperations.class);
this.entityInformation = metadata;
createCollectionIfNotExists();
}
public SimpleReactiveCosmosRepository(CosmosEntityInformation<T, K> metadata,
ReactiveCosmosOperations reactiveCosmosOperations) {
this.cosmosOperations = reactiveCosmosOperations;
this.entityInformation = metadata;
createCollectionIfNotExists();
}
private CosmosContainerResponse createCollectionIfNotExists() {
return this.cosmosOperations.createCollectionIfNotExists(this.entityInformation).block();
}
@Override
public Flux<T> findAll(Sort sort) {
Assert.notNull(sort, "Sort must not be null!");
final DocumentQuery query = new DocumentQuery(Criteria.getInstance(CriteriaType.ALL)).with(sort);
final DocumentQuery query =
new DocumentQuery(Criteria.getInstance(CriteriaType.ALL)).with(sort);
return cosmosOperations.find(query, entityInformation.getJavaType(), entityInformation.getCollectionName());
return cosmosOperations.find(query, entityInformation.getJavaType(),
entityInformation.getCollectionName());
}
@Override
@ -71,7 +93,8 @@ public class SimpleReactiveCosmosRepository<T, K extends Serializable> implement
@Override
public Mono<T> findById(K id) {
Assert.notNull(id, "The given id must not be null!");
return cosmosOperations.findById(entityInformation.getCollectionName(), id, entityInformation.getJavaType());
return cosmosOperations.findById(entityInformation.getCollectionName(), id,
entityInformation.getJavaType());
}
@Override
@ -102,13 +125,15 @@ public class SimpleReactiveCosmosRepository<T, K extends Serializable> implement
public Mono<Boolean> existsById(Publisher<K> publisher) {
Assert.notNull(publisher, "The given id must not be null!");
return Mono.from(publisher).flatMap(id -> cosmosOperations.existsById(id, entityInformation.getJavaType(),
return Mono.from(publisher).flatMap(id -> cosmosOperations.existsById(id,
entityInformation.getJavaType(),
entityInformation.getCollectionName()));
}
@Override
public Flux<T> findAll() {
return cosmosOperations.findAll(entityInformation.getCollectionName(), entityInformation.getJavaType());
return cosmosOperations.findAll(entityInformation.getCollectionName(),
entityInformation.getJavaType());
}
@Override

Просмотреть файл

@ -1 +1 @@
org.springframework.data.repository.core.support.RepositoryFactorySupport=com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbRepositoryFactory
org.springframework.data.repository.core.support.RepositoryFactorySupport=com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosRepositoryFactory

Просмотреть файл

@ -0,0 +1,72 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb;
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_FAKE_CONNECTION_STRING;
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_FAKE_HOST;
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_FAKE_KEY;
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_INVALID_FAKE_CONNECTION_STRING;
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.DB_NAME;
import static org.assertj.core.api.Assertions.assertThat;
@PropertySource(value = {"classpath:application.properties"})
@RunWith(SpringJUnit4ClassRunner.class)
public class CosmosDbFactoryTestIT {
@Value("${cosmosdb.uri:}")
private String cosmosDbUri;
@Value("${cosmosdb.key:}")
private String cosmosDbKey;
@Test(expected = IllegalArgumentException.class)
public void testEmptyKey() {
final CosmosDBConfig dbConfig = CosmosDBConfig.builder(COSMOSDB_FAKE_HOST, "", DB_NAME).build();
new CosmosDbFactory(dbConfig);
}
@Test
public void testInvalidEndpoint() {
final CosmosDBConfig dbConfig =
CosmosDBConfig.builder(COSMOSDB_FAKE_HOST, COSMOSDB_FAKE_KEY, DB_NAME).build();
final CosmosDbFactory factory = new CosmosDbFactory(dbConfig);
assertThat(factory).isNotNull();
}
@Test
public void testConnectWithConnectionString() {
final CosmosDBConfig dbConfig =
CosmosDBConfig.builder(COSMOSDB_FAKE_CONNECTION_STRING, DB_NAME).build();
final CosmosDbFactory factory = new CosmosDbFactory(dbConfig);
assertThat(factory).isNotNull();
}
@Test(expected = CosmosDBAccessException.class)
public void testInvalidConnectionString() {
CosmosDBConfig.builder(COSMOSDB_INVALID_FAKE_CONNECTION_STRING, DB_NAME).build();
}
@Test
public void testConnectionPolicyUserAgentKept() {
final CosmosDBConfig dbConfig =
CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, DB_NAME).build();
final CosmosDbFactory factory = new CosmosDbFactory(dbConfig);
factory.getCosmosClient();
final String uaSuffix = factory.getConfig().getConnectionPolicy().userAgentSuffix();
assertThat(uaSuffix).contains("spring-data");
}
}

Просмотреть файл

@ -1,59 +0,0 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb;
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.*;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringJUnit4ClassRunner.class)
public class DocumentDbFactoryUnitTest {
@Test(expected = IllegalArgumentException.class)
public void testEmptyKey() {
final DocumentDBConfig dbConfig = DocumentDBConfig.builder(DOCUMENTDB_FAKE_HOST, "", DB_NAME).build();
new DocumentDbFactory(dbConfig);
}
@Test
public void testInvalidEndpoint() {
final DocumentDBConfig dbConfig =
DocumentDBConfig.builder(DOCUMENTDB_FAKE_HOST, DOCUMENTDB_FAKE_KEY, DB_NAME).build();
final DocumentDbFactory factory = new DocumentDbFactory(dbConfig);
assertThat(factory).isNotNull();
}
@Test
public void testConnectWithConnectionString() {
final DocumentDBConfig dbConfig =
DocumentDBConfig.builder(DOCUMENTDB_FAKE_CONNECTION_STRING, DB_NAME).build();
final DocumentDbFactory factory = new DocumentDbFactory(dbConfig);
assertThat(factory).isNotNull();
}
@Test(expected = DocumentDBAccessException.class)
public void testInvalidConnectionString() {
final DocumentDBConfig dbConfig =
DocumentDBConfig.builder(DOCUMENTDB_INVALID_FAKE_CONNECTION_STRING, DB_NAME).build();
}
@Test
public void testConnectionPolicyUserAgentKept() {
final DocumentDBConfig dbConfig =
DocumentDBConfig.builder(DOCUMENTDB_FAKE_HOST, DOCUMENTDB_FAKE_KEY, DB_NAME).build();
final DocumentDbFactory factory = new DocumentDbFactory(dbConfig);
final String uaSuffix = factory.getDocumentClient().getConnectionPolicy().getUserAgentSuffix();
assertThat(uaSuffix).contains("spring-data");
}
}

Просмотреть файл

@ -1,39 +0,0 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb;
import com.microsoft.azure.spring.data.cosmosdb.common.PropertyLoader;
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(PowerMockRunner.class)
@PrepareForTest(PropertyLoader.class)
@PowerMockIgnore({"javax.net.ssl.*", "javax.crypto.*"})
public class UserAgentTest {
private static final String TEST_VERSION = "1.0.0-FOR-TEST";
@Test
public void testUserAgentSuffixAppended() {
PowerMockito.mockStatic(PropertyLoader.class);
BDDMockito.given(PropertyLoader.getProjectVersion()).willReturn(TEST_VERSION);
assertThat(PropertyLoader.getProjectVersion()).isEqualTo(TEST_VERSION);
final DocumentDBConfig dbConfig = DocumentDBConfig.builder("https://uri", "key", TestConstants.DB_NAME).build();
final DocumentDbFactory factory = new DocumentDbFactory(dbConfig);
assertThat(factory.getDocumentClient().getConnectionPolicy().getUserAgentSuffix()).contains(TEST_VERSION);
}
}

Просмотреть файл

@ -0,0 +1,42 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.data.cosmosdb;
import com.microsoft.azure.spring.data.cosmosdb.common.PropertyLoader;
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.context.annotation.PropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@Ignore("Cannot use fake uri and key with CosmosDbFactory as it tries the connection on new creation." +
"At the same time, cannot use mockito with real values, because it won't prepare PropertyLoader class for mocking")
@RunWith(PowerMockRunner.class)
@PrepareForTest(PropertyLoader.class)
@PropertySource(value = {"classpath:application.properties"})
public class UserAgentTestIT {
private static final String TEST_VERSION = "1.0.0-FOR-TEST";
@Test
public void testUserAgentSuffixAppended() {
PowerMockito.mockStatic(PropertyLoader.class);
Mockito.doReturn(TEST_VERSION).when(PropertyLoader.getProjectVersion());
final CosmosDBConfig dbConfig = CosmosDBConfig.builder(TestConstants.COSMOSDB_FAKE_HOST,
TestConstants.COSMOSDB_FAKE_KEY, TestConstants.DB_NAME).build();
final CosmosDbFactory factory = new CosmosDbFactory(dbConfig);
factory.getCosmosClient();
assertThat(factory.getConfig().getConnectionPolicy().userAgentSuffix()).contains(TEST_VERSION);
}
}

Просмотреть файл

@ -5,7 +5,7 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.common;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest;
import org.json.JSONObject;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
@ -17,21 +17,21 @@ public class PageTestUtils {
public static void validateLastPage(Page page, int pageSize) {
final Pageable pageable = page.getPageable();
assertThat(pageable).isInstanceOf(DocumentDbPageRequest.class);
assertTrue(continuationTokenIsNull((DocumentDbPageRequest) pageable));
assertThat(pageable).isInstanceOf(CosmosPageRequest.class);
assertTrue(continuationTokenIsNull((CosmosPageRequest) pageable));
assertThat(pageable.getPageSize()).isEqualTo(pageSize);
}
public static void validateNonLastPage(Page page, int pageSize) {
final Pageable pageable = page.getPageable();
assertThat(pageable).isInstanceOf(DocumentDbPageRequest.class);
assertThat(((DocumentDbPageRequest) pageable).getRequestContinuation()).isNotNull();
assertThat(((DocumentDbPageRequest) pageable).getRequestContinuation()).isNotBlank();
assertThat(pageable).isInstanceOf(CosmosPageRequest.class);
assertThat(((CosmosPageRequest) pageable).getRequestContinuation()).isNotNull();
assertThat(((CosmosPageRequest) pageable).getRequestContinuation()).isNotBlank();
assertThat(pageable.getPageSize()).isEqualTo(pageSize);
}
private static boolean continuationTokenIsNull(DocumentDbPageRequest pageRequest) {
private static boolean continuationTokenIsNull(CosmosPageRequest pageRequest) {
final String tokenJson = pageRequest.getRequestContinuation();
if (tokenJson == null) {
return true;

Просмотреть файл

@ -5,7 +5,7 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.common;
import com.microsoft.azure.documentdb.IndexingMode;
import com.azure.data.cosmos.IndexingMode;
import com.microsoft.azure.spring.data.cosmosdb.domain.Address;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@ -29,7 +29,7 @@ public class TestConstants {
public static final String DEFAULT_COLLECTION_NAME = "Person";
public static final int DEFAULT_REQUEST_UNIT = 4000;
public static final boolean DEFAULT_INDEXINGPOLICY_AUTOMATIC = true;
public static final IndexingMode DEFAULT_INDEXINGPOLICY_MODE = IndexingMode.Consistent;
public static final IndexingMode DEFAULT_INDEXINGPOLICY_MODE = IndexingMode.CONSISTENT;
public static final String[] DEFAULT_EXCLUDEDPATHS = {};
public static final String[] DEFAULT_INCLUDEDPATHS = {
"{\"path\":\"/*\",\"indexes\":[" +
@ -43,7 +43,7 @@ public class TestConstants {
public static final int TIME_TO_LIVE = 5;
public static final String REQUEST_UNIT_STRING = "1000";
public static final boolean INDEXINGPOLICY_AUTOMATIC = false;
public static final IndexingMode INDEXINGPOLICY_MODE = IndexingMode.Lazy;
public static final IndexingMode INDEXINGPOLICY_MODE = IndexingMode.LAZY;
public static final String INCLUDEDPATH_0 = "{\"path\":\"/*\",\"indexes\":[" +
"{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":2}," +
"{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":2}," +
@ -130,11 +130,11 @@ public class TestConstants {
public static final String CRITERIA_FAKE_KEY = "CriteriaFakeKey";
public static final String CRITERIA_OBJECT = "CriteriaTestObject";
public static final String DOCUMENTDB_FAKE_HOST = "https://fakeuri";
public static final String DOCUMENTDB_FAKE_KEY = "fakekey";
public static final String DOCUMENTDB_FAKE_CONNECTION_STRING =
public static final String COSMOSDB_FAKE_HOST = "https://fakeuri";
public static final String COSMOSDB_FAKE_KEY = "fakekey";
public static final String COSMOSDB_FAKE_CONNECTION_STRING =
"AccountEndpoint=https://fakeuri/;AccountKey=fakekey;";
public static final String DOCUMENTDB_INVALID_FAKE_CONNECTION_STRING = "invalid connection string";
public static final String COSMOSDB_INVALID_FAKE_CONNECTION_STRING = "invalid connection string";
public static final String PROPERTY_ID = "id";
public static final String PROPERTY_FIRST_NAME = "firstName";

Просмотреть файл

@ -5,11 +5,9 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.common;
import com.microsoft.azure.documentdb.JsonSerializable;
import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@ -23,7 +21,7 @@ public class TestUtils {
return null;
}
public static <T extends JsonSerializable> void testIndexingPolicyPathsEquals(Collection<T> policyPaths,
public static <T> void testIndexingPolicyPathsEquals(List<T> policyPaths,
String [] pathsExpected) {
if (policyPaths == null) {
throw new IllegalStateException("policyPaths should not be null");
@ -38,7 +36,6 @@ public class TestUtils {
for (final String path: pathsExpected) {
Assert.isTrue(pathIterator.hasNext(), "policy path iterator should have next");
final T includedPath = pathIterator.next();
Assert.isTrue(includedPath.toString().equals(path), "unmatched policy path");
}
}

Просмотреть файл

@ -6,12 +6,12 @@
package com.microsoft.azure.spring.data.cosmosdb.config;
import com.azure.data.cosmos.ConsistencyLevel;
import com.azure.data.cosmos.CosmosClient;
import com.azure.data.cosmos.internal.RequestOptions;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.azure.documentdb.ConsistencyLevel;
import com.microsoft.azure.documentdb.DocumentClient;
import com.microsoft.azure.documentdb.RequestOptions;
import com.microsoft.azure.spring.data.cosmosdb.Constants;
import com.microsoft.azure.spring.data.cosmosdb.DocumentDbFactory;
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
import com.microsoft.azure.spring.data.cosmosdb.common.ExpressionResolver;
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
import org.assertj.core.api.Assertions;
@ -30,7 +30,7 @@ import org.springframework.context.support.AbstractApplicationContext;
import static org.junit.Assert.assertNotNull;
public class AbstractDocumentDbConfigurationIT {
public class AbstractCosmosConfigurationIT {
private static final String OBJECTMAPPER_BEAN_NAME = Constants.OBJECTMAPPER_BEAN_NAME;
@Rule
@ -39,23 +39,23 @@ public class AbstractDocumentDbConfigurationIT {
@Test
public void containsExpressionResolver() {
final AbstractApplicationContext context = new AnnotationConfigApplicationContext(
TestDocumentDbConfiguration.class);
TestCosmosConfiguration.class);
assertNotNull(context.getBean(ExpressionResolver.class));
}
@Test
public void containsDocumentDbFactory() {
public void containsCosmosDbFactory() {
final AbstractApplicationContext context = new AnnotationConfigApplicationContext(
TestDocumentDbConfiguration.class);
TestCosmosConfiguration.class);
Assertions.assertThat(context.getBean(DocumentDbFactory.class)).isNotNull();
Assertions.assertThat(context.getBean(CosmosDbFactory.class)).isNotNull();
}
@Test(expected = NoSuchBeanDefinitionException.class)
public void defaultObjectMapperBeanNotExists() {
final AbstractApplicationContext context = new AnnotationConfigApplicationContext(
TestDocumentDbConfiguration.class);
TestCosmosConfiguration.class);
context.getBean(ObjectMapper.class);
}
@ -73,44 +73,43 @@ public class AbstractDocumentDbConfigurationIT {
public void testRequestOptionsConfigurable() {
final AbstractApplicationContext context = new AnnotationConfigApplicationContext(
RequestOptionsConfiguration.class);
final DocumentDbFactory factory = context.getBean(DocumentDbFactory.class);
final CosmosDbFactory factory = context.getBean(CosmosDbFactory.class);
Assertions.assertThat(factory).isNotNull();
final RequestOptions options = factory.getConfig().getRequestOptions();
Assertions.assertThat(options).isNotNull();
Assertions.assertThat(options.getConsistencyLevel()).isEqualTo(ConsistencyLevel.ConsistentPrefix);
Assertions.assertThat(options.getDisableRUPerMinuteUsage()).isTrue();
Assertions.assertThat(options.getConsistencyLevel()).isEqualTo(ConsistencyLevel.CONSISTENT_PREFIX);
Assertions.assertThat(options.isScriptLoggingEnabled()).isTrue();
}
@Configuration
@PropertySource(value = {"classpath:application.properties"})
static class TestDocumentDbConfiguration extends AbstractDocumentDbConfiguration {
static class TestCosmosConfiguration extends AbstractCosmosConfiguration {
@Value("${cosmosdb.uri:}")
private String documentDbUri;
private String cosmosDbUri;
@Value("${cosmosdb.key:}")
private String documentDbKey;
private String cosmosDbKey;
@Mock
private DocumentClient mockClient;
private CosmosClient mockClient;
@Bean
public DocumentDBConfig getConfig() {
return DocumentDBConfig.builder(documentDbUri, documentDbKey, TestConstants.DB_NAME).build();
public CosmosDBConfig getConfig() {
return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, TestConstants.DB_NAME).build();
}
@Override
public DocumentClient documentClient(DocumentDBConfig config) {
public CosmosClient cosmosClient(CosmosDBConfig config) {
return mockClient;
}
}
@Configuration
static class ObjectMapperConfiguration extends TestDocumentDbConfiguration {
static class ObjectMapperConfiguration extends TestCosmosConfiguration {
@Bean(name = OBJECTMAPPER_BEAN_NAME)
public ObjectMapper objectMapper() {
return new ObjectMapper();
@ -119,28 +118,27 @@ public class AbstractDocumentDbConfigurationIT {
@Configuration
@PropertySource(value = {"classpath:application.properties"})
static class RequestOptionsConfiguration extends AbstractDocumentDbConfiguration {
static class RequestOptionsConfiguration extends AbstractCosmosConfiguration {
@Value("${cosmosdb.uri:}")
private String documentDbUri;
private String cosmosDbUri;
@Value("${cosmosdb.key:}")
private String documentDbKey;
private String cosmosDbKey;
private RequestOptions getRequestOptions() {
final RequestOptions options = new RequestOptions();
options.setConsistencyLevel(ConsistencyLevel.ConsistentPrefix);
options.setDisableRUPerMinuteUsage(true);
options.setConsistencyLevel(ConsistencyLevel.CONSISTENT_PREFIX);
options.setScriptLoggingEnabled(true);
return options;
}
@Bean
public DocumentDBConfig getConfig() {
public CosmosDBConfig getConfig() {
final RequestOptions options = getRequestOptions();
return DocumentDBConfig.builder(documentDbUri, documentDbKey, TestConstants.DB_NAME)
return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, TestConstants.DB_NAME)
.requestOptions(options)
.build();
}

Просмотреть файл

@ -7,18 +7,18 @@
package com.microsoft.azure.spring.data.cosmosdb.core;
import com.azure.data.cosmos.CosmosClientException;
import com.microsoft.azure.documentdb.PartitionKey;
import com.azure.data.cosmos.PartitionKey;
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest;
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.domain.Person;
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import org.assertj.core.util.Lists;
import org.junit.After;
import org.junit.Before;
@ -63,7 +63,7 @@ import java.util.UUID;
@RunWith(SpringJUnit4ClassRunner.class)
@PropertySource(value = { "classpath:application.properties" })
public class DocumentDbTemplateIT {
public class CosmosTemplateIT {
private static final Person TEST_PERSON = new Person(ID_1, FIRST_NAME, LAST_NAME, HOBBIES,
ADDRESSES);
@ -80,14 +80,13 @@ public class DocumentDbTemplateIT {
private static final String WRONG_ETAG = "WRONG_ETAG";
@Value("${cosmosdb.uri}")
private String documentDbUri;
private String cosmosDbUri;
@Value("${cosmosdb.key}")
private String documentDbKey;
private String cosmosDbKey;
private static DocumentDbTemplate dbTemplate;
private static DocumentDbEntityInformation<Person, String> personInfo;
private static CosmosTemplate cosmosTemplate;
private static CosmosEntityInformation<Person, String> personInfo;
private static String collectionName;
private static boolean initialized;
private Person insertedPerson;
@ -98,64 +97,64 @@ public class DocumentDbTemplateIT {
@Before
public void setup() throws ClassNotFoundException {
if (!initialized) {
final DocumentDBConfig dbConfig = DocumentDBConfig.builder(documentDbUri,
documentDbKey, DB_NAME).build();
final CosmosDBConfig dbConfig = CosmosDBConfig.builder(cosmosDbUri,
cosmosDbKey, DB_NAME).build();
final CosmosDbFactory cosmosDbFactory = new CosmosDbFactory(dbConfig);
final DocumentDbMappingContext mappingContext = new DocumentDbMappingContext();
personInfo = new DocumentDbEntityInformation<>(Person.class);
final CosmosMappingContext mappingContext = new CosmosMappingContext();
personInfo = new CosmosEntityInformation<>(Person.class);
collectionName = personInfo.getCollectionName();
mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class));
final MappingDocumentDbConverter dbConverter =
new MappingDocumentDbConverter(mappingContext, null);
dbTemplate = new DocumentDbTemplate(cosmosDbFactory, dbConverter, DB_NAME);
dbTemplate.createCollectionIfNotExists(personInfo);
final MappingCosmosConverter cosmosConverter = new MappingCosmosConverter(mappingContext,
null);
cosmosTemplate = new CosmosTemplate(cosmosDbFactory, cosmosConverter, DB_NAME);
cosmosTemplate.createCollectionIfNotExists(personInfo);
initialized = true;
}
insertedPerson = dbTemplate.insert(Person.class.getSimpleName(), TEST_PERSON, null);
insertedPerson = cosmosTemplate.insert(Person.class.getSimpleName(), TEST_PERSON, null);
}
@After
public void cleanup() {
dbTemplate.deleteAll(Person.class.getSimpleName(), Person.class);
cosmosTemplate.deleteAll(Person.class.getSimpleName(), Person.class);
}
@Test(expected = DocumentDBAccessException.class)
@Test(expected = CosmosDBAccessException.class)
public void testInsertDuplicateId() {
dbTemplate.insert(Person.class.getSimpleName(), TEST_PERSON,
cosmosTemplate.insert(Person.class.getSimpleName(), TEST_PERSON,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON)));
}
@Test
public void testFindAll() {
final List<Person> result = dbTemplate.findAll(Person.class.getSimpleName(), Person.class);
final List<Person> result = cosmosTemplate.findAll(Person.class.getSimpleName(), Person.class);
assertThat(result.size()).isEqualTo(1);
assertThat(result.get(0)).isEqualTo(TEST_PERSON);
}
@Test
public void testFindById() {
final Person result = dbTemplate.findById(Person.class.getSimpleName(),
final Person result = cosmosTemplate.findById(Person.class.getSimpleName(),
TEST_PERSON.getId(), Person.class);
assertEquals(result, TEST_PERSON);
final Person nullResult = dbTemplate.findById(Person.class.getSimpleName(),
final Person nullResult = cosmosTemplate.findById(Person.class.getSimpleName(),
NOT_EXIST_ID, Person.class);
assertThat(nullResult).isNull();
}
@Test
public void testFindByMultiIds() {
dbTemplate.insert(TEST_PERSON_2,
cosmosTemplate.insert(TEST_PERSON_2,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
dbTemplate.insert(TEST_PERSON_3,
cosmosTemplate.insert(TEST_PERSON_3,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3)));
final List<Object> ids = Lists.newArrayList(ID_1, ID_2, ID_3);
final List<Person> result = dbTemplate.findByIds(ids, Person.class, collectionName);
final List<Person> result = cosmosTemplate.findByIds(ids, Person.class, collectionName);
final List<Person> expected = Lists.newArrayList(TEST_PERSON, TEST_PERSON_2, TEST_PERSON_3);
assertThat(result.size()).isEqualTo(expected.size());
@ -165,17 +164,17 @@ public class DocumentDbTemplateIT {
@Test
public void testUpsertNewDocument() {
// Delete first as was inserted in setup
dbTemplate.deleteById(Person.class.getSimpleName(), TEST_PERSON.getId(),
cosmosTemplate.deleteById(Person.class.getSimpleName(), TEST_PERSON.getId(),
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON)));
final String firstName = NEW_FIRST_NAME + "_" + UUID.randomUUID().toString();
final Person newPerson = new Person(TEST_PERSON.getId(), firstName,
NEW_FIRST_NAME, null, null);
dbTemplate.upsert(Person.class.getSimpleName(), newPerson,
cosmosTemplate.upsert(Person.class.getSimpleName(), newPerson,
new PartitionKey(personInfo.getPartitionKeyFieldValue(newPerson)));
final List<Person> result = dbTemplate.findAll(Person.class);
final List<Person> result = cosmosTemplate.findAll(Person.class);
assertThat(result.size()).isEqualTo(1);
assertEquals(result.get(0).getFirstName(), firstName);
@ -187,9 +186,9 @@ public class DocumentDbTemplateIT {
TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(), TEST_PERSON.getShippingAddresses());
updated.set_etag(insertedPerson.get_etag());
dbTemplate.upsert(Person.class.getSimpleName(), updated, null);
cosmosTemplate.upsert(Person.class.getSimpleName(), updated, null);
final Person result = dbTemplate.findById(Person.class.getSimpleName(),
final Person result = cosmosTemplate.findById(Person.class.getSimpleName(),
updated.getId(), Person.class);
assertEquals(result, updated);
@ -202,14 +201,14 @@ public class DocumentDbTemplateIT {
updated.set_etag(WRONG_ETAG);
try {
dbTemplate.upsert(Person.class.getSimpleName(), updated, null);
} catch (DocumentDBAccessException e) {
cosmosTemplate.upsert(Person.class.getSimpleName(), updated, null);
} catch (CosmosDBAccessException e) {
assertThat(e.getCause()).isNotNull();
final Throwable cosmosClientException = e.getCause().getCause();
assertThat(cosmosClientException).isInstanceOf(CosmosClientException.class);
assertThat(cosmosClientException.getMessage()).contains(PRECONDITION_IS_NOT_MET);
final Person unmodifiedPerson = dbTemplate.findById(Person.class.getSimpleName(),
final Person unmodifiedPerson = cosmosTemplate.findById(Person.class.getSimpleName(),
TEST_PERSON.getId(), Person.class);
assertThat(unmodifiedPerson.getFirstName()).isEqualTo(insertedPerson.getFirstName());
return;
@ -220,54 +219,54 @@ public class DocumentDbTemplateIT {
@Test
public void testDeleteById() {
dbTemplate.insert(TEST_PERSON_2, null);
assertThat(dbTemplate.findAll(Person.class).size()).isEqualTo(2);
cosmosTemplate.insert(TEST_PERSON_2, null);
assertThat(cosmosTemplate.findAll(Person.class).size()).isEqualTo(2);
dbTemplate.deleteById(Person.class.getSimpleName(), TEST_PERSON.getId(),
cosmosTemplate.deleteById(Person.class.getSimpleName(), TEST_PERSON.getId(),
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON)));
final List<Person> result = dbTemplate.findAll(Person.class);
final List<Person> result = cosmosTemplate.findAll(Person.class);
assertThat(result.size()).isEqualTo(1);
assertEquals(result.get(0), TEST_PERSON_2);
}
@Test
public void testCountByCollection() {
final long prevCount = dbTemplate.count(collectionName);
final long prevCount = cosmosTemplate.count(collectionName);
assertThat(prevCount).isEqualTo(1);
dbTemplate.insert(TEST_PERSON_2,
cosmosTemplate.insert(TEST_PERSON_2,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
final long newCount = dbTemplate.count(collectionName);
final long newCount = cosmosTemplate.count(collectionName);
assertThat(newCount).isEqualTo(2);
}
@Test
public void testCountByQuery() {
dbTemplate.insert(TEST_PERSON_2,
cosmosTemplate.insert(TEST_PERSON_2,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName",
Collections.singletonList(TEST_PERSON_2.getFirstName()));
final DocumentQuery query = new DocumentQuery(criteria);
final long count = dbTemplate.count(query, Person.class, collectionName);
final long count = cosmosTemplate.count(query, Person.class, collectionName);
assertThat(count).isEqualTo(1);
}
@Test
public void testFindAllPageableMultiPages() {
dbTemplate.insert(TEST_PERSON_2,
cosmosTemplate.insert(TEST_PERSON_2,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
final DocumentDbPageRequest pageRequest = new DocumentDbPageRequest(0, PAGE_SIZE_1, null);
final Page<Person> page1 = dbTemplate.findAll(pageRequest, Person.class, collectionName);
final CosmosPageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_1, null);
final Page<Person> page1 = cosmosTemplate.findAll(pageRequest, Person.class, collectionName);
assertThat(page1.getContent().size()).isEqualTo(PAGE_SIZE_1);
validateNonLastPage(page1, PAGE_SIZE_1);
final Page<Person> page2 = dbTemplate.findAll(page1.getPageable(), Person.class,
final Page<Person> page2 = cosmosTemplate.findAll(page1.getPageable(), Person.class,
collectionName);
assertThat(page2.getContent().size()).isEqualTo(1);
validateLastPage(page2, PAGE_SIZE_1);
@ -275,30 +274,30 @@ public class DocumentDbTemplateIT {
@Test
public void testPaginationQuery() {
dbTemplate.insert(TEST_PERSON_2,
cosmosTemplate.insert(TEST_PERSON_2,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName",
Collections.singletonList(FIRST_NAME));
final PageRequest pageRequest = new DocumentDbPageRequest(0, PAGE_SIZE_2, null);
final PageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_2, null);
final DocumentQuery query = new DocumentQuery(criteria).with(pageRequest);
final Page<Person> page = dbTemplate.paginationQuery(query, Person.class, collectionName);
final Page<Person> page = cosmosTemplate.paginationQuery(query, Person.class, collectionName);
assertThat(page.getContent().size()).isEqualTo(1);
validateLastPage(page, PAGE_SIZE_2);
}
@Test
public void testFindAllWithPageableAndSort() {
dbTemplate.insert(TEST_PERSON_2,
cosmosTemplate.insert(TEST_PERSON_2,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
dbTemplate.insert(TEST_PERSON_3,
cosmosTemplate.insert(TEST_PERSON_3,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3)));
final Sort sort = new Sort(Sort.Direction.DESC, "firstName");
final PageRequest pageRequest = DocumentDbPageRequest.of(0, PAGE_SIZE_3, null, sort);
final Sort sort = Sort.by(Sort.Direction.DESC, "firstName");
final PageRequest pageRequest = CosmosPageRequest.of(0, PAGE_SIZE_3, null, sort);
final Page<Person> page = dbTemplate.findAll(pageRequest, Person.class, collectionName);
final Page<Person> page = cosmosTemplate.findAll(pageRequest, Person.class, collectionName);
assertThat(page.getContent().size()).isEqualTo(3);
validateLastPage(page, PAGE_SIZE_3);
@ -314,19 +313,19 @@ public class DocumentDbTemplateIT {
final Person testPerson4 = new Person("id_4", "barney", NEW_LAST_NAME, HOBBIES, ADDRESSES);
final Person testPerson5 = new Person("id_5", "fred", NEW_LAST_NAME, HOBBIES, ADDRESSES);
dbTemplate.insert(TEST_PERSON_2,
cosmosTemplate.insert(TEST_PERSON_2,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
dbTemplate.insert(TEST_PERSON_3,
cosmosTemplate.insert(TEST_PERSON_3,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3)));
dbTemplate.insert(testPerson4,
cosmosTemplate.insert(testPerson4,
new PartitionKey(personInfo.getPartitionKeyFieldValue(testPerson4)));
dbTemplate.insert(testPerson5,
cosmosTemplate.insert(testPerson5,
new PartitionKey(personInfo.getPartitionKeyFieldValue(testPerson5)));
final Sort sort = new Sort(Sort.Direction.ASC, "firstName");
final PageRequest pageRequest = DocumentDbPageRequest.of(0, PAGE_SIZE_3, null, sort);
final Sort sort = Sort.by(Sort.Direction.ASC, "firstName");
final PageRequest pageRequest = CosmosPageRequest.of(0, PAGE_SIZE_3, null, sort);
final Page<Person> firstPage = dbTemplate.findAll(pageRequest, Person.class,
final Page<Person> firstPage = cosmosTemplate.findAll(pageRequest, Person.class,
collectionName);
assertThat(firstPage.getContent().size()).isEqualTo(3);
@ -337,7 +336,7 @@ public class DocumentDbTemplateIT {
assertThat(firstPageResults.get(1).getFirstName()).isEqualTo(FIRST_NAME);
assertThat(firstPageResults.get(2).getFirstName()).isEqualTo(testPerson5.getFirstName());
final Page<Person> secondPage = dbTemplate.findAll(firstPage.getPageable(), Person.class,
final Page<Person> secondPage = cosmosTemplate.findAll(firstPage.getPageable(), Person.class,
collectionName);
assertThat(secondPage.getContent().size()).isEqualTo(2);

Просмотреть файл

@ -5,7 +5,7 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.core;
import com.microsoft.azure.documentdb.PartitionKey;
import com.azure.data.cosmos.PartitionKey;
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.domain.Person;
@ -16,7 +16,6 @@ import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.util.Assert;
import static com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType.IS_EQUAL;
@ -26,7 +25,7 @@ import java.lang.reflect.Method;
import java.util.Arrays;
@RunWith(MockitoJUnitRunner.class)
public class DocumentDbTemplateIllegalTest {
public class CosmosTemplateIllegalTest {
private static final String NULL_STR = null;
private static final String DUMMY_COLL = "dummy";
private static final String DUMMY_ID = "ID_1";
@ -36,7 +35,7 @@ public class DocumentDbTemplateIllegalTest {
private static final String CHECK_FAILURE_MSG = "Illegal argument is not checked";
@Mock(answer = Answers.CALLS_REAL_METHODS)
private DocumentDbTemplate dbTemplate;
private CosmosTemplate dbTemplate;
private Class dbTemplateClass;
@Before

Просмотреть файл

@ -6,17 +6,17 @@
package com.microsoft.azure.spring.data.cosmosdb.core;
import com.microsoft.azure.documentdb.PartitionKey;
import com.azure.data.cosmos.PartitionKey;
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest;
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.domain.PartitionPerson;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -45,7 +45,7 @@ import static org.junit.Assert.assertTrue;
@RunWith(SpringJUnit4ClassRunner.class)
@PropertySource(value = {"classpath:application.properties"})
public class DocumentDbTemplatePartitionIT {
public class CosmosTemplatePartitionIT {
private static final PartitionPerson TEST_PERSON = new PartitionPerson(ID_1, FIRST_NAME, LAST_NAME,
HOBBIES, ADDRESSES);
@ -53,13 +53,13 @@ public class DocumentDbTemplatePartitionIT {
TEST_PERSON.getLastName(), HOBBIES, ADDRESSES);
@Value("${cosmosdb.uri}")
private String documentDbUri;
private String cosmosDbUri;
@Value("${cosmosdb.key}")
private String documentDbKey;
private String cosmosDbKey;
private static DocumentDbTemplate dbTemplate;
private static CosmosTemplate cosmosTemplate;
private static String collectionName;
private static DocumentDbEntityInformation<PartitionPerson, String> personInfo;
private static CosmosEntityInformation<PartitionPerson, String> personInfo;
private static boolean initialized;
@Autowired
@ -68,36 +68,36 @@ public class DocumentDbTemplatePartitionIT {
@Before
public void setup() throws ClassNotFoundException {
if (!initialized) {
final DocumentDBConfig dbConfig = DocumentDBConfig.builder(documentDbUri, documentDbKey, DB_NAME).build();
final CosmosDBConfig dbConfig = CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, DB_NAME).build();
final CosmosDbFactory cosmosDbFactory = new CosmosDbFactory(dbConfig);
final DocumentDbMappingContext mappingContext = new DocumentDbMappingContext();
final CosmosMappingContext mappingContext = new CosmosMappingContext();
personInfo = new DocumentDbEntityInformation<>(PartitionPerson.class);
personInfo = new CosmosEntityInformation<>(PartitionPerson.class);
mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class));
final MappingDocumentDbConverter dbConverter = new MappingDocumentDbConverter(mappingContext, null);
final MappingCosmosConverter dbConverter = new MappingCosmosConverter(mappingContext, null);
dbTemplate = new DocumentDbTemplate(cosmosDbFactory, dbConverter, DB_NAME);
cosmosTemplate = new CosmosTemplate(cosmosDbFactory, dbConverter, DB_NAME);
collectionName = personInfo.getCollectionName();
dbTemplate.createCollectionIfNotExists(personInfo);
cosmosTemplate.createCollectionIfNotExists(personInfo);
initialized = true;
}
dbTemplate.insert(PartitionPerson.class.getSimpleName(), TEST_PERSON,
cosmosTemplate.insert(PartitionPerson.class.getSimpleName(), TEST_PERSON,
new PartitionKey(TEST_PERSON.getLastName()));
}
@After
public void cleanup() {
dbTemplate.deleteAll(personInfo.getCollectionName(), PartitionPerson.class);
cosmosTemplate.deleteAll(personInfo.getCollectionName(), PartitionPerson.class);
}
@Test
public void testFindWithPartition() {
Criteria criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_LAST_NAME, Arrays.asList(LAST_NAME));
DocumentQuery query = new DocumentQuery(criteria);
List<PartitionPerson> result = dbTemplate.find(query, PartitionPerson.class,
List<PartitionPerson> result = cosmosTemplate.find(query, PartitionPerson.class,
PartitionPerson.class.getSimpleName());
assertThat(result.size()).isEqualTo(1);
@ -105,15 +105,16 @@ public class DocumentDbTemplatePartitionIT {
criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_ID, Arrays.asList(ID_1));
query = new DocumentQuery(criteria);
result = dbTemplate.find(query, PartitionPerson.class, PartitionPerson.class.getSimpleName());
result = cosmosTemplate.find(query, PartitionPerson.class, PartitionPerson.class.getSimpleName());
assertThat(result.size()).isEqualTo(1);
assertEquals(TEST_PERSON, result.get(0));
}
@Test
public void testFindByIdWithPartition() {
final PartitionPerson partitionPersonById = dbTemplate.findById(TEST_PERSON.getId(),
final PartitionPerson partitionPersonById = cosmosTemplate.findById(TEST_PERSON.getId(),
PartitionPerson.class,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON)));
@ -125,7 +126,7 @@ public class DocumentDbTemplatePartitionIT {
final Criteria criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_ID, Arrays.asList(NOT_EXIST_ID));
final DocumentQuery query = new DocumentQuery(criteria);
final List<PartitionPerson> result = dbTemplate.find(query, PartitionPerson.class,
final List<PartitionPerson> result = cosmosTemplate.find(query, PartitionPerson.class,
PartitionPerson.class.getSimpleName());
assertThat(result.size()).isEqualTo(0);
}
@ -138,9 +139,9 @@ public class DocumentDbTemplatePartitionIT {
null, null);
final String partitionKeyValue = newPerson.getLastName();
dbTemplate.upsert(PartitionPerson.class.getSimpleName(), newPerson, new PartitionKey(partitionKeyValue));
cosmosTemplate.upsert(PartitionPerson.class.getSimpleName(), newPerson, new PartitionKey(partitionKeyValue));
final List<PartitionPerson> result = dbTemplate.findAll(PartitionPerson.class);
final List<PartitionPerson> result = cosmosTemplate.findAll(PartitionPerson.class);
assertThat(result.size()).isEqualTo(2);
@ -153,9 +154,9 @@ public class DocumentDbTemplatePartitionIT {
public void testUpdatePartition() {
final PartitionPerson updated = new PartitionPerson(TEST_PERSON.getId(), UPDATED_FIRST_NAME,
TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(), TEST_PERSON.getShippingAddresses());
dbTemplate.upsert(PartitionPerson.class.getSimpleName(), updated, new PartitionKey(updated.getLastName()));
cosmosTemplate.upsert(PartitionPerson.class.getSimpleName(), updated, new PartitionKey(updated.getLastName()));
final List<PartitionPerson> result = dbTemplate.findAll(PartitionPerson.class);
final List<PartitionPerson> result = cosmosTemplate.findAll(PartitionPerson.class);
final PartitionPerson person = result.stream().filter(
p -> TEST_PERSON.getId().equals(p.getId())).findFirst().get();
@ -165,41 +166,41 @@ public class DocumentDbTemplatePartitionIT {
@Test
public void testDeleteByIdPartition() {
// insert new document with same partition key
dbTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
final List<PartitionPerson> inserted = dbTemplate.findAll(PartitionPerson.class);
final List<PartitionPerson> inserted = cosmosTemplate.findAll(PartitionPerson.class);
assertThat(inserted.size()).isEqualTo(2);
assertThat(inserted.get(0).getLastName()).isEqualTo(TEST_PERSON.getLastName());
assertThat(inserted.get(1).getLastName()).isEqualTo(TEST_PERSON.getLastName());
dbTemplate.deleteById(PartitionPerson.class.getSimpleName(),
cosmosTemplate.deleteById(PartitionPerson.class.getSimpleName(),
TEST_PERSON.getId(), new PartitionKey(TEST_PERSON.getLastName()));
final List<PartitionPerson> result = dbTemplate.findAll(PartitionPerson.class);
final List<PartitionPerson> result = cosmosTemplate.findAll(PartitionPerson.class);
assertThat(result.size()).isEqualTo(1);
assertTrue(result.get(0).equals(TEST_PERSON_2));
}
@Test
public void testCountForPartitionedCollection() {
final long prevCount = dbTemplate.count(collectionName);
final long prevCount = cosmosTemplate.count(collectionName);
assertThat(prevCount).isEqualTo(1);
dbTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
final long newCount = dbTemplate.count(collectionName);
final long newCount = cosmosTemplate.count(collectionName);
assertThat(newCount).isEqualTo(2);
}
@Test
public void testCountForPartitionedCollectionByQuery() {
dbTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName",
Arrays.asList(TEST_PERSON_2.getFirstName()));
final DocumentQuery query = new DocumentQuery(criteria);
final long count = dbTemplate.count(query, PartitionPerson.class, collectionName);
final long count = cosmosTemplate.count(query, PartitionPerson.class, collectionName);
assertThat(count).isEqualTo(1);
}
@ -209,21 +210,21 @@ public class DocumentDbTemplatePartitionIT {
Arrays.asList("non-exist-first-name"));
final DocumentQuery query = new DocumentQuery(criteria);
final long count = dbTemplate.count(query, PartitionPerson.class, collectionName);
final long count = cosmosTemplate.count(query, PartitionPerson.class, collectionName);
assertThat(count).isEqualTo(0);
}
@Test
public void testPartitionedFindAllPageableMultiPages() {
dbTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
final DocumentDbPageRequest pageRequest = new DocumentDbPageRequest(0, PAGE_SIZE_1, null);
final Page<PartitionPerson> page1 = dbTemplate.findAll(pageRequest, PartitionPerson.class, collectionName);
final CosmosPageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_1, null);
final Page<PartitionPerson> page1 = cosmosTemplate.findAll(pageRequest, PartitionPerson.class, collectionName);
assertThat(page1.getContent().size()).isEqualTo(PAGE_SIZE_1);
validateNonLastPage(page1, PAGE_SIZE_1);
final Page<PartitionPerson> page2 = dbTemplate.findAll(page1.getPageable(),
final Page<PartitionPerson> page2 = cosmosTemplate.findAll(page1.getPageable(),
PartitionPerson.class, collectionName);
assertThat(page2.getContent().size()).isEqualTo(1);
validateLastPage(page2, PAGE_SIZE_1);
@ -231,14 +232,14 @@ public class DocumentDbTemplatePartitionIT {
@Test
public void testPartitionedPaginationQuery() {
dbTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName",
Arrays.asList(FIRST_NAME));
final PageRequest pageRequest = new DocumentDbPageRequest(0, PAGE_SIZE_2, null);
final PageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_2, null);
final DocumentQuery query = new DocumentQuery(criteria).with(pageRequest);
final Page<PartitionPerson> page = dbTemplate.paginationQuery(query, PartitionPerson.class, collectionName);
final Page<PartitionPerson> page = cosmosTemplate.paginationQuery(query, PartitionPerson.class, collectionName);
assertThat(page.getContent().size()).isEqualTo(1);
validateLastPage(page, PAGE_SIZE_2);
}

Просмотреть файл

@ -8,19 +8,19 @@ package com.microsoft.azure.spring.data.cosmosdb.core;
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class DocumentDbTemplateUnitTest {
public class CosmosTemplateUnitTest {
@Test(expected = IllegalArgumentException.class)
public void rejectNullDbFactory() {
final DocumentDBConfig dbConfig = DocumentDBConfig.builder("", "", TestConstants.DB_NAME).build();
final CosmosDBConfig dbConfig = CosmosDBConfig.builder("", "", TestConstants.DB_NAME).build();
final CosmosDbFactory cosmosDbFactory = new CosmosDbFactory(dbConfig);
new DocumentDbTemplate(cosmosDbFactory, null, TestConstants.DB_NAME);
new CosmosTemplate(cosmosDbFactory, null, TestConstants.DB_NAME);
}
}

Просмотреть файл

@ -10,14 +10,15 @@ import com.azure.data.cosmos.CosmosKeyCredential;
import com.azure.data.cosmos.PartitionKey;
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.domain.Person;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import io.reactivex.subscribers.TestSubscriber;
import org.junit.After;
import org.junit.Assert;
@ -64,15 +65,15 @@ public class ReactiveCosmosTemplateIT {
TestConstants.NEW_LAST_NAME, TestConstants.HOBBIES, TestConstants.ADDRESSES);
@Value("${cosmosdb.uri}")
private String documentDbUri;
private String cosmosDbUri;
@Value("${cosmosdb.key}")
private String documentDbKey;
private String cosmosDbKey;
@Value("${cosmosdb.secondaryKey}")
private String documentDbSecondaryKey;
private String cosmosDbSecondaryKey;
private static ReactiveCosmosTemplate cosmosTemplate;
private static String containerName;
private static DocumentDbEntityInformation<Person, String> personInfo;
private static CosmosEntityInformation<Person, String> personInfo;
private static CosmosKeyCredential cosmosKeyCredential;
private static boolean initialized;
@ -83,19 +84,19 @@ public class ReactiveCosmosTemplateIT {
@Before
public void setUp() throws ClassNotFoundException {
if (!initialized) {
cosmosKeyCredential = new CosmosKeyCredential(documentDbKey);
final DocumentDBConfig dbConfig = DocumentDBConfig.builder(documentDbUri,
cosmosKeyCredential = new CosmosKeyCredential(cosmosDbKey);
final CosmosDBConfig dbConfig = CosmosDBConfig.builder(cosmosDbUri,
cosmosKeyCredential, DB_NAME).build();
final CosmosDbFactory dbFactory = new CosmosDbFactory(dbConfig);
final DocumentDbMappingContext mappingContext = new DocumentDbMappingContext();
personInfo = new DocumentDbEntityInformation<>(Person.class);
final CosmosMappingContext mappingContext = new CosmosMappingContext();
personInfo = new CosmosEntityInformation<>(Person.class);
containerName = personInfo.getCollectionName();
mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class));
final MappingDocumentDbConverter dbConverter =
new MappingDocumentDbConverter(mappingContext, null);
final MappingCosmosConverter dbConverter =
new MappingCosmosConverter(mappingContext, null);
cosmosTemplate = new ReactiveCosmosTemplate(dbFactory, dbConverter, DB_NAME);
cosmosTemplate.createCollectionIfNotExists(personInfo).block().container();
initialized = true;
@ -107,7 +108,7 @@ public class ReactiveCosmosTemplateIT {
@After
public void cleanup() {
// Reset master key
cosmosKeyCredential.key(documentDbKey);
cosmosKeyCredential.key(cosmosDbKey);
cosmosTemplate.deleteAll(Person.class.getSimpleName(),
personInfo.getPartitionKeyFieldName()).block();
}
@ -122,7 +123,8 @@ public class ReactiveCosmosTemplateIT {
testSubscriber.assertNotComplete();
testSubscriber.assertTerminated();
assertThat(testSubscriber.errors()).hasSize(1);
assertThat(((List) testSubscriber.getEvents().get(1)).get(0)).isInstanceOf(CosmosClientException.class);
assertThat(((List) testSubscriber.getEvents().get(1)).get(0))
.isInstanceOf(CosmosDBAccessException.class);
}
@Test
@ -137,7 +139,7 @@ public class ReactiveCosmosTemplateIT {
@Test
public void testFindByIDBySecondaryKey() {
cosmosKeyCredential.key(documentDbSecondaryKey);
cosmosKeyCredential.key(cosmosDbSecondaryKey);
final Mono<Person> findById = cosmosTemplate.findById(Person.class.getSimpleName(),
TEST_PERSON.getId(),
Person.class);
@ -171,7 +173,7 @@ public class ReactiveCosmosTemplateIT {
@Test
public void testInsertBySecondaryKey() {
cosmosKeyCredential.key(documentDbSecondaryKey);
cosmosKeyCredential.key(cosmosDbSecondaryKey);
StepVerifier.create(cosmosTemplate.insert(TEST_PERSON_3,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3))))
.expectNext(TEST_PERSON_3).verifyComplete();
@ -197,7 +199,7 @@ public class ReactiveCosmosTemplateIT {
@Test
public void testUpsertBySecondaryKey() {
cosmosKeyCredential.key(documentDbSecondaryKey);
cosmosKeyCredential.key(cosmosDbSecondaryKey);
final Person p = TEST_PERSON_2;
final ArrayList<String> hobbies = new ArrayList<>(p.getHobbies());
hobbies.add("more code");
@ -234,7 +236,7 @@ public class ReactiveCosmosTemplateIT {
@Test
public void testDeleteByIdBySecondaryKey() {
cosmosKeyCredential.key(documentDbSecondaryKey);
cosmosKeyCredential.key(cosmosDbSecondaryKey);
cosmosTemplate.insert(TEST_PERSON_4,
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_4))).block();
Flux<Person> flux = cosmosTemplate.findAll(Person.class.getSimpleName(), Person.class);
@ -274,7 +276,7 @@ public class ReactiveCosmosTemplateIT {
@Test
public void testCountBySecondaryKey() {
cosmosKeyCredential.key(documentDbSecondaryKey);
cosmosKeyCredential.key(cosmosDbSecondaryKey);
final Mono<Long> count = cosmosTemplate.count(containerName);
StepVerifier.create(count).expectNext((long) 1).verifyComplete();
}

Просмотреть файл

@ -7,13 +7,13 @@ package com.microsoft.azure.spring.data.cosmosdb.core;
import com.azure.data.cosmos.PartitionKey;
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
import com.microsoft.azure.spring.data.cosmosdb.domain.PartitionPerson;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@ -59,13 +59,13 @@ public class ReactiveCosmosTemplatePartitionIT {
TEST_PERSON.getLastName(), HOBBIES, ADDRESSES);
@Value("${cosmosdb.uri}")
private String documentDbUri;
private String cosmosDbUri;
@Value("${cosmosdb.key}")
private String documentDbKey;
private String cosmosDbKey;
private static ReactiveCosmosTemplate cosmosTemplate;
private static String containerName;
private static DocumentDbEntityInformation<PartitionPerson, String> personInfo;
private static CosmosEntityInformation<PartitionPerson, String> personInfo;
private static boolean initialized;
@ -75,17 +75,19 @@ public class ReactiveCosmosTemplatePartitionIT {
@Before
public void setUp() throws ClassNotFoundException {
if (!initialized) {
final DocumentDBConfig dbConfig = DocumentDBConfig.builder(documentDbUri, documentDbKey, DB_NAME).build();
final CosmosDBConfig dbConfig = CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey,
DB_NAME).build();
final CosmosDbFactory dbFactory = new CosmosDbFactory(dbConfig);
final DocumentDbMappingContext mappingContext = new DocumentDbMappingContext();
personInfo = new DocumentDbEntityInformation<>(PartitionPerson.class);
final CosmosMappingContext mappingContext = new CosmosMappingContext();
personInfo =
new CosmosEntityInformation<>(PartitionPerson.class);
containerName = personInfo.getCollectionName();
mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class));
final MappingDocumentDbConverter dbConverter = new MappingDocumentDbConverter(mappingContext, null);
final MappingCosmosConverter dbConverter = new MappingCosmosConverter(mappingContext,
null);
cosmosTemplate = new ReactiveCosmosTemplate(dbFactory, dbConverter, DB_NAME);
cosmosTemplate.createCollectionIfNotExists(personInfo).block();
@ -96,14 +98,17 @@ public class ReactiveCosmosTemplatePartitionIT {
@After
public void cleanup() {
cosmosTemplate.deleteAll(PartitionPerson.class.getSimpleName(), personInfo.getPartitionKeyFieldName()).block();
cosmosTemplate.deleteAll(PartitionPerson.class.getSimpleName(),
personInfo.getPartitionKeyFieldName()).block();
}
@Test
public void testFindWithPartition() {
final Criteria criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_LAST_NAME, Arrays.asList(LAST_NAME));
final Criteria criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_LAST_NAME,
Arrays.asList(LAST_NAME));
final DocumentQuery query = new DocumentQuery(criteria);
final Flux<PartitionPerson> partitionPersonFlux = cosmosTemplate.find(query, PartitionPerson.class,
final Flux<PartitionPerson> partitionPersonFlux = cosmosTemplate.find(query,
PartitionPerson.class,
PartitionPerson.class.getSimpleName());
StepVerifier.create(partitionPersonFlux).consumeNextWith(actual -> {
Assert.assertThat(actual.getFirstName(), is(equalTo(TEST_PERSON.getFirstName())));
@ -111,6 +116,7 @@ public class ReactiveCosmosTemplatePartitionIT {
}).verifyComplete();
}
@Test
public void testFindByIdWithPartition() {
final Mono<PartitionPerson> partitionPersonMono = cosmosTemplate.findById(TEST_PERSON.getId(),
@ -122,25 +128,28 @@ public class ReactiveCosmosTemplatePartitionIT {
}).verifyComplete();
}
// @Test
// public void testFindByNonExistIdWithPartition() {
//
// }
// @Test
// public void testFindByNonExistIdWithPartition() {
//
// }
@Test
public void testUpsertNewDocumentPartition() {
final String firstName = NEW_FIRST_NAME + "_" + UUID.randomUUID().toString();
final PartitionPerson newPerson = new PartitionPerson(UUID.randomUUID().toString(), firstName, NEW_LAST_NAME,
final PartitionPerson newPerson = new PartitionPerson(UUID.randomUUID().toString(),
firstName, NEW_LAST_NAME,
null, null);
final String partitionKeyValue = newPerson.getLastName();
final Mono<PartitionPerson> upsert = cosmosTemplate.upsert(newPerson, new PartitionKey(partitionKeyValue));
final Mono<PartitionPerson> upsert = cosmosTemplate.upsert(newPerson,
new PartitionKey(partitionKeyValue));
StepVerifier.create(upsert).expectNextCount(1).verifyComplete();
}
@Test
public void testUpdateWithPartition() {
final PartitionPerson updated = new PartitionPerson(TEST_PERSON.getId(), UPDATED_FIRST_NAME,
TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(), TEST_PERSON.getShippingAddresses());
TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(),
TEST_PERSON.getShippingAddresses());
cosmosTemplate.upsert(updated, new PartitionKey(updated.getLastName())).block();
final PartitionPerson person = cosmosTemplate
@ -165,10 +174,24 @@ public class ReactiveCosmosTemplatePartitionIT {
}
@Test
public void testCountForPartitionedCollection() {
StepVerifier.create(cosmosTemplate.count(containerName)).expectNext((long) 1).verifyComplete();
public void testDeleteAll() {
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())).block();
StepVerifier.create(cosmosTemplate.count(containerName)).expectNext((long) 2).verifyComplete();
StepVerifier.create(cosmosTemplate.findAll(PartitionPerson.class)).expectNextCount(2).verifyComplete();
final CosmosEntityInformation<PartitionPerson, String> personInfo =
new CosmosEntityInformation<>(PartitionPerson.class);
cosmosTemplate.deleteAll(containerName, personInfo.getPartitionKeyFieldName()).block();
StepVerifier.create(cosmosTemplate.findAll(PartitionPerson.class))
.expectNextCount(0)
.verifyComplete();
}
@Test
public void testCountForPartitionedCollection() {
StepVerifier.create(cosmosTemplate.count(containerName))
.expectNext((long) 1).verifyComplete();
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())).block();
StepVerifier.create(cosmosTemplate.count(containerName))
.expectNext((long) 2).verifyComplete();
}
@Test
@ -177,7 +200,8 @@ public class ReactiveCosmosTemplatePartitionIT {
final Criteria criteria = Criteria.getInstance(IS_EQUAL, "firstName",
Arrays.asList(TEST_PERSON_2.getFirstName()));
final DocumentQuery query = new DocumentQuery(criteria);
StepVerifier.create(cosmosTemplate.count(query, containerName)).expectNext((long) 1).verifyComplete();
StepVerifier.create(cosmosTemplate.count(query, containerName))
.expectNext((long) 1).verifyComplete();
}
}

Просмотреть файл

@ -8,8 +8,8 @@ package com.microsoft.azure.spring.data.cosmosdb.core.converter;
import com.azure.data.cosmos.CosmosItemProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
import com.microsoft.azure.spring.data.cosmosdb.domain.Address;
import com.microsoft.azure.spring.data.cosmosdb.domain.Memo;
import com.microsoft.azure.spring.data.cosmosdb.domain.Importance;
@ -18,7 +18,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.context.ApplicationContext;
import java.text.ParseException;
@ -28,33 +28,31 @@ import java.util.Date;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(MockitoJUnitRunner.class)
public class MappingDocumentDbConverterUnitTest {
public class MappingCosmosConverterUnitTest {
private static final SimpleDateFormat DATE = new SimpleDateFormat(TestConstants.DATE_FORMAT);
private static final SimpleDateFormat TIMEZONE_DATE = new SimpleDateFormat(TestConstants.DATE_TIMEZONE_FORMAT);
MappingDocumentDbConverter dbConverter;
DocumentDbMappingContext mappingContext;
ObjectMapper objectMapper;
private MappingCosmosConverter mappingCosmosConverter;
@Mock
ApplicationContext applicationContext;
@Before
public void setup() {
mappingContext = new DocumentDbMappingContext();
objectMapper = new ObjectMapper();
final CosmosMappingContext mappingContext = new CosmosMappingContext();
final ObjectMapper objectMapper = new ObjectMapper();
mappingContext.setApplicationContext(applicationContext);
mappingContext.afterPropertiesSet();
mappingContext.getPersistentEntity(Address.class);
dbConverter = new MappingDocumentDbConverter(mappingContext, objectMapper);
mappingCosmosConverter = new MappingCosmosConverter(mappingContext, objectMapper);
}
@Test
public void covertAddressToDocumentCorrectly() {
final Address testAddress = new Address(TestConstants.POSTAL_CODE, TestConstants.CITY, TestConstants.STREET);
final CosmosItemProperties cosmosItemProperties = dbConverter.writeCosmosItemProperties(testAddress);
final CosmosItemProperties cosmosItemProperties = mappingCosmosConverter.writeCosmosItemProperties(testAddress);
assertThat(cosmosItemProperties.id()).isEqualTo(testAddress.getPostalCode());
assertThat(cosmosItemProperties.getString(TestConstants.PROPERTY_CITY)).isEqualTo(testAddress.getCity());
@ -70,7 +68,7 @@ public class MappingDocumentDbConverterUnitTest {
final CosmosItemProperties cosmosItemProperties = new CosmosItemProperties(jsonObject.toString());
cosmosItemProperties.id(TestConstants.POSTAL_CODE);
final Address address = dbConverter.read(Address.class, cosmosItemProperties);
final Address address = mappingCosmosConverter.read(Address.class, cosmosItemProperties);
assertThat(address.getPostalCode()).isEqualTo(TestConstants.POSTAL_CODE);
assertThat(address.getCity()).isEqualTo(TestConstants.CITY);
@ -81,7 +79,7 @@ public class MappingDocumentDbConverterUnitTest {
public void canWritePojoWithDateToDocument() throws ParseException {
final Memo memo = new Memo(TestConstants.ID_1, TestConstants.MESSAGE, DATE.parse(TestConstants.DATE_STRING),
Importance.NORMAL);
final CosmosItemProperties cosmosItemProperties = dbConverter.writeCosmosItemProperties(memo);
final CosmosItemProperties cosmosItemProperties = mappingCosmosConverter.writeCosmosItemProperties(memo);
assertThat(cosmosItemProperties.id()).isEqualTo(memo.getId());
assertThat(cosmosItemProperties.getString(TestConstants.PROPERTY_MESSAGE)).isEqualTo(memo.getMessage());
@ -99,7 +97,7 @@ public class MappingDocumentDbConverterUnitTest {
final CosmosItemProperties cosmosItemProperties = new CosmosItemProperties(jsonObject.toString());
cosmosItemProperties.id(TestConstants.ID_1);
final Memo memo = dbConverter.read(Memo.class, cosmosItemProperties);
final Memo memo = mappingCosmosConverter.read(Memo.class, cosmosItemProperties);
assertThat(cosmosItemProperties.id()).isEqualTo(memo.getId());
assertThat(cosmosItemProperties.getString(TestConstants.PROPERTY_MESSAGE)).isEqualTo(TestConstants.MESSAGE);
assertThat(cosmosItemProperties.getLong(TestConstants.PROPERTY_DATE)).isEqualTo(date);
@ -108,7 +106,7 @@ public class MappingDocumentDbConverterUnitTest {
@Test
public void convertDateValueToMilliSeconds() throws ParseException {
final Date date = TIMEZONE_DATE.parse(TestConstants.DATE_TIMEZONE_STRING);
final long time = (Long) MappingDocumentDbConverter.toDocumentDBValue(date);
final long time = (Long) MappingCosmosConverter.toCosmosDbValue(date);
assertThat(time).isEqualTo(TestConstants.MILLI_SECONDS);
}

Просмотреть файл

@ -12,18 +12,18 @@ import org.springframework.data.util.ClassTypeInformation;
import static org.assertj.core.api.Assertions.assertThat;
public class BasicDocumentDbPersistentEntityUnitTest {
public class BasicCosmosPersistentEntityUnitTest {
@Test
public void testGetCollection() {
final BasicDocumentDbPersistentEntity entity = new BasicDocumentDbPersistentEntity<Person>(
final BasicCosmosPersistentEntity entity = new BasicCosmosPersistentEntity<Person>(
ClassTypeInformation.from(Person.class));
assertThat(entity.getCollection()).isEqualTo("");
}
@Test
public void testGetLanguage() {
final BasicDocumentDbPersistentEntity entity = new BasicDocumentDbPersistentEntity<Person>(
final BasicCosmosPersistentEntity entity = new BasicCosmosPersistentEntity<Person>(
ClassTypeInformation.from(Person.class));
assertThat(entity.getLanguage()).isEqualTo("");
}

Просмотреть файл

@ -12,15 +12,15 @@ import org.springframework.context.ApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
public class DocumentDbMappingContextUnitTest {
public class CosmosMappingContextUnitTest {
@Mock
ApplicationContext context;
@Test
public void mappingContextWithImplicitIdProperty() {
final DocumentDbMappingContext context = new DocumentDbMappingContext();
final BasicDocumentDbPersistentEntity<?> entity = context.getPersistentEntity(ClassWithId.class);
final CosmosMappingContext context = new CosmosMappingContext();
final BasicCosmosPersistentEntity<?> entity = context.getPersistentEntity(ClassWithId.class);
assertThat(entity).isNotNull();
}

Просмотреть файл

@ -55,7 +55,7 @@ public class CriteriaUnitTest {
final Criteria criteria = Criteria.getInstance(CriteriaType.IN, CRITERIA_KEY, values);
final DocumentQuery query = new DocumentQuery(criteria);
new FindQuerySpecGenerator().generate(query);
new FindQuerySpecGenerator().generateCosmos(query);
}
@Test(expected = IllegalQueryException.class)
@ -64,6 +64,6 @@ public class CriteriaUnitTest {
final Criteria criteria = Criteria.getInstance(CriteriaType.IN, CRITERIA_KEY, values);
final DocumentQuery query = new DocumentQuery(criteria);
new FindQuerySpecGenerator().generate(query);
new FindQuerySpecGenerator().generateCosmos(query);
}
}

Просмотреть файл

@ -5,7 +5,7 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.domain;
import com.microsoft.azure.documentdb.IndexingMode;
import com.azure.data.cosmos.IndexingMode;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey;
@ -18,7 +18,7 @@ import java.util.UUID;
@AllArgsConstructor
@NoArgsConstructor
@Document
@DocumentIndexingPolicy(mode = IndexingMode.Lazy)
@DocumentIndexingPolicy(mode = IndexingMode.LAZY)
public class Question {
@Id

Просмотреть файл

@ -5,7 +5,7 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.domain;
import com.microsoft.azure.documentdb.IndexingMode;
import com.azure.data.cosmos.IndexingMode;
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy;
@ -17,7 +17,7 @@ import org.springframework.data.annotation.Id;
@Data
@AllArgsConstructor
@DocumentIndexingPolicy(
mode = IndexingMode.Lazy,
mode = IndexingMode.LAZY,
automatic = TestConstants.INDEXINGPOLICY_AUTOMATIC,
includePaths = {
TestConstants.INCLUDEDPATH_0,

Просмотреть файл

@ -5,10 +5,10 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.performance;
import com.microsoft.azure.spring.data.cosmosdb.config.AbstractDocumentDbConfiguration;
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.config.AbstractCosmosConfiguration;
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
import com.microsoft.azure.spring.data.cosmosdb.performance.utils.Constants;
import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableDocumentDbRepositories;
import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableCosmosRepositories;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -16,16 +16,16 @@ import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource(value = {"classpath:application.properties"})
@EnableDocumentDbRepositories
public class PerfConfiguration extends AbstractDocumentDbConfiguration {
@EnableCosmosRepositories
public class PerfConfiguration extends AbstractCosmosConfiguration {
@Value("${cosmosdb.uri:}")
private String documentDbUri;
private String cosmosDbUri;
@Value("${cosmosdb.key:}")
private String documentDbKey;
private String cosmosDbKey;
@Bean
public DocumentDBConfig getConfig() {
return DocumentDBConfig.builder(documentDbUri, documentDbKey, Constants.PERF_DATABASE_NAME).build();
public CosmosDBConfig getConfig() {
return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, Constants.PERF_DATABASE_NAME).build();
}
}

Просмотреть файл

@ -5,9 +5,10 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.performance;
import com.microsoft.azure.documentdb.DocumentClient;
import com.microsoft.azure.documentdb.DocumentClientException;
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
import com.azure.data.cosmos.CosmosClient;
import com.azure.data.cosmos.CosmosClientException;
import com.azure.data.cosmos.sync.CosmosSyncClient;
import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest;
import com.microsoft.azure.spring.data.cosmosdb.performance.domain.PerfPerson;
import com.microsoft.azure.spring.data.cosmosdb.performance.repository.PerfPersonRepository;
import com.microsoft.azure.spring.data.cosmosdb.performance.service.SdkService;
@ -32,7 +33,11 @@ import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.*;
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.acceptInputListFunc;
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.applyInputListFunc;
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.getSupplier;
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.runConsumerForTimes;
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.runFunctionForTimes;
import static org.assertj.core.api.Assertions.assertThat;
@Slf4j
@ -51,7 +56,10 @@ public class PerformanceCompare {
private float acceptanceDiff;
@Autowired
private DocumentClient documentClient;
private CosmosSyncClient cosmosSyncClient;
@Autowired
private CosmosClient asyncClient;
@Autowired
private PerfPersonRepository repository;
@ -61,14 +69,16 @@ public class PerformanceCompare {
private static PerformanceReport report = new PerformanceReport();
@Before
public void setup() throws DocumentClientException {
public void setup() throws CosmosClientException {
if (!hasInit) {
DatabaseUtils.createDatabase(documentClient, Constants.PERF_DATABASE_NAME);
DatabaseUtils.createCollection(documentClient, Constants.PERF_DATABASE_NAME,
DatabaseUtils.createDatabase(cosmosSyncClient, Constants.PERF_DATABASE_NAME);
DatabaseUtils.createCollection(cosmosSyncClient, Constants.PERF_DATABASE_NAME,
Constants.SPRING_COLLECTION_NAME);
DatabaseUtils.createCollection(documentClient, Constants.PERF_DATABASE_NAME, Constants.SDK_COLLECTION_NAME);
DatabaseUtils.createCollection(cosmosSyncClient,
Constants.PERF_DATABASE_NAME, Constants.SDK_COLLECTION_NAME);
sdkService = new SdkService(documentClient, Constants.PERF_DATABASE_NAME, Constants.SDK_COLLECTION_NAME);
sdkService = new SdkService(cosmosSyncClient, Constants.PERF_DATABASE_NAME,
Constants.SDK_COLLECTION_NAME, asyncClient);
hasInit = true;
}
@ -171,7 +181,7 @@ public class PerformanceCompare {
public void findBySortingTest() {
prepareListData(recurTimes);
final Sort sort = new Sort(Sort.Direction.ASC, "name");
final Sort sort = Sort.by(Sort.Direction.ASC, "name");
final List<Sort> sortList = buildSortList(sort, recurTimes);
final long springCost = applyInputListFunc(sortList, repository::findAll);
@ -248,7 +258,7 @@ public class PerformanceCompare {
}
private void queryTwoPages(int pageSize) {
final Pageable pageable = new DocumentDbPageRequest(0, pageSize, null);
final Pageable pageable = new CosmosPageRequest(0, pageSize, null);
final Page<PerfPerson> page = this.repository.findAll(pageable);
this.repository.findAll(page.getPageable());
}

Просмотреть файл

@ -6,14 +6,14 @@
package com.microsoft.azure.spring.data.cosmosdb.performance.repository;
import com.microsoft.azure.spring.data.cosmosdb.performance.domain.PerfPerson;
import com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository;
import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface PerfPersonRepository extends DocumentDbRepository<PerfPerson, String> {
public interface PerfPersonRepository extends CosmosRepository<PerfPerson, String> {
List<PerfPerson> findAll(Sort sort);
List<PerfPerson> findByName(String name);

Просмотреть файл

@ -5,8 +5,15 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.performance.service;
import com.azure.data.cosmos.CosmosClient;
import com.azure.data.cosmos.CosmosClientException;
import com.azure.data.cosmos.CosmosItemProperties;
import com.azure.data.cosmos.CosmosItemRequestOptions;
import com.azure.data.cosmos.FeedOptions;
import com.azure.data.cosmos.FeedResponse;
import com.azure.data.cosmos.PartitionKey;
import com.azure.data.cosmos.sync.CosmosSyncClient;
import com.google.gson.Gson;
import com.microsoft.azure.documentdb.*;
import com.microsoft.azure.spring.data.cosmosdb.performance.domain.PerfPerson;
import com.microsoft.azure.spring.data.cosmosdb.performance.utils.DatabaseUtils;
import org.assertj.core.util.Lists;
@ -18,34 +25,31 @@ import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.Constants.PERF_DATABASE_NAME;
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.Constants.SDK_COLLECTION_NAME;
public class SdkService {
private static Gson gson = new Gson();
private final DocumentClient documentClient;
private final CosmosSyncClient cosmosSyncClient;
private final String dbName;
private final String collectionName;
private final String collectionLink;
public SdkService(DocumentClient client, String dbName, String collectionName) {
this.documentClient = client;
public SdkService(CosmosSyncClient client, String dbName, String collectionName, CosmosClient asyncClient) {
this.cosmosSyncClient = client;
this.dbName = dbName;
this.collectionName = collectionName;
this.collectionLink = "dbs/" + PERF_DATABASE_NAME + "/colls/" + SDK_COLLECTION_NAME;
}
public PerfPerson save(PerfPerson person) {
try {
final String personJson = gson.toJson(person);
final Document personDoc = new Document(personJson);
final CosmosItemProperties personDoc = new CosmosItemProperties(personJson);
final Document doc = documentClient.createDocument(collectionLink, personDoc,
null, false).getResource();
final CosmosItemProperties doc = cosmosSyncClient.getDatabase(dbName)
.getContainer(collectionName)
.createItem(personDoc)
.properties();
return gson.fromJson(doc.toJson(), PerfPerson.class);
} catch (DocumentClientException e) {
} catch (Exception e) {
throw new IllegalStateException(e); // Runtime exception to fail directly
}
}
@ -60,9 +64,13 @@ public class SdkService {
public void delete(PerfPerson person) {
try {
final String docLink = DatabaseUtils.getDocumentLink(dbName, collectionName, person.getId());
cosmosSyncClient.getDatabase(dbName)
.getContainer(collectionName)
.getItem(person.getId(),
PartitionKey.None)
.delete(new CosmosItemRequestOptions());
documentClient.deleteDocument(docLink, null);
} catch (DocumentClientException e) {
} catch (CosmosClientException e) {
throw new IllegalStateException(e); // Runtime exception to fail directly
}
}
@ -71,9 +79,21 @@ public class SdkService {
personIterable.forEach(person -> delete(person));
}
public Document findById(String id) {
return documentClient.queryDocuments(collectionLink, "SELECT * FROM " + collectionName + " WHERE " +
collectionName + ".id='" + id + "'", new FeedOptions()).getQueryIterator().next();
public CosmosItemProperties findById(String id) {
final Iterator<FeedResponse<CosmosItemProperties>> feedResponseIterator =
cosmosSyncClient.getDatabase(dbName)
.getContainer(collectionName)
.queryItems("SELECT * FROM " + collectionName + " WHERE " +
collectionName + ".id='" + id + "'", new FeedOptions());
CosmosItemProperties itemProperties = null;
if (feedResponseIterator.hasNext()) {
final List<CosmosItemProperties> results = feedResponseIterator.next().results();
if (!results.isEmpty()) {
itemProperties = results.get(0);
}
}
return itemProperties;
}
public List<PerfPerson> findAllById(Iterable<String> ids) {
@ -83,29 +103,39 @@ public class SdkService {
+ idsInList + ")";
final FeedOptions feedOptions = new FeedOptions();
feedOptions.setEnableCrossPartitionQuery(true);
feedOptions.enableCrossPartitionQuery(true);
final List<CosmosItemProperties> docs = null;
final Iterator<FeedResponse<CosmosItemProperties>> feedResponseIterator = cosmosSyncClient.getDatabase(dbName)
.getContainer(collectionName)
.queryItems(sql, feedOptions);
while (feedResponseIterator.hasNext()) {
final FeedResponse<CosmosItemProperties> next = feedResponseIterator.next();
docs.addAll(next.results());
}
final List<Document> docs = documentClient.queryDocuments(collectionLink, sql, feedOptions)
.getQueryIterable().toList();
return fromDocuments(docs);
}
public List<PerfPerson> findAll() {
final List<Document> docs = documentClient.queryDocuments(collectionLink,
"SELECT * FROM " + collectionName, new FeedOptions()).getQueryIterable().toList();
final String sql = "SELECT * FROM " + collectionName;
final List<CosmosItemProperties> docs = getCosmosItemPropertiesList(sql);
return fromDocuments(docs);
}
public boolean deleteAll() {
final List<Document> documents = documentClient.queryDocuments(collectionLink,
"SELECT * FROM " + collectionName, new FeedOptions()).getQueryIterable().toList();
final String sql = "SELECT * FROM " + collectionName;
final List<CosmosItemProperties> documents = getCosmosItemPropertiesList(sql);
documents.forEach(document -> {
try {
documentClient.deleteDocument(document.getSelfLink(), null);
} catch (DocumentClientException e) {
cosmosSyncClient.getDatabase(dbName)
.getContainer(collectionName)
.getItem(document.id(), PartitionKey.None)
.delete(new CosmosItemRequestOptions().partitionKey(PartitionKey.None));
} catch (CosmosClientException e) {
throw new IllegalStateException(e);
}
});
@ -113,63 +143,74 @@ public class SdkService {
return true;
}
private List<CosmosItemProperties> getCosmosItemPropertiesList(String sql) {
final List<CosmosItemProperties> documents = new ArrayList<>();
final Iterator<FeedResponse<CosmosItemProperties>> feedResponseIterator =
cosmosSyncClient.getDatabase(dbName)
.getContainer(collectionName)
.queryItems(sql, new FeedOptions().enableCrossPartitionQuery(true));
while (feedResponseIterator.hasNext()) {
final FeedResponse<CosmosItemProperties> next = feedResponseIterator.next();
documents.addAll(next.results());
}
return documents;
}
public List<PerfPerson> searchDocuments(Sort sort) {
final Sort.Order order = sort.iterator().next(); // Only one Order supported
final List<Document> docs = documentClient.queryDocuments(collectionLink,
"SELECT * FROM " + collectionName + " ORDER BY " + collectionName + "." + order.getProperty()
+ " " + order.getDirection().name(), new FeedOptions()).getQueryIterable().toList();
final String sql = "SELECT * FROM " + collectionName + " ORDER BY " + collectionName + "."
+ order.getProperty() + " " + order.getDirection().name();
final List<CosmosItemProperties> docs = getCosmosItemPropertiesList(sql);
return fromDocuments(docs);
}
public long count() {
final Object result = documentClient.queryDocuments(collectionLink,
"SELECT VALUE COUNT(1) FROM " + collectionName, new FeedOptions())
.getQueryIterable().toList().get(0).getHashMap().get("_aggregate");
final String sql = "SELECT VALUE COUNT(1) FROM " + collectionName;
final Iterator<FeedResponse<CosmosItemProperties>> feedResponseIterator = cosmosSyncClient.getDatabase(dbName)
.getContainer(collectionName)
.queryItems(sql, new FeedOptions());
final Object result = feedResponseIterator.next().results().get(0).get("_aggregate");
return result instanceof Integer ? Long.valueOf((Integer) result) : (Long) result;
}
public List<PerfPerson> findByName(String name) {
final Iterator<Document> result = documentClient.queryDocuments(collectionLink,
"SELECT * FROM " + collectionName + " WHERE " + collectionName + ".name='"
+ name + "'", new FeedOptions()).getQueryIterator();
final String sql = "SELECT * FROM " + collectionName + " WHERE " + collectionName + ".name='"
+ name + "'";
final Iterator<CosmosItemProperties> result = getCosmosItemPropertiesList(sql).iterator();
return fromDocuments(Lists.newArrayList(result));
}
public void queryTwoPages(int pageSize) {
final FeedOptions options = new FeedOptions();
options.setPageSize(pageSize);
options.setRequestContinuation(null);
options.maxItemCount(pageSize);
options.requestContinuation(null);
searchBySize(pageSize, options);
searchBySize(pageSize, options);
}
private List<PerfPerson> searchBySize(int size, FeedOptions options) {
final FeedResponse<Document> q = documentClient
.queryDocuments(collectionLink, "SELECT * FROM " + collectionName, options);
final String sql = "SELECT * FROM " + collectionName;
final Iterator<Document> it = q.getQueryIterator();
final Iterator<CosmosItemProperties> it = getCosmosItemPropertiesList(sql).iterator();
final List<PerfPerson> entities = new ArrayList<>();
int i = 0;
while (it.hasNext() && i++ < size) {
// This convert here is in order to mock data conversion in real use case, in order to compare with
// Spring Data mapping
final Document d = it.next();
final CosmosItemProperties d = it.next();
final PerfPerson entity = gson.fromJson(d.toJson(), PerfPerson.class);
entities.add(entity);
}
options.setRequestContinuation(q.getResponseContinuation());
count(); // Mock same behavior with Spring pageable query, requires total elements count
return entities;
}
private List<PerfPerson> fromDocuments(List<Document> documents) {
private List<PerfPerson> fromDocuments(List<CosmosItemProperties> documents) {
return documents.stream().map(d -> gson.fromJson(d.toJson(), PerfPerson.class))
.collect(Collectors.toList());
}

Просмотреть файл

@ -5,45 +5,49 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.performance.utils;
import com.microsoft.azure.documentdb.*;
import com.azure.data.cosmos.CosmosClientException;
import com.azure.data.cosmos.CosmosContainerProperties;
import com.azure.data.cosmos.IncludedPath;
import com.azure.data.cosmos.IndexingPolicy;
import com.azure.data.cosmos.PartitionKeyDefinition;
import com.azure.data.cosmos.internal.RequestOptions;
import com.azure.data.cosmos.sync.CosmosSyncClient;
import java.util.Collections;
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.ORDER_BY_STRING_PATH;
public class DatabaseUtils {
public static void createDatabase(DocumentClient documentClient, String databaseName)
throws DocumentClientException {
public static void createDatabase(CosmosSyncClient documentClient, String databaseName)
throws CosmosClientException {
try {
documentClient.deleteDatabase("dbs/" + databaseName, null);
} catch (DocumentClientException e) {
// Can use sync api once ready
documentClient.getDatabase(databaseName).delete();
} catch (Exception e) {
// Ignore delete failure
}
final Database myDatabase = new Database();
myDatabase.setId(databaseName);
documentClient.createDatabase(myDatabase, null);
documentClient.createDatabase(databaseName);
}
public static void deleteCollection(DocumentClient documentClient, String databaseName, String collectionName)
throws DocumentClientException{
public static void deleteCollection(CosmosSyncClient documentClient, String databaseName, String collectionName)
throws CosmosClientException{
final RequestOptions requestOptions = new RequestOptions();
requestOptions.setOfferThroughput(1000);
documentClient.deleteCollection("dbs/" + databaseName + "/colls/" + collectionName, requestOptions);
documentClient.getDatabase(databaseName).getContainer(collectionName).delete();
}
public static void createCollection(DocumentClient documentClient, String databaseName, String collectionName)
throws DocumentClientException {
final DocumentCollection myCollection = new DocumentCollection();
myCollection.setId(collectionName);
public static void createCollection(CosmosSyncClient documentClient, String databaseName, String collectionName)
throws CosmosClientException {
final CosmosContainerProperties containerProperties = new CosmosContainerProperties(collectionName,
new PartitionKeyDefinition().paths(Collections.singletonList("/mypk")));
final IndexingPolicy policy = new IndexingPolicy();
policy.setIncludedPaths(Collections.singletonList(new IncludedPath(ORDER_BY_STRING_PATH)));
myCollection.setIndexingPolicy(policy);
containerProperties.indexingPolicy(policy);
documentClient.createCollection("dbs/" + databaseName, myCollection, null);
documentClient.getDatabase(databaseName).createContainer(containerProperties);
}
public static String getDocumentLink(String databaseName, String collectionName, Object documentId) {

Просмотреть файл

@ -5,7 +5,7 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.repository;
import com.microsoft.azure.documentdb.IndexingPolicy;
import com.azure.data.cosmos.IndexingPolicy;
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
import com.microsoft.azure.spring.data.cosmosdb.common.TestUtils;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
@ -13,20 +13,20 @@ import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPol
import com.microsoft.azure.spring.data.cosmosdb.domain.NoDBAnnotationPerson;
import com.microsoft.azure.spring.data.cosmosdb.domain.Role;
import com.microsoft.azure.spring.data.cosmosdb.domain.TimeToLiveSample;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import org.junit.Before;
import org.junit.Test;
import org.springframework.util.Assert;
public class DocumentDBAnnotationUnitTest {
private DocumentDbEntityInformation<NoDBAnnotationPerson, String> personInfo;
private DocumentDbEntityInformation<Role, String> roleInfo;
public class CosmosAnnotationUnitTest {
private CosmosEntityInformation<NoDBAnnotationPerson, String> personInfo;
private CosmosEntityInformation<Role, String> roleInfo;
@Before
public void setUp() {
personInfo = new DocumentDbEntityInformation<>(NoDBAnnotationPerson.class);
roleInfo = new DocumentDbEntityInformation<>(Role.class);
personInfo = new CosmosEntityInformation<>(NoDBAnnotationPerson.class);
roleInfo = new CosmosEntityInformation<>(Role.class);
}
@Test
@ -45,9 +45,9 @@ public class DocumentDBAnnotationUnitTest {
"should be default collection name");
Assert.isTrue(personInfo.getRequestUnit() == TestConstants.DEFAULT_REQUEST_UNIT,
"should be default request unit");
Assert.isTrue(policy.getAutomatic() == TestConstants.DEFAULT_INDEXINGPOLICY_AUTOMATIC,
Assert.isTrue(policy.automatic() == TestConstants.DEFAULT_INDEXINGPOLICY_AUTOMATIC,
"should be default indexing policy automatic");
Assert.isTrue(policy.getIndexingMode() == TestConstants.DEFAULT_INDEXINGPOLICY_MODE,
Assert.isTrue(policy.indexingMode() == TestConstants.DEFAULT_INDEXINGPOLICY_MODE,
"should be default indexing policy mode");
// IncludedPaths and ExcludedPaths
@ -55,8 +55,8 @@ public class DocumentDBAnnotationUnitTest {
// and the paths of policy will never be set from azure service.
// testIndexingPolicyPathsEquals(policy.getIncludedPaths(), TestConstants.DEFAULT_INCLUDEDPATHS);
// testIndexingPolicyPathsEquals(policy.getExcludedPaths(), TestConstants.DEFAULT_EXCLUDEDPATHS);
Assert.isTrue(policy.getIncludedPaths().size() == 0, "default includedpaths size must be 0");
Assert.isTrue(policy.getExcludedPaths().size() == 0, "default excludedpaths size must be 0");
Assert.isTrue(policy.includedPaths().isEmpty(), "default includedpaths size must be 0");
Assert.isTrue(policy.excludedPaths().isEmpty(), "default excludedpaths size must be 0");
}
@Test
@ -74,14 +74,14 @@ public class DocumentDBAnnotationUnitTest {
"should be Role(class) collection name");
Assert.isTrue(roleInfo.getRequestUnit() == TestConstants.REQUEST_UNIT,
"should be Role(class) request unit");
Assert.isTrue(policy.getAutomatic() == TestConstants.INDEXINGPOLICY_AUTOMATIC,
Assert.isTrue(policy.automatic() == TestConstants.INDEXINGPOLICY_AUTOMATIC,
"should be Role(class) indexing policy automatic");
Assert.isTrue(policy.getIndexingMode() == TestConstants.INDEXINGPOLICY_MODE,
Assert.isTrue(policy.indexingMode() == TestConstants.INDEXINGPOLICY_MODE,
"should be Role(class) indexing policy mode");
// IncludedPaths and ExcludedPaths
TestUtils.testIndexingPolicyPathsEquals(policy.getIncludedPaths(), TestConstants.INCLUDEDPATHS);
TestUtils.testIndexingPolicyPathsEquals(policy.getExcludedPaths(), TestConstants.EXCLUDEDPATHS);
TestUtils.testIndexingPolicyPathsEquals(policy.includedPaths(), TestConstants.INCLUDEDPATHS);
TestUtils.testIndexingPolicyPathsEquals(policy.excludedPaths(), TestConstants.EXCLUDEDPATHS);
}
@Test
@ -94,8 +94,8 @@ public class DocumentDBAnnotationUnitTest {
@Test
public void testDocumentAnnotationTimeToLive() {
final DocumentDbEntityInformation<TimeToLiveSample, String> info =
new DocumentDbEntityInformation<>(TimeToLiveSample.class);
final CosmosEntityInformation<TimeToLiveSample, String> info =
new CosmosEntityInformation<>(TimeToLiveSample.class);
final Integer timeToLive = info.getTimeToLive();
Assert.notNull(timeToLive, "timeToLive should not be null");

Просмотреть файл

@ -5,10 +5,10 @@
*/
package com.microsoft.azure.spring.data.cosmosdb.repository;
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.domain.Person;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.SimpleDocumentDbRepository;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.SimpleCosmosRepository;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -16,17 +16,17 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class SimpleDocumentDbRepositoryIllegalTest {
private SimpleDocumentDbRepository<Person, String> repository;
public class SimpleCosmosRepositoryIllegalTest {
private SimpleCosmosRepository<Person, String> repository;
@Mock
DocumentDbOperations dbOperations;
CosmosOperations dbOperations;
@Mock
DocumentDbEntityInformation<Person, String> entityInformation;
CosmosEntityInformation<Person, String> entityInformation;
@Before
public void setUp() {
repository = new SimpleDocumentDbRepository<>(entityInformation, dbOperations);
repository = new SimpleCosmosRepository<>(entityInformation, dbOperations);
}
@Test(expected = IllegalArgumentException.class)

Просмотреть файл

@ -7,11 +7,11 @@
package com.microsoft.azure.spring.data.cosmosdb.repository;
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
import com.microsoft.azure.spring.data.cosmosdb.domain.Address;
import com.microsoft.azure.spring.data.cosmosdb.domain.Person;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.SimpleDocumentDbRepository;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
import com.microsoft.azure.spring.data.cosmosdb.repository.support.SimpleCosmosRepository;
import org.assertj.core.util.Lists;
import org.junit.Before;
import org.junit.Rule;
@ -26,11 +26,11 @@ import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class SimpleDocumentDbRepositoryUnitTest {
public class SimpleCosmosRepositoryUnitTest {
private static final Person TEST_PERSON =
new Person(TestConstants.ID_1, TestConstants.FIRST_NAME, TestConstants.LAST_NAME,
TestConstants.HOBBIES, TestConstants.ADDRESSES);
@ -38,11 +38,11 @@ public class SimpleDocumentDbRepositoryUnitTest {
private static final String PARTITION_VALUE_REQUIRED_MSG =
"PartitionKey value must be supplied for this operation.";
SimpleDocumentDbRepository<Person, String> repository;
private SimpleCosmosRepository<Person, String> repository;
@Mock
DocumentDbOperations dbOperations;
CosmosOperations cosmosOperations;
@Mock
DocumentDbEntityInformation<Person, String> entityInformation;
CosmosEntityInformation<Person, String> entityInformation;
@Rule
public ExpectedException expectedException = ExpectedException.none();
@ -51,9 +51,9 @@ public class SimpleDocumentDbRepositoryUnitTest {
public void setUp() {
when(entityInformation.getJavaType()).thenReturn(Person.class);
when(entityInformation.getCollectionName()).thenReturn(Person.class.getSimpleName());
when(dbOperations.findAll(anyString(), any())).thenReturn(Arrays.asList(TEST_PERSON));
when(cosmosOperations.findAll(anyString(), any())).thenReturn(Arrays.asList(TEST_PERSON));
repository = new SimpleDocumentDbRepository<>(entityInformation, dbOperations);
repository = new SimpleCosmosRepository<>(entityInformation, cosmosOperations);
}
@Test
@ -67,7 +67,7 @@ public class SimpleDocumentDbRepositoryUnitTest {
@Test
public void testFindOne() {
when(dbOperations.findById(anyString(), anyString(), any())).thenReturn(TEST_PERSON);
when(cosmosOperations.findById(anyString(), anyString(), any())).thenReturn(TEST_PERSON);
repository.save(TEST_PERSON);
@ -82,7 +82,7 @@ public class SimpleDocumentDbRepositoryUnitTest {
repository.save(TEST_PERSON);
when(dbOperations.findById(anyString(), anyString(), any()))
when(cosmosOperations.findById(anyString(), anyString(), any()))
.thenThrow(new UnsupportedOperationException(PARTITION_VALUE_REQUIRED_MSG));
final Person result = repository.findById(TEST_PERSON.getId()).get();
@ -98,7 +98,7 @@ public class SimpleDocumentDbRepositoryUnitTest {
TestConstants.UPDATED_HOBBIES, updatedAddress);
repository.save(updatedPerson);
when(dbOperations.findById(anyString(), anyString(), any())).thenReturn(updatedPerson);
when(cosmosOperations.findById(anyString(), anyString(), any())).thenReturn(updatedPerson);
final Person result = repository.findById(TEST_PERSON.getId()).get();
assertEquals(updatedPerson, result);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше