* Added auto create collection annotation field

* Fixed find by id APIs to return empty optional on not found
This commit is contained in:
Kushagra Thapar 2019-12-26 16:46:49 -08:00 коммит произвёл GitHub
Родитель 672876f3da
Коммит 6ea8892b5c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 84 добавлений и 13 удалений

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

@ -47,7 +47,7 @@
<spring.springframework.version>5.2.0.RELEASE</spring.springframework.version>
<spring.data.version>2.2.0.RELEASE</spring.data.version>
<fasterxml.jackson.version>2.9.5</fasterxml.jackson.version>
<fasterxml.jackson.version>2.10.0</fasterxml.jackson.version>
<mockito.core.version>2.8.9</mockito.core.version>
<powermock.version>1.7.1</powermock.version>
@ -58,7 +58,7 @@
<gson.version>2.8.4</gson.version>
<project.reactor.test.version>3.3.0.RELEASE</project.reactor.test.version>
<azure.cosmos.version>3.4.0</azure.cosmos.version>
<azure.cosmos.version>3.5.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>

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

@ -18,6 +18,7 @@ public class Constants {
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 boolean DEFAULT_AUTO_CREATE_COLLECTION = true;
public static final String ID_PROPERTY_NAME = "id";

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

@ -9,6 +9,7 @@ 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.CosmosClientException;
import com.azure.data.cosmos.CosmosContainerProperties;
import com.azure.data.cosmos.CosmosContainerResponse;
import com.azure.data.cosmos.CosmosItemProperties;
@ -18,6 +19,7 @@ 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.azure.data.cosmos.internal.HttpConstants;
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.MappingCosmosConverter;
@ -147,7 +149,15 @@ public class CosmosTemplate implements CosmosOperations, ApplicationContextAware
return Mono.justOrEmpty(toDomainObject(entityClass,
cosmosItemResponse.properties()));
})
.onErrorResume(Mono::error)
.onErrorResume(e -> {
if (e instanceof CosmosClientException) {
final CosmosClientException cosmosClientException = (CosmosClientException) e;
if (cosmosClientException.statusCode() == HttpConstants.StatusCodes.NOTFOUND) {
return Mono.empty();
}
}
return Mono.error(e);
})
.block();
} catch (Exception e) {
@ -179,7 +189,15 @@ public class CosmosTemplate implements CosmosOperations, ApplicationContextAware
.map(cosmosItem -> mappingCosmosConverter.read(domainClass, cosmosItem))
.findFirst());
})
.onErrorResume(Mono::error)
.onErrorResume(e -> {
if (e instanceof CosmosClientException) {
final CosmosClientException cosmosClientException = (CosmosClientException) e;
if (cosmosClientException.statusCode() == HttpConstants.StatusCodes.NOTFOUND) {
return Mono.empty();
}
}
return Mono.error(e);
})
.blockFirst();
} catch (Exception e) {

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

@ -21,4 +21,6 @@ public @interface Document {
String ru() default Constants.DEFAULT_REQUEST_UNIT;
int timeToLive() default Constants.DEFAULT_TIME_TO_LIVE;
boolean autoCreateCollection() default Constants.DEFAULT_AUTO_CREATE_COLLECTION;
}

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

@ -40,6 +40,7 @@ public class CosmosEntityInformation<T, ID> extends AbstractEntityInformation<T,
private Integer timeToLive;
private IndexingPolicy indexingPolicy;
private boolean isVersioned;
private boolean autoCreateCollection;
public CosmosEntityInformation(Class<T> domainClass) {
super(domainClass);
@ -57,6 +58,7 @@ public class CosmosEntityInformation<T, ID> extends AbstractEntityInformation<T,
this.timeToLive = getTimeToLive(domainClass);
this.indexingPolicy = getIndexingPolicy(domainClass);
this.isVersioned = getIsVersioned(domainClass);
this.autoCreateCollection = getIsAutoCreateCollection(domainClass);
}
@SuppressWarnings("unchecked")
@ -107,6 +109,10 @@ public class CosmosEntityInformation<T, ID> extends AbstractEntityInformation<T,
return partitionKeyField == null ? null : (String) ReflectionUtils.getField(partitionKeyField, entity);
}
public boolean isAutoCreateCollection() {
return autoCreateCollection;
}
private IndexingPolicy getIndexingPolicy(Class<?> domainClass) {
final IndexingPolicy policy = new IndexingPolicy();
@ -255,5 +261,16 @@ public class CosmosEntityInformation<T, ID> extends AbstractEntityInformation<T,
&& findField.isAnnotationPresent(Version.class);
}
private boolean getIsAutoCreateCollection(Class<T> domainClass) {
final Document annotation = domainClass.getAnnotation(Document.class);
boolean autoCreateCollection = Constants.DEFAULT_AUTO_CREATE_COLLECTION;
if (annotation != null) {
autoCreateCollection = annotation.autoCreateCollection();
}
return autoCreateCollection;
}
}

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

@ -36,16 +36,20 @@ public class SimpleCosmosRepository<T, ID extends Serializable> implements Cosmo
this.operation = applicationContext.getBean(CosmosOperations.class);
this.information = metadata;
if (this.information.isAutoCreateCollection()) {
createCollectionIfNotExists();
}
}
public SimpleCosmosRepository(CosmosEntityInformation<T, ID> metadata,
CosmosOperations dbOperations) {
this.operation = dbOperations;
this.information = metadata;
if (this.information.isAutoCreateCollection()) {
createCollectionIfNotExists();
}
}
private CosmosContainerProperties createCollectionIfNotExists() {
return this.operation.createCollectionIfNotExists(this.information);

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

@ -28,7 +28,9 @@ import org.springframework.data.annotation.Id;
TestConstants.EXCLUDEDPATH_0,
TestConstants.EXCLUDEDPATH_1,
})
@Document(collection = TestConstants.ROLE_COLLECTION_NAME, ru = TestConstants.REQUEST_UNIT_STRING)
@Document(collection = TestConstants.ROLE_COLLECTION_NAME,
ru = TestConstants.REQUEST_UNIT_STRING,
autoCreateCollection = false)
public class Role {
@Id
String id;

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

@ -84,6 +84,15 @@ public class CosmosAnnotationUnitTest {
TestUtils.testIndexingPolicyPathsEquals(policy.excludedPaths(), TestConstants.EXCLUDEDPATHS);
}
@Test
public void testAutoCreateCollectionAnnotation() {
final boolean autoCreateCollectionRoleInfo = roleInfo.isAutoCreateCollection();
final boolean autoCreateCollectionPersonInfo = personInfo.isAutoCreateCollection();
Assert.isTrue(!autoCreateCollectionRoleInfo, "autoCreateCollection in role should be false");
Assert.isTrue(autoCreateCollectionPersonInfo, "autoCreateCollection in person should be true");
}
@Test
public void testDefaultDocumentAnnotationTimeToLive() {
final Integer timeToLive = personInfo.getTimeToLive();

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

@ -166,12 +166,12 @@ public class AddressRepositoryIT {
assertThat(result.get(0).getCity()).isNotEqualTo(TEST_ADDRESS1_PARTITION1.getCity());
}
@Test(expected = CosmosDBAccessException.class)
@Test
public void testDeleteByIdAndPartitionKey() {
final long count = repository.count();
assertThat(count).isEqualTo(4);
final Optional<Address> addressById = repository.findById(TEST_ADDRESS1_PARTITION1.getPostalCode(),
Optional<Address> addressById = repository.findById(TEST_ADDRESS1_PARTITION1.getPostalCode(),
new PartitionKey(TEST_ADDRESS1_PARTITION1.getCity()));
assertThat(addressById.isPresent()).isTrue();
@ -181,8 +181,10 @@ public class AddressRepositoryIT {
final List<Address> result = TestUtils.toList(repository.findAll());
assertThat(result.size()).isEqualTo(3);
repository.findById(TEST_ADDRESS1_PARTITION1.getPostalCode(),
addressById = repository.findById(TEST_ADDRESS1_PARTITION1.getPostalCode(),
new PartitionKey(TEST_ADDRESS1_PARTITION1.getCity()));
assertThat(addressById.isPresent()).isFalse();
}
@Test

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

@ -160,7 +160,7 @@ public class ContactRepositoryIT {
@Ignore // TODO(kuthapar): v3 doesn't support creation of items without id.
public void testNullIdContact() {
final Contact nullIdContact = new Contact(null, "testTitile");
final Contact savedContact = this.repository.save(nullIdContact);
final Contact savedContact = repository.save(nullIdContact);
Assert.assertNotNull(savedContact.getLogicId());
Assert.assertEquals(nullIdContact.getTitle(), savedContact.getTitle());
@ -168,10 +168,17 @@ public class ContactRepositoryIT {
@Test
public void testFindById() {
final Optional<Contact> optional = this.repository.findById(TEST_CONTACT.getLogicId());
final Optional<Contact> optional = repository.findById(TEST_CONTACT.getLogicId());
Assert.assertTrue(optional.isPresent());
Assert.assertEquals(TEST_CONTACT, optional.get());
Assert.assertFalse(this.repository.findById("").isPresent());
Assert.assertFalse(repository.findById("").isPresent());
}
@Test
public void testFindByIdNotFound() {
final Optional<Contact> optional = repository.findById("unknown-id");
Assert.assertFalse(optional.isPresent());
}
}

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

@ -358,6 +358,15 @@ public class ProjectRepositoryIT {
Assert.assertEquals(project.get(), PROJECT_0);
}
@Test
public void findByIdWithPartitionKeyNotFound() {
final Optional<Project> project = repository.findById("unknown-id",
new PartitionKey("unknown-partition-key"));
Assert.assertFalse(project.isPresent());
}
@Test
public void testFindByIn() {
List<Project> projects = repository.findByCreatorIn(Collections.singleton(FAKE_CREATOR));