Scope and collection API for template. (#1133)
Scope and Collection API for template. Closes #963. Original pull request: #1071.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
* Copyright 2012-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,6 +31,7 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
@@ -68,6 +69,7 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests {
|
||||
couchbaseTemplate.removeByQuery(User.class).all();
|
||||
couchbaseTemplate.removeByQuery(UserAnnotated.class).all();
|
||||
couchbaseTemplate.removeByQuery(UserAnnotated2.class).all();
|
||||
couchbaseTemplate.removeByQuery(UserAnnotated3.class).all();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -93,12 +95,12 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests {
|
||||
@Test
|
||||
void withDurability()
|
||||
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
Class clazz = User.class; // for now, just User.class. There is no Durability annotation.
|
||||
Class<?> clazz = User.class; // for now, just User.class. There is no Durability annotation.
|
||||
// insert, replace, upsert
|
||||
for (OneAndAllEntity<User> operator : new OneAndAllEntity[] { couchbaseTemplate.insertById(clazz),
|
||||
couchbaseTemplate.replaceById(clazz), couchbaseTemplate.upsertById(clazz) }) {
|
||||
// create an entity of type clazz
|
||||
Constructor cons = clazz.getConstructor(String.class, String.class, String.class);
|
||||
Constructor<?> cons = clazz.getConstructor(String.class, String.class, String.class);
|
||||
User user = (User) cons.newInstance("" + operator.getClass().getSimpleName() + "_" + clazz.getSimpleName(),
|
||||
"firstname", "lastname");
|
||||
|
||||
@@ -112,7 +114,22 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests {
|
||||
couchbaseTemplate.insertById(User.class).one(user);
|
||||
}
|
||||
// call to insert/replace/update
|
||||
User returned = (User) operator.one(user);
|
||||
User returned = null;
|
||||
|
||||
// occasionally gives "reactor.core.Exceptions$OverflowException: Could not emit value due to lack of requests"
|
||||
for (int i = 1; i != 5; i++) {
|
||||
try {
|
||||
returned = (User) operator.one(user);
|
||||
break;
|
||||
} catch (Exception ofe) {
|
||||
System.out.println(""+i+" caught: "+ofe);
|
||||
couchbaseTemplate.removeByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all();
|
||||
if (i == 4) {
|
||||
throw ofe;
|
||||
}
|
||||
sleepSecs(1);
|
||||
}
|
||||
}
|
||||
assertEquals(user, returned);
|
||||
User found = couchbaseTemplate.findById(User.class).one(user.getId());
|
||||
assertEquals(user, found);
|
||||
@@ -210,8 +227,6 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests {
|
||||
{
|
||||
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
|
||||
User modified = couchbaseTemplate.upsertById(User.class).one(user);
|
||||
System.out.println(reactiveCouchbaseTemplate.support().getCas(user));
|
||||
System.out.println(reactiveCouchbaseTemplate.support().getCas(modified));
|
||||
assertEquals(user, modified);
|
||||
|
||||
// careful now - user and modified are the same object. The object has the new cas (@Version version)
|
||||
@@ -236,8 +251,23 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests {
|
||||
@Test
|
||||
void insertByIdwithDurability() {
|
||||
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
|
||||
User inserted = couchbaseTemplate.insertById(User.class).withDurability(PersistTo.ACTIVE, ReplicateTo.NONE)
|
||||
.one(user);
|
||||
User inserted = null;
|
||||
|
||||
// occasionally gives "reactor.core.Exceptions$OverflowException: Could not emit value due to lack of requests"
|
||||
for (int i = 1; i != 5; i++) {
|
||||
try {
|
||||
inserted = couchbaseTemplate.insertById(User.class).withDurability(PersistTo.ACTIVE, ReplicateTo.NONE)
|
||||
.one(user);
|
||||
break;
|
||||
} catch (Exception ofe) {
|
||||
System.out.println(""+i+" caught: "+ofe);
|
||||
couchbaseTemplate.removeByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all();
|
||||
if (i == 4) {
|
||||
throw ofe;
|
||||
}
|
||||
sleepSecs(1);
|
||||
}
|
||||
}
|
||||
assertEquals(user, inserted);
|
||||
assertThrows(DuplicateKeyException.class, () -> couchbaseTemplate.insertById(User.class).one(user));
|
||||
}
|
||||
|
||||
@@ -19,8 +19,10 @@ package org.springframework.data.couchbase.core;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Arrays;
|
||||
@@ -32,6 +34,7 @@ import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.couchbase.core.query.Query;
|
||||
import org.springframework.data.couchbase.core.query.QueryCriteria;
|
||||
@@ -46,30 +49,42 @@ import org.springframework.data.couchbase.domain.UserSubmission;
|
||||
import org.springframework.data.couchbase.domain.UserSubmissionProjected;
|
||||
import org.springframework.data.couchbase.domain.time.AuditingDateTimeProvider;
|
||||
import org.springframework.data.couchbase.util.Capabilities;
|
||||
import org.springframework.data.couchbase.util.ClusterAwareIntegrationTests;
|
||||
import org.springframework.data.couchbase.util.ClusterType;
|
||||
import org.springframework.data.couchbase.util.CollectionAwareIntegrationTests;
|
||||
import org.springframework.data.couchbase.util.IgnoreWhen;
|
||||
|
||||
import com.couchbase.client.core.error.AmbiguousTimeoutException;
|
||||
import com.couchbase.client.core.error.UnambiguousTimeoutException;
|
||||
import com.couchbase.client.java.analytics.AnalyticsOptions;
|
||||
import com.couchbase.client.java.kv.ExistsOptions;
|
||||
import com.couchbase.client.java.kv.GetAnyReplicaOptions;
|
||||
import com.couchbase.client.java.kv.GetOptions;
|
||||
import com.couchbase.client.java.kv.InsertOptions;
|
||||
import com.couchbase.client.java.kv.RemoveOptions;
|
||||
import com.couchbase.client.java.kv.ReplaceOptions;
|
||||
import com.couchbase.client.java.kv.UpsertOptions;
|
||||
import com.couchbase.client.java.query.QueryOptions;
|
||||
import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
|
||||
/**
|
||||
* Query tests Theses tests rely on a cb server running This class tests collection support with
|
||||
* inCollection(collection) It should be identical to CouchbaseTemplateQueryIntegrationTests except for the setup and
|
||||
* the inCollection(collectionName) calls. Testing without collections could also be done by this class simply by using
|
||||
* scopeName = null and collectionName = null (except for inCollection() checks that the collectionName is not null)
|
||||
* inCollection(collection), inScope(scope) and withOptions(options). Testing without collections could also be done by
|
||||
* this class simply by using scopeName = null and collectionName = null
|
||||
*
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
@IgnoreWhen(missesCapabilities = { Capabilities.QUERY, Capabilities.COLLECTIONS }, clusterTypes = ClusterType.MOCKED)
|
||||
class CouchbaseTemplateQueryCollectionIntegrationTests extends CollectionAwareIntegrationTests {
|
||||
|
||||
Airport vie = new Airport("airports::vie", "vie", "loww");
|
||||
|
||||
@BeforeAll
|
||||
public static void beforeAll() {
|
||||
// first call the super method
|
||||
callSuperBeforeAll(new Object() {});
|
||||
// then do processing for this class
|
||||
// collectionName = null;
|
||||
// scopeName = null;
|
||||
// no-op
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
@@ -87,15 +102,26 @@ class CouchbaseTemplateQueryCollectionIntegrationTests extends CollectionAwareIn
|
||||
super.beforeEach();
|
||||
// then do processing for this class
|
||||
couchbaseTemplate.removeByQuery(User.class).inCollection(collectionName).all();
|
||||
couchbaseTemplate.findByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.inCollection(collectionName).all();
|
||||
couchbaseTemplate.removeByQuery(Airport.class).inScope(scopeName).inCollection(collectionName).all();
|
||||
couchbaseTemplate.findByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).inScope(scopeName)
|
||||
.inCollection(collectionName).all();
|
||||
couchbaseTemplate.removeByQuery(Airport.class).inScope(otherScope).inCollection(otherCollection).all();
|
||||
couchbaseTemplate.findByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).inScope(otherScope)
|
||||
.inCollection(otherCollection).all();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@Override
|
||||
public void afterEach() {
|
||||
// first call the super method
|
||||
// first do processing for this class
|
||||
couchbaseTemplate.removeByQuery(User.class).inCollection(collectionName).all();
|
||||
// query with REQUEST_PLUS to ensure that the remove has completed.
|
||||
couchbaseTemplate.findByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.inCollection(collectionName).all();
|
||||
// then call the super method
|
||||
super.afterEach();
|
||||
// then do processing for this class
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -200,6 +226,9 @@ class CouchbaseTemplateQueryCollectionIntegrationTests extends CollectionAwareIn
|
||||
.matching(specialUsers).all().collectList().block();
|
||||
assertEquals(1, foundUsersReactive.size());
|
||||
|
||||
couchbaseTemplate.removeByQuery(UserSubmission.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all();
|
||||
couchbaseTemplate.removeByQuery(UserSubmission.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -207,16 +236,20 @@ class CouchbaseTemplateQueryCollectionIntegrationTests extends CollectionAwareIn
|
||||
User user1 = new User(UUID.randomUUID().toString(), "user1", "user1");
|
||||
User user2 = new User(UUID.randomUUID().toString(), "user2", "user2");
|
||||
|
||||
couchbaseTemplate.upsertById(User.class).inCollection(collectionName).all(Arrays.asList(user1, user2));
|
||||
couchbaseTemplate.upsertById(User.class).inScope(scopeName).inCollection(collectionName)
|
||||
.all(Arrays.asList(user1, user2));
|
||||
|
||||
assertTrue(couchbaseTemplate.existsById().inCollection(collectionName).one(user1.getId()));
|
||||
assertTrue(couchbaseTemplate.existsById().inCollection(collectionName).one(user2.getId()));
|
||||
assertTrue(couchbaseTemplate.existsById().inScope(scopeName).inCollection(collectionName).one(user1.getId()));
|
||||
assertTrue(couchbaseTemplate.existsById().inScope(scopeName).inCollection(collectionName).one(user2.getId()));
|
||||
|
||||
couchbaseTemplate.removeByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.inCollection(collectionName).all();
|
||||
List<RemoveResult> result = couchbaseTemplate.removeByQuery(User.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).all();
|
||||
assertEquals(2, result.size(), "should have deleted user1 and user2");
|
||||
|
||||
assertNull(couchbaseTemplate.findById(User.class).inCollection(collectionName).one(user1.getId()));
|
||||
assertNull(couchbaseTemplate.findById(User.class).inCollection(collectionName).one(user2.getId()));
|
||||
assertNull(
|
||||
couchbaseTemplate.findById(User.class).inScope(scopeName).inCollection(collectionName).one(user1.getId()));
|
||||
assertNull(
|
||||
couchbaseTemplate.findById(User.class).inScope(scopeName).inCollection(collectionName).one(user2.getId()));
|
||||
|
||||
}
|
||||
|
||||
@@ -315,7 +348,7 @@ class CouchbaseTemplateQueryCollectionIntegrationTests extends CollectionAwareIn
|
||||
|
||||
// count( distinct icao )
|
||||
// not currently possible to have multiple fields in COUNT(DISTINCT field1, field2, ... ) due to MB43475
|
||||
long count1 = reactiveCouchbaseTemplate.findByQuery(Airport.class).distinct(new String[] { "icao" })
|
||||
Long count1 = reactiveCouchbaseTemplate.findByQuery(Airport.class).distinct(new String[] { "icao" })
|
||||
.as(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).count()
|
||||
.block();
|
||||
assertEquals(2, count1);
|
||||
@@ -336,4 +369,387 @@ class CouchbaseTemplateQueryCollectionIntegrationTests extends CollectionAwareIn
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find . -name 'Exec*OperationSupport.java'|awk -F/ '{print $NF}'|sort| awk -F. '{print "* ", NR, ")",$1, ""}'<br>
|
||||
* 1) ExecutableExistsByIdOperationSupport <br>
|
||||
* 2) ExecutableFindByAnalyticsOperationSupport <br>
|
||||
* 3) ExecutableFindByIdOperationSupport <br>
|
||||
* 4) ExecutableFindByQueryOperationSupport <br>
|
||||
* 5) ExecutableFindFromReplicasByIdOperationSupport <br>
|
||||
* 6) ExecutableInsertByIdOperationSupport <br>
|
||||
* 7) ExecutableRemoveByIdOperationSupport <br>
|
||||
* 8) ExecutableRemoveByQueryOperationSupport <br>
|
||||
* 9) ExecutableReplaceByIdOperationSupport <br>
|
||||
* 10)ExecutableUpsertByIdOperationSupport <br>
|
||||
*/
|
||||
@Test
|
||||
public void existsById() { // 1
|
||||
GetOptions options = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
ExistsOptions existsOptions = ExistsOptions.existsOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.one(vie);
|
||||
try {
|
||||
Boolean exists = couchbaseTemplate.existsById().inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(existsOptions).one(saved.getId());
|
||||
assertTrue(exists, "Airport should exist: " + saved.getId());
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // needs analytics data set
|
||||
public void findByAnalytics() { // 2
|
||||
AnalyticsOptions options = AnalyticsOptions.analyticsOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.one(vie);
|
||||
try {
|
||||
List<Airport> found = couchbaseTemplate.findByAnalytics(Airport.class).inScope(scopeName)
|
||||
.inCollection(collectionName).withOptions(options).all();
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findById() { // 3
|
||||
GetOptions options = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.one(vie);
|
||||
try {
|
||||
Airport found = couchbaseTemplate.findById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).one(saved.getId());
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByQuery() { // 4
|
||||
QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.one(vie);
|
||||
try {
|
||||
List<Airport> found = couchbaseTemplate.findByQuery(Airport.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).all();
|
||||
assertEquals(saved.getId(), found.get(0).getId());
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findFromReplicasById() { // 5
|
||||
GetAnyReplicaOptions options = GetAnyReplicaOptions.getAnyReplicaOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.one(vie);
|
||||
try {
|
||||
Airport found = couchbaseTemplate.findFromReplicasById(Airport.class).inScope(scopeName)
|
||||
.inCollection(collectionName).withOptions(options).any(saved.getId());
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertById() { // 6
|
||||
InsertOptions options = InsertOptions.insertOptions().timeout(Duration.ofSeconds(10));
|
||||
GetOptions getOptions = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).one(vie.withId(UUID.randomUUID().toString()));
|
||||
try {
|
||||
Airport found = couchbaseTemplate.findById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(getOptions).one(saved.getId());
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeById() { // 7
|
||||
RemoveOptions options = RemoveOptions.removeOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.one(vie);
|
||||
RemoveResult removeResult = couchbaseTemplate.removeById().inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).one(saved.getId());
|
||||
assertEquals(saved.getId(), removeResult.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeByQuery() { // 8
|
||||
QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.one(vie);
|
||||
List<RemoveResult> removeResults = couchbaseTemplate.removeByQuery(Airport.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).matching(Query.query(QueryCriteria.where("iata").is(vie.getIata()))).all();
|
||||
assertEquals(saved.getId(), removeResults.get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceById() { // 9
|
||||
InsertOptions insertOptions = InsertOptions.insertOptions().timeout(Duration.ofSeconds(10));
|
||||
ReplaceOptions options = ReplaceOptions.replaceOptions().timeout(Duration.ofSeconds(10));
|
||||
GetOptions getOptions = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(insertOptions).one(vie);
|
||||
Airport replaced = couchbaseTemplate.replaceById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).one(vie.withIcao("newIcao"));
|
||||
try {
|
||||
Airport found = couchbaseTemplate.findById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(getOptions).one(saved.getId());
|
||||
assertEquals(replaced, found);
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upsertById() { // 10
|
||||
UpsertOptions options = UpsertOptions.upsertOptions().timeout(Duration.ofSeconds(10));
|
||||
GetOptions getOptions = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
|
||||
Airport saved = couchbaseTemplate.upsertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).one(vie);
|
||||
try {
|
||||
Airport found = couchbaseTemplate.findById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(getOptions).one(saved.getId());
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existsByIdOther() { // 1
|
||||
GetOptions options = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
ExistsOptions existsOptions = ExistsOptions.existsOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.one(vie);
|
||||
try {
|
||||
Boolean exists = couchbaseTemplate.existsById().inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(existsOptions).one(saved.getId());
|
||||
assertTrue(exists, "Airport should exist: " + saved.getId());
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // needs analytics data set
|
||||
public void findByAnalyticsOther() { // 2
|
||||
AnalyticsOptions options = AnalyticsOptions.analyticsOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.one(vie);
|
||||
try {
|
||||
List<Airport> found = couchbaseTemplate.findByAnalytics(Airport.class).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).all();
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByIdOther() { // 3
|
||||
GetOptions options = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.one(vie);
|
||||
try {
|
||||
Airport found = couchbaseTemplate.findById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).one(saved.getId());
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByQueryOther() { // 4
|
||||
QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.one(vie);
|
||||
try {
|
||||
List<Airport> found = couchbaseTemplate.findByQuery(Airport.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).all();
|
||||
assertEquals(saved.getId(), found.get(0).getId());
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findFromReplicasByIdOther() { // 5
|
||||
GetAnyReplicaOptions options = GetAnyReplicaOptions.getAnyReplicaOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.one(vie);
|
||||
try {
|
||||
Airport found = couchbaseTemplate.findFromReplicasById(Airport.class).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).any(saved.getId());
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertByIdOther() { // 6
|
||||
InsertOptions options = InsertOptions.insertOptions().timeout(Duration.ofSeconds(10));
|
||||
GetOptions getOptions = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).one(vie.withId(UUID.randomUUID().toString()));
|
||||
try {
|
||||
Airport found = couchbaseTemplate.findById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(getOptions).one(saved.getId());
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeByIdOther() { // 7
|
||||
RemoveOptions options = RemoveOptions.removeOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.one(vie);
|
||||
RemoveResult removeResult = couchbaseTemplate.removeById().inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).one(saved.getId());
|
||||
assertEquals(saved.getId(), removeResult.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeByQueryOther() { // 8
|
||||
QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.one(vie);
|
||||
List<RemoveResult> removeResults = couchbaseTemplate.removeByQuery(Airport.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).matching(Query.query(QueryCriteria.where("iata").is(vie.getIata()))).all();
|
||||
assertEquals(saved.getId(), removeResults.get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceByIdOther() { // 9
|
||||
InsertOptions insertOptions = InsertOptions.insertOptions().timeout(Duration.ofSeconds(10));
|
||||
ReplaceOptions options = ReplaceOptions.replaceOptions().timeout(Duration.ofSeconds(10));
|
||||
GetOptions getOptions = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(insertOptions).one(vie);
|
||||
Airport replaced = couchbaseTemplate.replaceById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).one(vie.withIcao("newIcao"));
|
||||
try {
|
||||
Airport found = couchbaseTemplate.findById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(getOptions).one(saved.getId());
|
||||
assertEquals(replaced, found);
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upsertByIdOther() { // 10
|
||||
UpsertOptions options = UpsertOptions.upsertOptions().timeout(Duration.ofSeconds(10));
|
||||
GetOptions getOptions = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
|
||||
Airport saved = couchbaseTemplate.upsertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).one(vie);
|
||||
try {
|
||||
Airport found = couchbaseTemplate.findById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(getOptions).one(saved.getId());
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existsByIdOptions() { // 1 - Options
|
||||
ExistsOptions options = ExistsOptions.existsOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(UnambiguousTimeoutException.class, () -> couchbaseTemplate.existsById().inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).one(vie.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // needs analytics data set
|
||||
public void findByAnalyticsOptions() { // 2
|
||||
AnalyticsOptions options = AnalyticsOptions.analyticsOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class, () -> couchbaseTemplate.findByAnalytics(Airport.class)
|
||||
.inScope(otherScope).inCollection(otherCollection).withOptions(options).all());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByIdOptions() { // 3
|
||||
GetOptions options = GetOptions.getOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(UnambiguousTimeoutException.class, () -> couchbaseTemplate.findById(Airport.class).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).one(vie.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByQueryOptions() { // 4
|
||||
QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class,
|
||||
() -> couchbaseTemplate.findByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.inScope(otherScope).inCollection(otherCollection).withOptions(options).all());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findFromReplicasByIdOptions() { // 5
|
||||
GetAnyReplicaOptions options = GetAnyReplicaOptions.getAnyReplicaOptions().timeout(Duration.ofNanos(1000));
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.one(vie);
|
||||
try {
|
||||
Airport found = couchbaseTemplate.findFromReplicasById(Airport.class).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).any(saved.getId());
|
||||
assertNull(found, "should not have found document in short timeout");
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertByIdOptions() { // 6
|
||||
InsertOptions options = InsertOptions.insertOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class, () -> couchbaseTemplate.insertById(Airport.class).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).one(vie.withId(UUID.randomUUID().toString())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeByIdOptions() { // 7 - options
|
||||
Airport saved = couchbaseTemplate.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.one(vie);
|
||||
RemoveOptions options = RemoveOptions.removeOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class, () -> couchbaseTemplate.removeById().inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).one(vie.getId()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeByQueryOptions() { // 8 - options
|
||||
QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class,
|
||||
() -> couchbaseTemplate.removeByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.inScope(otherScope).inCollection(otherCollection).withOptions(options)
|
||||
.matching(Query.query(QueryCriteria.where("iata").is(vie.getIata()))).all());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceByIdOptions() { // 9 - options
|
||||
ReplaceOptions options = ReplaceOptions.replaceOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class, () -> couchbaseTemplate.replaceById(Airport.class).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).one(vie.withIcao("newIcao")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upsertByIdOptions() { // 10 - options
|
||||
UpsertOptions options = UpsertOptions.upsertOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class, () -> couchbaseTemplate.upsertById(Airport.class).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).one(vie));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.springframework.data.couchbase.config.BeanNames.COUCHBASE_TEMPLATE;
|
||||
import static org.springframework.data.couchbase.config.BeanNames.REACTIVE_COUCHBASE_TEMPLATE;
|
||||
import static org.springframework.data.couchbase.core.query.N1QLExpression.i;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -33,13 +31,10 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.data.couchbase.core.query.Query;
|
||||
import org.springframework.data.couchbase.core.query.QueryCriteria;
|
||||
import org.springframework.data.couchbase.domain.Address;
|
||||
import org.springframework.data.couchbase.domain.Airport;
|
||||
import org.springframework.data.couchbase.domain.Config;
|
||||
import org.springframework.data.couchbase.domain.Course;
|
||||
import org.springframework.data.couchbase.domain.NaiveAuditorAware;
|
||||
import org.springframework.data.couchbase.domain.Submission;
|
||||
@@ -69,11 +64,15 @@ class CouchbaseTemplateQueryIntegrationTests extends JavaIntegrationTests {
|
||||
@BeforeEach
|
||||
@Override
|
||||
public void beforeEach() {
|
||||
ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
|
||||
couchbaseTemplate = (CouchbaseTemplate) ac.getBean(COUCHBASE_TEMPLATE);
|
||||
reactiveCouchbaseTemplate = (ReactiveCouchbaseTemplate) ac.getBean(REACTIVE_COUCHBASE_TEMPLATE);
|
||||
super.beforeEach();
|
||||
// already setup by JavaIntegrationTests.beforeAll()
|
||||
// ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
|
||||
// couchbaseTemplate = (CouchbaseTemplate) ac.getBean(COUCHBASE_TEMPLATE);
|
||||
// reactiveCouchbaseTemplate = (ReactiveCouchbaseTemplate) ac.getBean(REACTIVE_COUCHBASE_TEMPLATE);
|
||||
// ensure each test starts with clean state
|
||||
|
||||
couchbaseTemplate.removeByQuery(User.class).all();
|
||||
couchbaseTemplate.findByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -108,13 +107,13 @@ class CouchbaseTemplateQueryIntegrationTests extends JavaIntegrationTests {
|
||||
couchbaseTemplate.findById(User.class).one(user1.getId());
|
||||
reactiveCouchbaseTemplate.findById(User.class).one(user1.getId()).block();
|
||||
} finally {
|
||||
couchbaseTemplate.removeByQuery(User.class).all();
|
||||
couchbaseTemplate.removeByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all();
|
||||
}
|
||||
|
||||
User usery = couchbaseTemplate.findById(User.class).one("userx");
|
||||
assertNull(usery, "usery should be null");
|
||||
User userz = reactiveCouchbaseTemplate.findById(User.class).one("userx").block();
|
||||
assertNull(userz, "uz should be null");
|
||||
User usery = couchbaseTemplate.findById(User.class).one("user1");
|
||||
assertNull(usery, "user1 should have been deleted");
|
||||
User userz = reactiveCouchbaseTemplate.findById(User.class).one("user2").block();
|
||||
assertNull(userz, "user2 should have been deleted");
|
||||
|
||||
}
|
||||
|
||||
@@ -136,6 +135,8 @@ class CouchbaseTemplateQueryIntegrationTests extends JavaIntegrationTests {
|
||||
@Test
|
||||
void findByMatchingQueryProjected() {
|
||||
|
||||
couchbaseTemplate.removeByQuery(UserSubmission.class).all();
|
||||
|
||||
UserSubmission user = new UserSubmission();
|
||||
user.setId(UUID.randomUUID().toString());
|
||||
user.setUsername("dave");
|
||||
|
||||
@@ -224,7 +224,7 @@ class QueryCriteriaTests {
|
||||
@Test
|
||||
void testIn() {
|
||||
String[] args = new String[] { "gump", "davis" };
|
||||
QueryCriteria c = where(i("name")).in(args);
|
||||
QueryCriteria c = where(i("name")).in((Object)args);
|
||||
assertEquals("`name` in ( [\"gump\",\"davis\"] )", c.export());
|
||||
JsonArray parameters = JsonArray.create();
|
||||
assertEquals("`name` in ( $1 )", c.export(new int[1], parameters, null));
|
||||
@@ -234,7 +234,7 @@ class QueryCriteriaTests {
|
||||
@Test
|
||||
void testNotIn() {
|
||||
String[] args = new String[] { "gump", "davis" };
|
||||
QueryCriteria c = where(i("name")).notIn(args);
|
||||
QueryCriteria c = where(i("name")).notIn((Object)args);
|
||||
assertEquals("not( (`name` in ( [\"gump\",\"davis\"] )) )", c.export());
|
||||
JsonArray parameters = JsonArray.create();
|
||||
assertEquals("not( (`name` in ( $1 )) )", c.export(new int[1], parameters, null));
|
||||
|
||||
@@ -0,0 +1,745 @@
|
||||
/*
|
||||
* Copyright 2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.core.query;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.couchbase.core.ReactiveCouchbaseTemplate;
|
||||
import org.springframework.data.couchbase.core.RemoveResult;
|
||||
import org.springframework.data.couchbase.domain.Address;
|
||||
import org.springframework.data.couchbase.domain.Airport;
|
||||
import org.springframework.data.couchbase.domain.Course;
|
||||
import org.springframework.data.couchbase.domain.NaiveAuditorAware;
|
||||
import org.springframework.data.couchbase.domain.Submission;
|
||||
import org.springframework.data.couchbase.domain.User;
|
||||
import org.springframework.data.couchbase.domain.UserJustLastName;
|
||||
import org.springframework.data.couchbase.domain.UserSubmission;
|
||||
import org.springframework.data.couchbase.domain.UserSubmissionProjected;
|
||||
import org.springframework.data.couchbase.domain.time.AuditingDateTimeProvider;
|
||||
import org.springframework.data.couchbase.util.Capabilities;
|
||||
import org.springframework.data.couchbase.util.ClusterType;
|
||||
import org.springframework.data.couchbase.util.CollectionAwareIntegrationTests;
|
||||
import org.springframework.data.couchbase.util.IgnoreWhen;
|
||||
|
||||
import com.couchbase.client.core.error.AmbiguousTimeoutException;
|
||||
import com.couchbase.client.core.error.UnambiguousTimeoutException;
|
||||
import com.couchbase.client.java.analytics.AnalyticsOptions;
|
||||
import com.couchbase.client.java.kv.ExistsOptions;
|
||||
import com.couchbase.client.java.kv.GetAnyReplicaOptions;
|
||||
import com.couchbase.client.java.kv.GetOptions;
|
||||
import com.couchbase.client.java.kv.InsertOptions;
|
||||
import com.couchbase.client.java.kv.RemoveOptions;
|
||||
import com.couchbase.client.java.kv.ReplaceOptions;
|
||||
import com.couchbase.client.java.kv.UpsertOptions;
|
||||
import com.couchbase.client.java.query.QueryOptions;
|
||||
import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
|
||||
/**
|
||||
* Query tests Theses tests rely on a cb server running This class tests collection support with
|
||||
* inCollection(collection), inScope(scope) and withOptions(options). Testing without collections could also be done by
|
||||
* this class simply by using scopeName = null and collectionName = null
|
||||
*
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
@IgnoreWhen(missesCapabilities = { Capabilities.QUERY, Capabilities.COLLECTIONS }, clusterTypes = ClusterType.MOCKED)
|
||||
class ReactiveCouchbaseTemplateQueryCollectionIntegrationTests extends CollectionAwareIntegrationTests {
|
||||
|
||||
Airport vie = new Airport("airports::vie", "vie", "low7");
|
||||
ReactiveCouchbaseTemplate template = reactiveCouchbaseTemplate;
|
||||
|
||||
@BeforeAll
|
||||
public static void beforeAll() {
|
||||
// first call the super method
|
||||
callSuperBeforeAll(new Object() {});
|
||||
// then do processing for this class
|
||||
// no-op
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void afterAll() {
|
||||
// first do the processing for this class
|
||||
// no-op
|
||||
// then call the super method
|
||||
callSuperAfterAll(new Object() {});
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
@Override
|
||||
public void beforeEach() {
|
||||
// first call the super method
|
||||
super.beforeEach();
|
||||
// then do processing for this class
|
||||
couchbaseTemplate.removeByQuery(User.class).inCollection(collectionName).all();
|
||||
couchbaseTemplate.findByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.inCollection(collectionName).all();
|
||||
couchbaseTemplate.removeByQuery(Airport.class).inScope(scopeName).inCollection(collectionName).all();
|
||||
couchbaseTemplate.findByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).inScope(scopeName)
|
||||
.inCollection(collectionName).all();
|
||||
couchbaseTemplate.removeByQuery(Airport.class).inScope(otherScope).inCollection(otherCollection).all();
|
||||
couchbaseTemplate.findByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).inScope(otherScope)
|
||||
.inCollection(otherCollection).all();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@Override
|
||||
public void afterEach() {
|
||||
// first do processing for this class
|
||||
couchbaseTemplate.removeByQuery(User.class).inCollection(collectionName).all();
|
||||
// query with REQUEST_PLUS to ensure that the remove has completed.
|
||||
couchbaseTemplate.findByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.inCollection(collectionName).all();
|
||||
// then call the super method
|
||||
super.afterEach();
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByQueryAll() {
|
||||
try {
|
||||
User user1 = new User(UUID.randomUUID().toString(), "user1", "user1");
|
||||
User user2 = new User(UUID.randomUUID().toString(), "user2", "user2");
|
||||
|
||||
couchbaseTemplate.upsertById(User.class).inCollection(collectionName).all(Arrays.asList(user1, user2));
|
||||
|
||||
final List<User> foundUsers = couchbaseTemplate.findByQuery(User.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).all();
|
||||
|
||||
for (User u : foundUsers) {
|
||||
if (!(u.equals(user1) || u.equals(user2))) {
|
||||
// somebody didn't clean up after themselves.
|
||||
couchbaseTemplate.removeById().inCollection(collectionName).one(u.getId());
|
||||
}
|
||||
}
|
||||
assertEquals(2, foundUsers.size());
|
||||
TemporalAccessor auditTime = new AuditingDateTimeProvider().getNow().get();
|
||||
long auditMillis = Instant.from(auditTime).toEpochMilli();
|
||||
String auditUser = new NaiveAuditorAware().getCurrentAuditor().get();
|
||||
|
||||
for (User u : foundUsers) {
|
||||
assertTrue(u.equals(user1) || u.equals(user2));
|
||||
assertEquals(auditUser, u.getCreator());
|
||||
assertEquals(auditMillis, u.getCreatedDate());
|
||||
assertEquals(auditUser, u.getLastModifiedBy());
|
||||
assertEquals(auditMillis, u.getLastModifiedDate());
|
||||
}
|
||||
couchbaseTemplate.findById(User.class).inCollection(collectionName).one(user1.getId());
|
||||
reactiveCouchbaseTemplate.findById(User.class).inCollection(collectionName).one(user1.getId()).block();
|
||||
} finally {
|
||||
couchbaseTemplate.removeByQuery(User.class).inCollection(collectionName).all();
|
||||
}
|
||||
|
||||
User usery = couchbaseTemplate.findById(User.class).inCollection(collectionName).one("userx");
|
||||
assertNull(usery, "usery should be null");
|
||||
User userz = reactiveCouchbaseTemplate.findById(User.class).inCollection(collectionName).one("userx").block();
|
||||
assertNull(userz, "userz should be null");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByMatchingQuery() {
|
||||
User user1 = new User(UUID.randomUUID().toString(), "user1", "user1");
|
||||
User user2 = new User(UUID.randomUUID().toString(), "user2", "user2");
|
||||
User specialUser = new User(UUID.randomUUID().toString(), "special", "special");
|
||||
|
||||
couchbaseTemplate.upsertById(User.class).inCollection(collectionName).all(Arrays.asList(user1, user2, specialUser));
|
||||
|
||||
Query specialUsers = new Query(QueryCriteria.where("firstname").like("special"));
|
||||
final List<User> foundUsers = couchbaseTemplate.findByQuery(User.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).matching(specialUsers).all();
|
||||
|
||||
assertEquals(1, foundUsers.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByMatchingQueryProjected() {
|
||||
|
||||
UserSubmission user = new UserSubmission();
|
||||
user.setId(UUID.randomUUID().toString());
|
||||
user.setUsername("dave");
|
||||
user.setRoles(Arrays.asList("role1", "role2"));
|
||||
Address address = new Address();
|
||||
address.setStreet("1234 Olcott Street");
|
||||
user.setAddress(address);
|
||||
user.setSubmissions(
|
||||
Arrays.asList(new Submission(UUID.randomUUID().toString(), user.getId(), "tid", "status", 123)));
|
||||
user.setCourses(Arrays.asList(new Course(UUID.randomUUID().toString(), user.getId(), "581"),
|
||||
new Course(UUID.randomUUID().toString(), user.getId(), "777")));
|
||||
couchbaseTemplate.upsertById(UserSubmission.class).inCollection(collectionName).one(user);
|
||||
|
||||
Query daveUsers = new Query(QueryCriteria.where("username").like("dave"));
|
||||
|
||||
final List<UserSubmissionProjected> foundUserSubmissions = couchbaseTemplate.findByQuery(UserSubmission.class)
|
||||
.as(UserSubmissionProjected.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.inCollection(collectionName).matching(daveUsers).all();
|
||||
assertEquals(1, foundUserSubmissions.size());
|
||||
assertEquals(user.getUsername(), foundUserSubmissions.get(0).getUsername());
|
||||
assertEquals(user.getId(), foundUserSubmissions.get(0).getId());
|
||||
assertEquals(user.getCourses(), foundUserSubmissions.get(0).getCourses());
|
||||
assertEquals(user.getAddress(), foundUserSubmissions.get(0).getAddress());
|
||||
|
||||
couchbaseTemplate.removeByQuery(UserSubmission.class).inCollection(collectionName).all();
|
||||
|
||||
User user1 = new User(UUID.randomUUID().toString(), "user1", "user1");
|
||||
User user2 = new User(UUID.randomUUID().toString(), "user2", "user2");
|
||||
User specialUser = new User(UUID.randomUUID().toString(), "special", "special");
|
||||
|
||||
couchbaseTemplate.upsertById(User.class).inCollection(collectionName).all(Arrays.asList(user1, user2, specialUser));
|
||||
|
||||
Query specialUsers = new Query(QueryCriteria.where("firstname").like("special"));
|
||||
final List<UserJustLastName> foundUsers = couchbaseTemplate.findByQuery(User.class).as(UserJustLastName.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).matching(specialUsers).all();
|
||||
assertEquals(1, foundUsers.size());
|
||||
|
||||
final List<UserJustLastName> foundUsersReactive = reactiveCouchbaseTemplate.findByQuery(User.class)
|
||||
.as(UserJustLastName.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName)
|
||||
.matching(specialUsers).all().collectList().block();
|
||||
assertEquals(1, foundUsersReactive.size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeByQueryAll() {
|
||||
User user1 = new User(UUID.randomUUID().toString(), "user1", "user1");
|
||||
User user2 = new User(UUID.randomUUID().toString(), "user2", "user2");
|
||||
|
||||
couchbaseTemplate.upsertById(User.class).inScope(scopeName).inCollection(collectionName)
|
||||
.all(Arrays.asList(user1, user2));
|
||||
|
||||
assertTrue(couchbaseTemplate.existsById().inScope(scopeName).inCollection(collectionName).one(user1.getId()));
|
||||
assertTrue(couchbaseTemplate.existsById().inScope(scopeName).inCollection(collectionName).one(user2.getId()));
|
||||
|
||||
List<RemoveResult> result = couchbaseTemplate.removeByQuery(User.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).all();
|
||||
assertEquals(2, result.size(), "should have deleted user1 and user2");
|
||||
|
||||
assertNull(
|
||||
couchbaseTemplate.findById(User.class).inScope(scopeName).inCollection(collectionName).one(user1.getId()));
|
||||
assertNull(
|
||||
couchbaseTemplate.findById(User.class).inScope(scopeName).inCollection(collectionName).one(user2.getId()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeByMatchingQuery() {
|
||||
User user1 = new User(UUID.randomUUID().toString(), "user1", "user1");
|
||||
User user2 = new User(UUID.randomUUID().toString(), "user2", "user2");
|
||||
User specialUser = new User(UUID.randomUUID().toString(), "special", "special");
|
||||
|
||||
couchbaseTemplate.upsertById(User.class).inCollection(collectionName).all(Arrays.asList(user1, user2, specialUser));
|
||||
|
||||
assertTrue(couchbaseTemplate.existsById().inCollection(collectionName).one(user1.getId()));
|
||||
assertTrue(couchbaseTemplate.existsById().inCollection(collectionName).one(user2.getId()));
|
||||
assertTrue(couchbaseTemplate.existsById().inCollection(collectionName).one(specialUser.getId()));
|
||||
|
||||
Query nonSpecialUsers = new Query(QueryCriteria.where("firstname").notLike("special"));
|
||||
|
||||
couchbaseTemplate.removeByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.inCollection(collectionName).matching(nonSpecialUsers).all();
|
||||
|
||||
assertNull(couchbaseTemplate.findById(User.class).inCollection(collectionName).one(user1.getId()));
|
||||
assertNull(couchbaseTemplate.findById(User.class).inCollection(collectionName).one(user2.getId()));
|
||||
assertNotNull(couchbaseTemplate.findById(User.class).inCollection(collectionName).one(specialUser.getId()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void distinct() {
|
||||
String[] iatas = { "JFK", "IAD", "SFO", "SJC", "SEA", "LAX", "PHX" };
|
||||
String[] icaos = { "ic0", "ic1", "ic0", "ic1", "ic0", "ic1", "ic0" };
|
||||
|
||||
try {
|
||||
for (int i = 0; i < iatas.length; i++) {
|
||||
Airport airport = new Airport("airports::" + iatas[i], iatas[i] /*iata*/, icaos[i] /* icao */);
|
||||
couchbaseTemplate.insertById(Airport.class).inCollection(collectionName).one(airport);
|
||||
}
|
||||
|
||||
// distinct and count(distinct(...)) calls. use as() and consistentWith to verify fluent api
|
||||
// as the fluent api for Distinct is tricky
|
||||
|
||||
// distinct icao
|
||||
List<Airport> airports1 = couchbaseTemplate.findByQuery(Airport.class).distinct(new String[] { "icao" })
|
||||
.as(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).all();
|
||||
assertEquals(2, airports1.size());
|
||||
|
||||
// distinct all-fields-in-Airport.class
|
||||
List<Airport> airports2 = couchbaseTemplate.findByQuery(Airport.class).distinct(new String[] {}).as(Airport.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).all();
|
||||
assertEquals(7, airports2.size());
|
||||
|
||||
// count( distinct { iata, icao } )
|
||||
long count1 = couchbaseTemplate.findByQuery(Airport.class).distinct(new String[] { "iata", "icao" })
|
||||
.as(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).count();
|
||||
assertEquals(7, count1);
|
||||
|
||||
// count( distinct (all fields in icaoClass)
|
||||
Class icaoClass = (new Object() {
|
||||
String iata;
|
||||
String icao;
|
||||
}).getClass();
|
||||
long count2 = couchbaseTemplate.findByQuery(Airport.class).distinct(new String[] {}).as(icaoClass)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).count();
|
||||
assertEquals(7, count2);
|
||||
|
||||
} finally {
|
||||
couchbaseTemplate.removeById().inCollection(collectionName)
|
||||
.all(Arrays.stream(iatas).map((iata) -> "airports::" + iata).collect(Collectors.toSet()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void distinctReactive() {
|
||||
String[] iatas = { "JFK", "IAD", "SFO", "SJC", "SEA", "LAX", "PHX" };
|
||||
String[] icaos = { "ic0", "ic1", "ic0", "ic1", "ic0", "ic1", "ic0" };
|
||||
|
||||
try {
|
||||
for (int i = 0; i < iatas.length; i++) {
|
||||
Airport airport = new Airport("airports::" + iatas[i], iatas[i] /*iata*/, icaos[i] /* icao */);
|
||||
reactiveCouchbaseTemplate.insertById(Airport.class).inCollection(collectionName).one(airport).block();
|
||||
}
|
||||
|
||||
// distinct and count(distinct(...)) calls. use as() and consistentWith to verify fluent api
|
||||
// as the fluent api for Distinct is tricky
|
||||
|
||||
// distinct icao
|
||||
List<Airport> airports1 = reactiveCouchbaseTemplate.findByQuery(Airport.class).distinct(new String[] { "icao" })
|
||||
.as(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).all()
|
||||
.collectList().block();
|
||||
assertEquals(2, airports1.size());
|
||||
|
||||
// distinct all-fields-in-Airport.class
|
||||
List<Airport> airports2 = reactiveCouchbaseTemplate.findByQuery(Airport.class).distinct(new String[] {})
|
||||
.as(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).all()
|
||||
.collectList().block();
|
||||
assertEquals(7, airports2.size());
|
||||
|
||||
// count( distinct icao )
|
||||
// not currently possible to have multiple fields in COUNT(DISTINCT field1, field2, ... ) due to MB43475
|
||||
Long count1 = reactiveCouchbaseTemplate.findByQuery(Airport.class).distinct(new String[] { "icao" })
|
||||
.as(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).count()
|
||||
.block();
|
||||
assertEquals(2, count1);
|
||||
|
||||
// count( distinct (all fields in icaoClass) // which only has one field
|
||||
// not currently possible to have multiple fields in COUNT(DISTINCT field1, field2, ... ) due to MB43475
|
||||
Class icaoClass = (new Object() {
|
||||
String icao;
|
||||
}).getClass();
|
||||
long count2 = (long) reactiveCouchbaseTemplate.findByQuery(Airport.class).distinct(new String[] {}).as(icaoClass)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inCollection(collectionName).count().block();
|
||||
assertEquals(2, count2);
|
||||
|
||||
} finally {
|
||||
reactiveCouchbaseTemplate.removeById().inCollection(collectionName)
|
||||
.all(Arrays.stream(iatas).map((iata) -> "airports::" + iata).collect(Collectors.toSet())).collectList()
|
||||
.block();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find . -name 'Exec*OperationSupport.java'|awk -F/ '{print $NF}'|sort| awk -F. '{print "* ", NR, ")",$1, ""}'<br>
|
||||
* 1) ExecutableExistsByIdOperationSupport <br>
|
||||
* 2) ExecutableFindByAnalyticsOperationSupport <br>
|
||||
* 3) ExecutableFindByIdOperationSupport <br>
|
||||
* 4) ExecutableFindByQueryOperationSupport <br>
|
||||
* 5) ExecutableFindFromReplicasByIdOperationSupport <br>
|
||||
* 6) ExecutableInsertByIdOperationSupport <br>
|
||||
* 7) ExecutableRemoveByIdOperationSupport <br>
|
||||
* 8) ExecutableRemoveByQueryOperationSupport <br>
|
||||
* 9) ExecutableReplaceByIdOperationSupport <br>
|
||||
* 10)ExecutableUpsertByIdOperationSupport <br>
|
||||
*/
|
||||
@Test
|
||||
public void existsById() { // 1
|
||||
GetOptions options = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
ExistsOptions existsOptions = ExistsOptions.existsOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(scopeName).inCollection(collectionName).one(vie.withIcao("low7")).block();
|
||||
try {
|
||||
Boolean exists = template.existsById().inScope(scopeName).inCollection(collectionName).withOptions(existsOptions)
|
||||
.one(saved.getId()).block();
|
||||
assertTrue(exists, "Airport should exist: " + saved.getId());
|
||||
} finally {
|
||||
template.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // needs analytics data set
|
||||
public void findByAnalytics() { // 2
|
||||
AnalyticsOptions options = AnalyticsOptions.analyticsOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(scopeName).inCollection(collectionName).one(vie.withIcao("low8")).block();
|
||||
try {
|
||||
List<Airport> found = template.findByAnalytics(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).all().collectList().block();
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
template.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findById() { // 3
|
||||
GetOptions options = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(scopeName).inCollection(collectionName).one(vie.withIcao("low9")).block();
|
||||
try {
|
||||
Airport found = template.findById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).one(saved.getId()).block();
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
template.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByQuery() { // 4
|
||||
QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(scopeName).inCollection(collectionName).one(vie.withIcao("lowa")).block();
|
||||
try {
|
||||
List<Airport> found = template.findByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.inScope(scopeName).inCollection(collectionName).withOptions(options).all().collectList().block();
|
||||
assertEquals(saved.getId(), found.get(0).getId());
|
||||
} finally {
|
||||
template.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findFromReplicasById() { // 5
|
||||
GetAnyReplicaOptions options = GetAnyReplicaOptions.getAnyReplicaOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(scopeName).inCollection(collectionName).one(vie.withIcao("lowb")).block();
|
||||
try {
|
||||
Airport found = template.findFromReplicasById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).any(saved.getId()).block();
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
template.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertById() { // 6
|
||||
InsertOptions options = InsertOptions.insertOptions().timeout(Duration.ofSeconds(10));
|
||||
GetOptions getOptions = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).one(vie.withIcao("lowc").withId(UUID.randomUUID().toString())).block();
|
||||
try {
|
||||
Airport found = template.findById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(getOptions).one(saved.getId()).block();
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
template.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeById() { // 7
|
||||
RemoveOptions options = RemoveOptions.removeOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(scopeName).inCollection(collectionName).one(vie.withIcao("lowd")).block();
|
||||
RemoveResult removeResult = template.removeById().inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).one(saved.getId()).block();
|
||||
assertEquals(saved.getId(), removeResult.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeByQuery() { // 8
|
||||
QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(scopeName).inCollection(collectionName).one(vie.withIcao("lowe")).block();
|
||||
List<RemoveResult> removeResults = template.removeByQuery(Airport.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).matching(Query.query(QueryCriteria.where("iata").is(vie.getIata()))).all().collectList()
|
||||
.block();
|
||||
assertEquals(saved.getId(), removeResults.get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceById() { // 9
|
||||
InsertOptions insertOptions = InsertOptions.insertOptions().timeout(Duration.ofSeconds(10));
|
||||
ReplaceOptions options = ReplaceOptions.replaceOptions().timeout(Duration.ofSeconds(10));
|
||||
GetOptions getOptions = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(insertOptions).one(vie.withIcao("lowe")).block();
|
||||
Airport replaced = template.replaceById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).one(vie.withIcao("newIcao")).block();
|
||||
try {
|
||||
Airport found = template.findById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(getOptions).one(saved.getId()).block();
|
||||
assertEquals(replaced, found);
|
||||
} finally {
|
||||
template.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upsertById() { // 10
|
||||
UpsertOptions options = UpsertOptions.upsertOptions().timeout(Duration.ofSeconds(10));
|
||||
GetOptions getOptions = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
|
||||
Airport saved = template.upsertById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(options).one(vie.withIcao("lowf")).block();
|
||||
try {
|
||||
Airport found = template.findById(Airport.class).inScope(scopeName).inCollection(collectionName)
|
||||
.withOptions(getOptions).one(saved.getId()).block();
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
template.removeById().inScope(scopeName).inCollection(collectionName).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existsByIdOther() { // 1
|
||||
GetOptions options = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
ExistsOptions existsOptions = ExistsOptions.existsOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection).one(vie.withIcao("lowg"))
|
||||
.block();
|
||||
try {
|
||||
Boolean exists = template.existsById().inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(existsOptions).one(saved.getId()).block();
|
||||
assertTrue(exists, "Airport should exist: " + saved.getId());
|
||||
} finally {
|
||||
template.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // needs analytics data set
|
||||
public void findByAnalyticsOther() { // 2
|
||||
AnalyticsOptions options = AnalyticsOptions.analyticsOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection).one(vie.withIcao("lowh"))
|
||||
.block();
|
||||
try {
|
||||
List<Airport> found = template.findByAnalytics(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).all().collectList().block();
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
template.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByIdOther() { // 3
|
||||
GetOptions options = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection).one(vie.withIcao("lowi"))
|
||||
.block();
|
||||
try {
|
||||
Airport found = template.findById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).one(saved.getId()).block();
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
template.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByQueryOther() { // 4
|
||||
QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection).one(vie.withIcao("lowj"))
|
||||
.block();
|
||||
try {
|
||||
List<Airport> found = template.findByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.inScope(otherScope).inCollection(otherCollection).withOptions(options).all().collectList().block();
|
||||
assertEquals(saved.getId(), found.get(0).getId());
|
||||
} finally {
|
||||
template.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findFromReplicasByIdOther() { // 5
|
||||
GetAnyReplicaOptions options = GetAnyReplicaOptions.getAnyReplicaOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection).one(vie.withIcao("lowk"))
|
||||
.block();
|
||||
try {
|
||||
Airport found = template.findFromReplicasById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).any(saved.getId()).block();
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
template.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertByIdOther() { // 6
|
||||
InsertOptions options = InsertOptions.insertOptions().timeout(Duration.ofSeconds(10));
|
||||
GetOptions getOptions = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).one(vie.withIcao("lowl").withId(UUID.randomUUID().toString())).block();
|
||||
try {
|
||||
Airport found = template.findById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(getOptions).one(saved.getId()).block();
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
template.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeByIdOther() { // 7
|
||||
RemoveOptions options = RemoveOptions.removeOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection).one(vie.withIcao("lowm"))
|
||||
.block();
|
||||
RemoveResult removeResult = template.removeById().inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).one(saved.getId()).block();
|
||||
assertEquals(saved.getId(), removeResult.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeByQueryOther() { // 8
|
||||
QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection).one(vie.withIcao("lown"))
|
||||
.block();
|
||||
List<RemoveResult> removeResults = template.removeByQuery(Airport.class)
|
||||
.withConsistency(QueryScanConsistency.REQUEST_PLUS).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).matching(Query.query(QueryCriteria.where("iata").is(vie.getIata()))).all().collectList()
|
||||
.block();
|
||||
assertEquals(saved.getId(), removeResults.get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceByIdOther() { // 9
|
||||
InsertOptions insertOptions = InsertOptions.insertOptions().timeout(Duration.ofSeconds(10));
|
||||
ReplaceOptions options = ReplaceOptions.replaceOptions().timeout(Duration.ofSeconds(10));
|
||||
GetOptions getOptions = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
Airport saved = template.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(insertOptions).one(vie.withIcao("lown")).block();
|
||||
Airport replaced = template.replaceById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).one(vie.withIcao("newIcao")).block();
|
||||
try {
|
||||
Airport found = template.findById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(getOptions).one(saved.getId()).block();
|
||||
assertEquals(replaced, found);
|
||||
} finally {
|
||||
template.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upsertByIdOther() { // 10
|
||||
UpsertOptions options = UpsertOptions.upsertOptions().timeout(Duration.ofSeconds(10));
|
||||
GetOptions getOptions = GetOptions.getOptions().timeout(Duration.ofSeconds(10));
|
||||
|
||||
Airport saved = template.upsertById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).one(vie.withIcao("lowo")).block();
|
||||
try {
|
||||
Airport found = template.findById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(getOptions).one(saved.getId()).block();
|
||||
assertEquals(saved, found);
|
||||
} finally {
|
||||
template.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existsByIdOptions() { // 1 - Options
|
||||
ExistsOptions options = ExistsOptions.existsOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(UnambiguousTimeoutException.class, () -> template.existsById().inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).one(vie.getId()).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // needs analytics data set
|
||||
public void findByAnalyticsOptions() { // 2
|
||||
AnalyticsOptions options = AnalyticsOptions.analyticsOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class, () -> template.findByAnalytics(Airport.class).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).all().collectList().block());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByIdOptions() { // 3
|
||||
GetOptions options = GetOptions.getOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(UnambiguousTimeoutException.class, () -> template.findById(Airport.class).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).one(vie.getId()).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByQueryOptions() { // 4
|
||||
QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class,
|
||||
() -> template.findByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).all().collectList().block());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findFromReplicasByIdOptions() { // 5
|
||||
GetAnyReplicaOptions options = GetAnyReplicaOptions.getAnyReplicaOptions().timeout(Duration.ofNanos(1000));
|
||||
Airport saved = template.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection).one(vie)
|
||||
.block();
|
||||
try {
|
||||
Airport found = template.findFromReplicasById(Airport.class).inScope(otherScope).inCollection(otherCollection)
|
||||
.withOptions(options).any(saved.getId()).block();
|
||||
assertNull(found, "should not have found document in short timeout");
|
||||
} finally {
|
||||
template.removeById().inScope(otherScope).inCollection(otherCollection).one(saved.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertByIdOptions() { // 6
|
||||
InsertOptions options = InsertOptions.insertOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class, () -> template.insertById(Airport.class).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).one(vie.withId(UUID.randomUUID().toString())).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeByIdOptions() { // 7 - options
|
||||
Airport saved = template.insertById(Airport.class).inScope(otherScope).inCollection(otherCollection).one(vie)
|
||||
.block();
|
||||
RemoveOptions options = RemoveOptions.removeOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class, () -> template.removeById().inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).one(vie.getId()).block());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeByQueryOptions() { // 8 - options
|
||||
QueryOptions options = QueryOptions.queryOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class,
|
||||
() -> template.removeByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
|
||||
.inScope(otherScope).inCollection(otherCollection).withOptions(options)
|
||||
.matching(Query.query(QueryCriteria.where("iata").is(vie.getIata()))).all().collectList().block());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceByIdOptions() { // 9 - options
|
||||
ReplaceOptions options = ReplaceOptions.replaceOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class, () -> template.replaceById(Airport.class).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).one(vie.withIcao("newIcao")).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upsertByIdOptions() { // 10 - options
|
||||
UpsertOptions options = UpsertOptions.upsertOptions().timeout(Duration.ofNanos(10));
|
||||
assertThrows(AmbiguousTimeoutException.class, () -> template.upsertById(Airport.class).inScope(otherScope)
|
||||
.inCollection(otherCollection).withOptions(options).one(vie).block());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
* Copyright 2012-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -48,7 +48,7 @@ import com.couchbase.client.java.json.JacksonTransformers;
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCouchbaseRepositories
|
||||
@EnableCouchbaseAuditing(auditorAwareRef="auditorAwareRef", dateTimeProviderRef="dateTimeProviderRef") // this activates auditing
|
||||
@EnableCouchbaseAuditing(auditorAwareRef = "auditorAwareRef", dateTimeProviderRef = "dateTimeProviderRef")
|
||||
public class Config extends AbstractCouchbaseConfiguration {
|
||||
String bucketname = "travel-sample";
|
||||
String username = "Administrator";
|
||||
@@ -205,4 +205,15 @@ public class Config extends AbstractCouchbaseConfiguration {
|
||||
return "t"; // this will override '_class', is passed in to new CustomMappingCouchbaseConverter
|
||||
}
|
||||
|
||||
static String scopeName = null;
|
||||
|
||||
@Override
|
||||
protected String getScopeName() {
|
||||
return scopeName;
|
||||
}
|
||||
|
||||
public static void setScopeName(String scopeName) {
|
||||
Config.scopeName = scopeName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.domain;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories;
|
||||
|
||||
/**
|
||||
* Configuration that uses a scope. This is a separate class as it is difficult to debug if you forget to unset the
|
||||
* scopeName and the config is used for non-collection operations.
|
||||
*
|
||||
* @Author Michael Reiche
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCouchbaseRepositories
|
||||
public class ConfigScoped extends Config {
|
||||
|
||||
static String scopeName = null;
|
||||
|
||||
@Override
|
||||
protected String getScopeName() {
|
||||
return scopeName;
|
||||
}
|
||||
|
||||
public static void setScopeName(String scopeName) {
|
||||
ConfigScoped.scopeName = scopeName;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,21 @@
|
||||
/*
|
||||
* Copyright 2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.couchbase.domain;
|
||||
|
||||
import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
@@ -9,13 +23,16 @@ import org.springframework.data.mapping.context.MappingContext;
|
||||
public class CustomMappingCouchbaseConverter extends MappingCouchbaseConverter {
|
||||
|
||||
/**
|
||||
* this constructer creates a TypeBasedCouchbaseTypeMapper with the specified typeKey
|
||||
* while MappingCouchbaseConverter uses a DefaultCouchbaseTypeMapper
|
||||
* typeMapper = new DefaultCouchbaseTypeMapper(typeKey != null ? typeKey : TYPEKEY_DEFAULT);
|
||||
* this constructer creates a TypeBasedCouchbaseTypeMapper with the specified typeKey while MappingCouchbaseConverter
|
||||
* uses a DefaultCouchbaseTypeMapper typeMapper = new DefaultCouchbaseTypeMapper(typeKey != null ? typeKey :
|
||||
* TYPEKEY_DEFAULT);
|
||||
*
|
||||
* @param mappingContext
|
||||
* @param typeKey - the typeKey to be used (normally "_class")
|
||||
*/
|
||||
public CustomMappingCouchbaseConverter(final MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext, final String typeKey) {
|
||||
public CustomMappingCouchbaseConverter(
|
||||
final MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext,
|
||||
final String typeKey) {
|
||||
super(mappingContext, typeKey);
|
||||
this.typeMapper = new TypeBasedCouchbaseTypeMapper(typeKey);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
package org.springframework.data.couchbase.domain;
|
||||
|
||||
import com.couchbase.client.java.query.QueryOptions;
|
||||
import com.couchbase.client.java.query.QueryProfile;
|
||||
import com.couchbase.client.java.query.QueryResult;
|
||||
import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.data.couchbase.config.BeanNames;
|
||||
import org.springframework.data.couchbase.core.CouchbaseTemplate;
|
||||
import org.springframework.data.couchbase.core.ReactiveCouchbaseTemplate;
|
||||
import org.springframework.data.couchbase.core.RemoveResult;
|
||||
import org.springframework.data.couchbase.util.Capabilities;
|
||||
import org.springframework.data.couchbase.util.ClusterType;
|
||||
import org.springframework.data.couchbase.util.IgnoreWhen;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.publisher.ParallelFlux;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
|
||||
import org.springframework.data.couchbase.repository.config.EnableReactiveCouchbaseRepositories;
|
||||
import org.springframework.data.couchbase.util.JavaIntegrationTests;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import com.couchbase.client.java.Collection;
|
||||
import com.couchbase.client.java.ReactiveCollection;
|
||||
import com.couchbase.client.java.json.JsonObject;
|
||||
import com.couchbase.client.java.kv.GetResult;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@SpringJUnitConfig(FluxTest.Config.class)
|
||||
@IgnoreWhen(clusterTypes = ClusterType.MOCKED)
|
||||
public class FluxTest extends JavaIntegrationTests {
|
||||
|
||||
@BeforeAll
|
||||
public static void beforeEverything() {
|
||||
/**
|
||||
* The couchbaseTemplate inherited from JavaIntegrationTests uses org.springframework.data.couchbase.domain.Config
|
||||
* It has typeName = 't' (instead of _class). Don't use it.
|
||||
*/
|
||||
ApplicationContext ac = new AnnotationConfigApplicationContext(FluxTest.Config.class);
|
||||
couchbaseTemplate = (CouchbaseTemplate) ac.getBean(BeanNames.COUCHBASE_TEMPLATE);
|
||||
reactiveCouchbaseTemplate = (ReactiveCouchbaseTemplate) ac.getBean(BeanNames.REACTIVE_COUCHBASE_TEMPLATE);
|
||||
collection = couchbaseTemplate.getCouchbaseClientFactory().getBucket().defaultCollection();
|
||||
rCollection = couchbaseTemplate.getCouchbaseClientFactory().getBucket().reactive().defaultCollection();
|
||||
for (String k : keyList) {
|
||||
couchbaseTemplate.getCouchbaseClientFactory().getBucket().defaultCollection().upsert(k,
|
||||
JsonObject.create().put("x", k));
|
||||
}
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void afterEverthing() {
|
||||
couchbaseTemplate.removeByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all();
|
||||
couchbaseTemplate.findByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
@Override
|
||||
public void beforeEach() {
|
||||
super.beforeEach();
|
||||
}
|
||||
|
||||
static List<String> keyList = Arrays.asList("a", "b", "c", "d", "e");
|
||||
static Collection collection;
|
||||
static ReactiveCollection rCollection;
|
||||
@Autowired ReactiveAirportRepository airportRepository; // intellij flags "Could not Autowire", but it runs ok.
|
||||
|
||||
AtomicInteger rCat = new AtomicInteger(0);
|
||||
AtomicInteger rFlat = new AtomicInteger(0);
|
||||
|
||||
@Test
|
||||
public void concatMapCB() throws Exception {
|
||||
System.out.println("Start concatMapCB");
|
||||
System.out.println("\n******** Using concatMap() *********");
|
||||
ParallelFlux<GetResult> concat = Flux.fromIterable(keyList).parallel(2).runOn(Schedulers.parallel())
|
||||
.concatMap(item -> cbGet(item)
|
||||
/* rCollection.get(item) */.doOnSubscribe((x) -> System.out.println(" +" + rCat.incrementAndGet()))
|
||||
.doOnTerminate(() -> System.out.println(" -" + rCat.decrementAndGet())));
|
||||
System.out.println(concat.sequential().collectList().block());
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreWhen(missesCapabilities = { Capabilities.QUERY, Capabilities.COLLECTIONS }, clusterTypes = ClusterType.MOCKED)
|
||||
public void cbse() {
|
||||
LinkedList<LinkedList<Airport>> listOfLists = new LinkedList<>();
|
||||
Airport a = new Airport(UUID.randomUUID().toString(), "iata", "lowp");
|
||||
String last = null;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
LinkedList<Airport> list = new LinkedList<>();
|
||||
for (int j = 0; j < 10; j++) {
|
||||
list.add(a.withId(UUID.randomUUID().toString()));
|
||||
last = a.getId();
|
||||
}
|
||||
listOfLists.add(list);
|
||||
}
|
||||
Flux<Object> af = Flux.fromIterable(listOfLists).concatMap(catalogToStore -> Flux.fromIterable(catalogToStore)
|
||||
.parallel(4).runOn(Schedulers.parallel()).concatMap((entity) -> airportRepository.save(entity)));
|
||||
List<Object> saved = af.collectList().block();
|
||||
System.out.println("results.size() : " + saved.size());
|
||||
|
||||
String statement = "select * from `" + /*config().bucketname()*/ "_default" + "` where META().id >= '" + last + "'";
|
||||
System.out.println("statement: " + statement);
|
||||
try {
|
||||
QueryResult qr = couchbaseTemplate.getCouchbaseClientFactory().getScope().query(statement,
|
||||
QueryOptions.queryOptions().profile(QueryProfile.PHASES));
|
||||
List<RemoveResult> rr = couchbaseTemplate.removeByQuery(Airport.class)
|
||||
.withOptions(QueryOptions.queryOptions().scanConsistency(QueryScanConsistency.REQUEST_PLUS)).all();
|
||||
System.out.println(qr.metaData().profile().get());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
List<Airport> airports = airportRepository.findAll().collectList().block();
|
||||
assertEquals(0, airports.size(), "should have been all deleted");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flatMapCB() throws Exception {
|
||||
System.out.println("Start flatMapCB");
|
||||
ParallelFlux<GetResult> concat = Flux.fromIterable(keyList).parallel(2).runOn(Schedulers.parallel())
|
||||
.flatMap(item -> cbGet(item) /* rCollection.get(item) */
|
||||
.doOnSubscribe((x) -> System.out.println(" +" + rCat.incrementAndGet()))
|
||||
.doOnTerminate(() -> System.out.println(" -" + rCat.decrementAndGet())));
|
||||
System.out.println(concat.sequential().collectList().block());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flatMapSyncCB() throws Exception {
|
||||
System.out.println("Start flatMapSyncCB");
|
||||
System.out.println("\n******** Using flatSyncMap() *********");
|
||||
ParallelFlux<GetResult> concat = Flux.fromIterable(keyList).parallel(2).runOn(Schedulers.parallel())
|
||||
.flatMap(item -> Flux.just(cbGetSync(item) /* collection.get(item) */));
|
||||
System.out.println(concat.sequential().collectList().block());
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flatMapVsConcatMapCB2() throws Exception {
|
||||
System.out.println("Start flatMapCB2");
|
||||
System.out.println("\n******** Using flatMap() *********");
|
||||
ParallelFlux<GetResult> flat = Flux.fromIterable(keyList).parallel(1).runOn(Schedulers.parallel())
|
||||
.flatMap(item -> rCollection.get(item).doOnSubscribe((x) -> System.out.println(" +" + rCat.incrementAndGet()))
|
||||
.doOnTerminate(() -> System.out.println(" -" + rCat.getAndDecrement())));
|
||||
System.out.println(flat.sequential().collectList().block());
|
||||
System.out.println("Start concatMapCB");
|
||||
System.out.println("\n******** Using concatMap() *********");
|
||||
ParallelFlux<GetResult> concat = Flux.fromIterable(keyList).parallel(2).runOn(Schedulers.parallel())
|
||||
.concatMap(item -> cbGet(item).doOnSubscribe((x) -> System.out.println(" +" + rCat.incrementAndGet()))
|
||||
.doOnTerminate(() -> System.out.println(" -" + rCat.getAndDecrement())));
|
||||
System.out.println(concat.sequential().collectList().block());
|
||||
;
|
||||
}
|
||||
|
||||
static Random r = new Random();
|
||||
|
||||
static void sleep(long sleepMs) {
|
||||
try {
|
||||
int random = Math.abs(r.nextInt() % 1000);
|
||||
Thread.sleep(sleepMs * random);
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
|
||||
AtomicInteger cbCount = new AtomicInteger();
|
||||
|
||||
Mono<GetResult> cbGet(String id) {
|
||||
// System.out.println(" =" + id);
|
||||
return rCollection.get(id);
|
||||
}
|
||||
|
||||
GetResult cbGetSync(String id) {
|
||||
// System.out.println(id + " +" + rCat.incrementAndGet());
|
||||
GetResult result = collection.get(id);
|
||||
// System.out.println(id + " -" + rCat.getAndDecrement());
|
||||
return result;
|
||||
}
|
||||
|
||||
static String tab(int len) {
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
sb.append(" ");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableReactiveCouchbaseRepositories("org.springframework.data.couchbase")
|
||||
static class Config extends AbstractCouchbaseConfiguration {
|
||||
|
||||
@Override
|
||||
public String getConnectionString() {
|
||||
return connectionString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserName() {
|
||||
return config().adminUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return config().adminPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBucketName() {
|
||||
return bucketName();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
* Copyright 2012-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.couchbase.domain;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.couchbase.client.core.deps.com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.springframework.data.annotation.CreatedBy;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedBy;
|
||||
@@ -53,6 +52,7 @@ public class Person extends AbstractEntity {
|
||||
this();
|
||||
setFirstname(firstname);
|
||||
setLastname(lastname);
|
||||
setMiddlename("Nick");
|
||||
}
|
||||
|
||||
public Person(int id, String firstname, String lastname) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
* Copyright 2012-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,15 +15,16 @@
|
||||
*/
|
||||
package org.springframework.data.couchbase.domain;
|
||||
|
||||
import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.data.couchbase.repository.Query;
|
||||
import org.springframework.data.couchbase.repository.ScanConsistency;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
|
||||
/**
|
||||
* @author Michael Reiche
|
||||
@@ -107,6 +108,9 @@ public interface PersonRepository extends CrudRepository<Person, String> {
|
||||
|
||||
void deleteAll();
|
||||
|
||||
@ScanConsistency(query=QueryScanConsistency.REQUEST_PLUS)
|
||||
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
|
||||
List<Person> findByAddressStreet(String street);
|
||||
|
||||
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
|
||||
List<Person> findByMiddlename(String nickName);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.data.couchbase.domain;
|
||||
|
||||
import org.springframework.data.couchbase.core.RemoveResult;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -30,6 +31,7 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.repository.reactive.ReactiveSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.couchbase.client.java.json.JsonArray;
|
||||
import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
|
||||
/**
|
||||
@@ -55,6 +57,15 @@ public interface ReactiveAirportRepository extends ReactiveSortingRepository<Air
|
||||
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
|
||||
Flux<Airport> findAllByIata(String iata);
|
||||
|
||||
@Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter}")
|
||||
Flux<Airport> findAllPoliciesByApplicableTypes(String state, JsonArray applicableTypes);
|
||||
|
||||
@Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} and icao != $1 ORDER BY effectiveDateTime DESC LIMIT 1")
|
||||
Mono<Airport> findPolicySnapshotByPolicyIdAndEffectiveDateTime(String policyId, long effectiveDateTime);
|
||||
|
||||
@Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} ORDER BY effectiveDateTime DESC")
|
||||
Flux<Airport> findPolicySnapshotAll();
|
||||
|
||||
@Query("#{#n1ql.selectEntity} where iata = $1")
|
||||
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
|
||||
Flux<Airport> getAllByIata(String iata);
|
||||
|
||||
@@ -109,7 +109,7 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
void shouldSaveAndFindAll() {
|
||||
Airport vie = null;
|
||||
try {
|
||||
vie = new Airport("airports::vie", "vie", "loww");
|
||||
vie = new Airport("airports::vie", "vie", "low4");
|
||||
airportRepository.save(vie);
|
||||
List<Airport> all = new ArrayList<>();
|
||||
airportRepository.findAll().forEach(all::add);
|
||||
@@ -133,6 +133,22 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
personRepository.save(person);
|
||||
List<Person> persons = personRepository.findByAddressStreet("Maple");
|
||||
assertEquals(1, persons.size());
|
||||
List<Person> persons2 = personRepository.findByMiddlename("Nick");
|
||||
assertEquals(1, persons2.size());
|
||||
} finally {
|
||||
personRepository.deleteById(person.getId().toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void annotatedFieldFind() {
|
||||
Person person = null;
|
||||
try {
|
||||
person = new Person(1, "first", "last");
|
||||
person.setMiddlename("Nick"); // middlename is stored as nickname
|
||||
personRepository.save(person);
|
||||
List<Person> persons2 = personRepository.findByMiddlename("Nick");
|
||||
assertEquals(1, persons2.size());
|
||||
} finally {
|
||||
personRepository.deleteById(person.getId().toString());
|
||||
}
|
||||
@@ -144,7 +160,7 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
Airport vie = null;
|
||||
Airport xxx = null;
|
||||
try {
|
||||
vie = new Airport("airports::vie", "vie", "loww");
|
||||
vie = new Airport("airports::vie", "vie", "low5");
|
||||
airportRepository.save(vie);
|
||||
xxx = new Airport("airports::xxx", "xxx", "xxxx");
|
||||
airportRepository.save(xxx);
|
||||
@@ -164,7 +180,7 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
void findBySimpleProperty() {
|
||||
Airport vie = null;
|
||||
try {
|
||||
vie = new Airport("airports::vie", "vie", "loww");
|
||||
vie = new Airport("airports::vie", "vie", "low6");
|
||||
vie = airportRepository.save(vie);
|
||||
List<Airport> airports = airportRepository.findAllByIata("vie");
|
||||
assertEquals(1, airports.size());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,11 +22,15 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -72,7 +76,7 @@ public class ReactiveCouchbaseRepositoryQueryIntegrationTests extends JavaIntegr
|
||||
Airport vie = null;
|
||||
Airport jfk = null;
|
||||
try {
|
||||
vie = new Airport("airports::vie", "vie", "loww");
|
||||
vie = new Airport("airports::vie", "vie", "low1");
|
||||
airportRepository.save(vie).block();
|
||||
jfk = new Airport("airports::jfk", "JFK", "xxxx");
|
||||
airportRepository.save(jfk).block();
|
||||
@@ -92,7 +96,7 @@ public class ReactiveCouchbaseRepositoryQueryIntegrationTests extends JavaIntegr
|
||||
void findBySimpleProperty() {
|
||||
Airport vie = null;
|
||||
try {
|
||||
vie = new Airport("airports::vie", "vie", "loww");
|
||||
vie = new Airport("airports::vie", "vie", "low2");
|
||||
airportRepository.save(vie).block();
|
||||
List<Airport> airports1 = airportRepository.findAllByIata("vie").collectList().block();
|
||||
assertEquals(1, airports1.size());
|
||||
@@ -121,6 +125,37 @@ public class ReactiveCouchbaseRepositoryQueryIntegrationTests extends JavaIntegr
|
||||
userRepository.delete(user).block();
|
||||
}
|
||||
|
||||
@Test
|
||||
void limitTest() {
|
||||
Airport vie = new Airport("airports::vie", "vie", "low3");
|
||||
Airport saved1 = airportRepository.save(vie).block();
|
||||
Airport saved2 = airportRepository.save(vie.withId(UUID.randomUUID().toString())).block();
|
||||
try {
|
||||
airportRepository.findAll().collectList().block(); // findAll has QueryScanConsistency;
|
||||
Mono<Airport> airport = airportRepository.findPolicySnapshotByPolicyIdAndEffectiveDateTime("any", 0);
|
||||
System.out.println("------------------------------");
|
||||
System.out.println(airport.block());
|
||||
System.out.println("------------------------------");
|
||||
Flux<Airport> airports = airportRepository.findPolicySnapshotAll();
|
||||
System.out.println(airports.collectList().block());
|
||||
System.out.println("------------------------------");
|
||||
Mono<Airport> ap = getPolicyByIdAndEffectiveDateTime("x", Instant.now());
|
||||
System.out.println(ap.block());
|
||||
} finally {
|
||||
airportRepository.delete(saved1).block();
|
||||
airportRepository.delete(saved2).block();
|
||||
}
|
||||
}
|
||||
|
||||
public Mono<Airport> getPolicyByIdAndEffectiveDateTime(String policyId, Instant effectiveDateTime) {
|
||||
return airportRepository
|
||||
.findPolicySnapshotByPolicyIdAndEffectiveDateTime(policyId, effectiveDateTime.toEpochMilli())
|
||||
// .map(Airport::getEntity)
|
||||
.doOnError(
|
||||
error -> System.out.println("MSG='Exception happened while retrieving Policy by Id and effectiveDateTime', "
|
||||
+ "policyId={}, effectiveDateTime={}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void count() {
|
||||
Set<String> iatas = new HashSet();
|
||||
|
||||
@@ -32,6 +32,8 @@ import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
|
||||
import org.springframework.data.couchbase.core.query.Query;
|
||||
import org.springframework.data.couchbase.domain.Person;
|
||||
import org.springframework.data.couchbase.domain.PersonRepository;
|
||||
import org.springframework.data.couchbase.domain.User;
|
||||
import org.springframework.data.couchbase.domain.UserRepository;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
@@ -75,6 +77,19 @@ class N1qlQueryCreatorTests {
|
||||
assertEquals(query.export(), " WHERE " + where(i("firstname")).is("Oliver").export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createsQueryFieldAnnotationCorrectly() throws Exception {
|
||||
String input = "findByMiddlename";
|
||||
PartTree tree = new PartTree(input, Person.class);
|
||||
Method method = PersonRepository.class.getMethod(input, String.class);
|
||||
|
||||
N1qlQueryCreator creator = new N1qlQueryCreator(tree, getAccessor(getParameters(method), "Oliver"), null, converter,
|
||||
bucketName);
|
||||
Query query = creator.createQuery();
|
||||
|
||||
assertEquals(query.export(), " WHERE " + where(i("nickname")).is("Oliver").export());
|
||||
}
|
||||
|
||||
@Test
|
||||
void queryParametersArray() throws Exception {
|
||||
String input = "findByFirstnameIn";
|
||||
@@ -89,9 +104,9 @@ class N1qlQueryCreatorTests {
|
||||
// Query expected = (new Query()).addCriteria(where("firstname").in("Oliver", "Charles"));
|
||||
assertEquals(expected.export(new int[1]), query.export(new int[1]));
|
||||
JsonObject expectedOptions = JsonObject.create();
|
||||
expected.buildQueryOptions(null).build().injectParams(expectedOptions);
|
||||
expected.buildQueryOptions(null, null).build().injectParams(expectedOptions);
|
||||
JsonObject actualOptions = JsonObject.create();
|
||||
expected.buildQueryOptions(null).build().injectParams(actualOptions);
|
||||
expected.buildQueryOptions(null, null).build().injectParams(actualOptions);
|
||||
assertEquals(expectedOptions.removeKey("client_context_id"), actualOptions.removeKey("client_context_id"));
|
||||
}
|
||||
|
||||
@@ -111,9 +126,9 @@ class N1qlQueryCreatorTests {
|
||||
Query expected = (new Query()).addCriteria(where(i("firstname")).in("Oliver", "Charles"));
|
||||
assertEquals(expected.export(new int[1]), query.export(new int[1]));
|
||||
JsonObject expectedOptions = JsonObject.create();
|
||||
expected.buildQueryOptions(null).build().injectParams(expectedOptions);
|
||||
expected.buildQueryOptions(null, null).build().injectParams(expectedOptions);
|
||||
JsonObject actualOptions = JsonObject.create();
|
||||
expected.buildQueryOptions(null).build().injectParams(actualOptions);
|
||||
expected.buildQueryOptions(null, null).build().injectParams(actualOptions);
|
||||
assertEquals(expectedOptions.removeKey("client_context_id"), actualOptions.removeKey("client_context_id"));
|
||||
}
|
||||
|
||||
@@ -133,9 +148,9 @@ class N1qlQueryCreatorTests {
|
||||
|
||||
assertEquals(expected.export(new int[1]), query.export(new int[1]));
|
||||
JsonObject expectedOptions = JsonObject.create();
|
||||
expected.buildQueryOptions(null).build().injectParams(expectedOptions);
|
||||
expected.buildQueryOptions(null, null).build().injectParams(expectedOptions);
|
||||
JsonObject actualOptions = JsonObject.create();
|
||||
expected.buildQueryOptions(null).build().injectParams(actualOptions);
|
||||
expected.buildQueryOptions(null, null).build().injectParams(actualOptions);
|
||||
assertEquals(expectedOptions.removeKey("client_context_id"), actualOptions.removeKey("client_context_id"));
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
|
||||
import org.springframework.data.couchbase.core.CouchbaseTemplate;
|
||||
import org.springframework.data.couchbase.core.ExecutableFindByQueryOperation;
|
||||
import org.springframework.data.couchbase.core.ExecutableFindByQueryOperation.ExecutableFindByQuery;
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext;
|
||||
@@ -101,7 +101,7 @@ class StringN1qlQueryCreatorTests extends ClusterAwareIntegrationTests {
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
} catch (Exception e) {}
|
||||
ExecutableFindByQueryOperation.ExecutableFindByQuery q = (ExecutableFindByQueryOperation.ExecutableFindByQuery) couchbaseTemplate
|
||||
ExecutableFindByQuery q = (ExecutableFindByQuery) couchbaseTemplate
|
||||
.findByQuery(Airline.class).matching(query);
|
||||
|
||||
Optional<Airline> al = q.one();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.couchbase.util;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Optional;
|
||||
@@ -113,31 +114,57 @@ public abstract class ClusterAwareIntegrationTests {
|
||||
public void afterEach() {}
|
||||
|
||||
/**
|
||||
* This should probably be the first call in the @BeforeAll method of a test class.
|
||||
* This will call super.beforeAll() when called as callSuperBeforeAll(new Object() {}); this trickery is necessary
|
||||
* because super.beforeAll() cannot be used because it is a static method. it is possible and likely that the
|
||||
* beforeAll() method of should still be called even when a test class defines its own beforeAll() method which would
|
||||
* hide the beforeAll() of the super class.
|
||||
* This trickery is not necessary for before/AfterEach, as those are not static methods
|
||||
* This should probably be the first call in the @BeforeAll method of a test class. This will call super @BeforeAll
|
||||
* methods when called as callSuperBeforeAll(new Object() {}); this trickery is necessary because super.beforeAll()
|
||||
* cannot be used because it is a static method. it is possible and likely that the beforeAll() method of should still
|
||||
* be called even when a test class defines its own beforeAll() method which would hide the beforeAll() of the super
|
||||
* class. This trickery is not necessary for before/AfterEach, as those are not static methods
|
||||
*
|
||||
* @Author Michael Reiche
|
||||
*
|
||||
* @param createdHere - an object from a class defined in the calling class
|
||||
*/
|
||||
public static void callSuperBeforeAll(Object createdHere) {
|
||||
callSuper(createdHere, "beforeAll");
|
||||
callSuper(createdHere, BeforeAll.class);
|
||||
}
|
||||
|
||||
// see comments for callSuperBeforeAll()
|
||||
public static void callSuperAfterAll(Object createdHere) {
|
||||
callSuper(createdHere, "afterAll");
|
||||
callSuper(createdHere, AfterAll.class);
|
||||
}
|
||||
|
||||
private static void callSuper(Object createdHere, String methodName) {
|
||||
private static void callSuper(Object createdHere, Class annotationClass) {
|
||||
try {
|
||||
Method method = createdHere.getClass().getEnclosingClass().getSuperclass().getMethod(methodName);
|
||||
method.invoke(null);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
Class<?> encClass = createdHere.getClass().getEnclosingClass();
|
||||
Class<?> theClass = encClass;
|
||||
Annotation annotation = null;
|
||||
Method invokedSuper = null;
|
||||
if (annotationClass != BeforeAll.class && annotationClass != AfterAll.class) {
|
||||
throw new RuntimeException("can only call super for BeforeAll and AfterAll " + annotationClass);
|
||||
}
|
||||
// look recursively for @BeforeAll or @AfterAll methods
|
||||
// when one is found and executed, do not continue the recursive search
|
||||
// as it is expected that the @BeforeAll or @AfterAll methods call
|
||||
// any super methods explicitly - perhaps using callSuperBeforeAll() or callSuperAfterAll()
|
||||
// Note that if the @BeforeAll and @AfterAll methods have different names, they will be
|
||||
// called twice - once by this callSuper() mechanism and once by junit as the method will not be hidden
|
||||
while ((theClass = theClass.getSuperclass()) != null) {
|
||||
Method[] methods = theClass.getMethods();
|
||||
for (Method m : methods) {
|
||||
annotation = m.getAnnotation(annotationClass);
|
||||
if (annotation != null) {
|
||||
if (annotation != null) {
|
||||
m.invoke(null);
|
||||
invokedSuper = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invokedSuper != null) { // called method is responsible for calling any super methods
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ import static org.springframework.data.couchbase.config.BeanNames.COUCHBASE_TEMP
|
||||
import static org.springframework.data.couchbase.config.BeanNames.REACTIVE_COUCHBASE_TEMPLATE;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
@@ -34,7 +36,8 @@ import com.couchbase.client.java.Cluster;
|
||||
import com.couchbase.client.java.ClusterOptions;
|
||||
import com.couchbase.client.java.env.ClusterEnvironment;
|
||||
import com.couchbase.client.java.manager.collection.CollectionManager;
|
||||
import org.springframework.data.couchbase.domain.ConfigScoped;
|
||||
import com.couchbase.client.java.manager.collection.CollectionSpec;
|
||||
import com.couchbase.client.java.manager.collection.ScopeSpec;
|
||||
|
||||
/**
|
||||
* Provides Collection support for integration tests
|
||||
@@ -43,8 +46,10 @@ import org.springframework.data.couchbase.domain.ConfigScoped;
|
||||
*/
|
||||
public class CollectionAwareIntegrationTests extends JavaIntegrationTests {
|
||||
|
||||
public static String scopeName = "scope_" + randomString();
|
||||
public static String collectionName = "collection_" + randomString();
|
||||
public static String scopeName = "my_scope";// + randomString();
|
||||
public static String otherScope = "other_scope";
|
||||
public static String collectionName = "my_collection";// + randomString();
|
||||
public static String otherCollection = "other_collection";// + randomString();
|
||||
|
||||
@BeforeAll
|
||||
public static void beforeAll() {
|
||||
@@ -57,20 +62,27 @@ public class CollectionAwareIntegrationTests extends JavaIntegrationTests {
|
||||
waitForService(bucket, ServiceType.QUERY);
|
||||
waitForQueryIndexerToHaveBucket(cluster, config().bucketname());
|
||||
CollectionManager collectionManager = bucket.collections();
|
||||
if (scopeName != null || collectionName != null) {
|
||||
setupScopeCollection(cluster, scopeName, collectionName, collectionManager);
|
||||
|
||||
setupScopeCollection(cluster, scopeName, collectionName, collectionManager);
|
||||
if (otherScope != null || otherCollection != null) {
|
||||
// afterAll should be undoing the creation of scope etc
|
||||
setupScopeCollection(cluster, otherScope, otherCollection, collectionManager);
|
||||
}
|
||||
|
||||
ConfigScoped.setScopeName(scopeName);
|
||||
ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigScoped.class);
|
||||
Config.setScopeName(scopeName);
|
||||
ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
|
||||
// the Config class has been modified, these need to be loaded again
|
||||
couchbaseTemplate = (CouchbaseTemplate) ac.getBean(COUCHBASE_TEMPLATE);
|
||||
reactiveCouchbaseTemplate = (ReactiveCouchbaseTemplate) ac.getBean(REACTIVE_COUCHBASE_TEMPLATE);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void afterAll(){
|
||||
System.out.println("CollectionAwareIntegrationTests.afterAll()");
|
||||
ConfigScoped.setScopeName(null);
|
||||
callSuperBeforeAll(new Object() {});
|
||||
public static void afterAll() {
|
||||
Config.setScopeName(null);
|
||||
ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
|
||||
// the Config class has been modified, these need to be loaded again
|
||||
couchbaseTemplate = (CouchbaseTemplate) ac.getBean(COUCHBASE_TEMPLATE);
|
||||
reactiveCouchbaseTemplate = (ReactiveCouchbaseTemplate) ac.getBean(REACTIVE_COUCHBASE_TEMPLATE);
|
||||
callSuperAfterAll(new Object() {});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors
|
||||
* Copyright 2020-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,15 +39,16 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.couchbase.client.core.io.CollectionIdentifier;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Timeout;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.data.couchbase.CouchbaseClientFactory;
|
||||
import org.springframework.data.couchbase.SimpleCouchbaseClientFactory;
|
||||
import org.springframework.data.couchbase.core.CouchbaseTemplate;
|
||||
import org.springframework.data.couchbase.core.ReactiveCouchbaseTemplate;
|
||||
import org.springframework.data.couchbase.domain.Config;
|
||||
|
||||
import com.couchbase.client.core.diagnostics.PingResult;
|
||||
import com.couchbase.client.core.diagnostics.PingState;
|
||||
@@ -80,7 +81,6 @@ import com.couchbase.client.java.query.QueryOptions;
|
||||
import com.couchbase.client.java.query.QueryResult;
|
||||
import com.couchbase.client.java.search.SearchQuery;
|
||||
import com.couchbase.client.java.search.result.SearchResult;
|
||||
import org.springframework.data.couchbase.domain.Config;
|
||||
|
||||
/**
|
||||
* Extends the {@link ClusterAwareIntegrationTests} with java-client specific code.
|
||||
@@ -91,8 +91,9 @@ import org.springframework.data.couchbase.domain.Config;
|
||||
@Timeout(value = 10, unit = TimeUnit.MINUTES) // Safety timer so tests can't block CI executors
|
||||
public class JavaIntegrationTests extends ClusterAwareIntegrationTests {
|
||||
|
||||
@Autowired static public CouchbaseTemplate couchbaseTemplate;
|
||||
@Autowired static public ReactiveCouchbaseTemplate reactiveCouchbaseTemplate;
|
||||
// Autowired annotation is not supported on static fields
|
||||
static public CouchbaseTemplate couchbaseTemplate;
|
||||
static public ReactiveCouchbaseTemplate reactiveCouchbaseTemplate;
|
||||
|
||||
@BeforeAll
|
||||
public static void beforeAll() {
|
||||
@@ -141,15 +142,28 @@ public class JavaIntegrationTests extends ClusterAwareIntegrationTests {
|
||||
ScopeSpec scopeSpec = ScopeSpec.create(scopeName);
|
||||
CollectionSpec collSpec = CollectionSpec.create(collectionName, scopeName);
|
||||
|
||||
if (!scopeName.equals("_default")) {
|
||||
collectionManager.createScope(scopeName);
|
||||
if (!scopeName.equals(CollectionIdentifier.DEFAULT_SCOPE)) {
|
||||
try {
|
||||
collectionManager.createScope(scopeName);
|
||||
waitUntilCondition(() -> scopeExists(collectionManager, scopeName));
|
||||
ScopeSpec found = collectionManager.getScope(scopeName);
|
||||
assertEquals(scopeSpec, found);
|
||||
} catch (CouchbaseException e) {
|
||||
if (!e.toString().contains("already exists")) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
waitUntilCondition(() -> scopeExists(collectionManager, scopeName));
|
||||
ScopeSpec found = collectionManager.getScope(scopeName);
|
||||
assertEquals(scopeSpec, found);
|
||||
|
||||
collectionManager.createCollection(collSpec);
|
||||
try {
|
||||
collectionManager.createCollection(collSpec);
|
||||
} catch (CouchbaseException e) {
|
||||
if (!e.toString().contains("already exists")) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
waitUntilCondition(() -> collectionExists(collectionManager, collSpec));
|
||||
waitUntilCondition(
|
||||
() -> collectionReady(cluster.bucket(config().bucketname()).scope(scopeName).collection(collectionName)));
|
||||
@@ -258,6 +272,7 @@ public class JavaIntegrationTests extends ClusterAwareIntegrationTests {
|
||||
String collectionName) {
|
||||
CreatePrimaryQueryIndexOptions options = CreatePrimaryQueryIndexOptions.createPrimaryQueryIndexOptions();
|
||||
options.timeout(Duration.ofSeconds(300));
|
||||
options.ignoreIfExists(true);
|
||||
final CreatePrimaryQueryIndexOptions.Built builtOpts = options.build();
|
||||
final String indexName = builtOpts.indexName().orElse(null);
|
||||
|
||||
@@ -335,7 +350,6 @@ public class JavaIntegrationTests extends ClusterAwareIntegrationTests {
|
||||
break;
|
||||
} catch (CouchbaseException | IllegalStateException ex) {
|
||||
// this is a pretty dirty hack to avoid a race where we don't know if the index is ready yet
|
||||
System.out.println("createFtsCollectionIndex: " + i + " " + ex);
|
||||
if (i < (maxTries - 1) && (ex.getMessage().contains("no planPIndexes for indexName")
|
||||
|| ex.getMessage().contains("pindex_consistency mismatched partition")
|
||||
|| ex.getMessage().contains("pindex not available"))) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
* Copyright 2012-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.couchbase.util;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.*;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import okhttp3.Credentials;
|
||||
import okhttp3.FormBody;
|
||||
@@ -43,6 +43,7 @@ public class UnmanagedTestCluster extends TestCluster {
|
||||
private final String adminPassword;
|
||||
private final int numReplicas;
|
||||
private volatile String bucketname;
|
||||
private long startTime = System.currentTimeMillis();
|
||||
|
||||
UnmanagedTestCluster(final Properties properties) {
|
||||
seedHost = properties.getProperty("cluster.unmanaged.seed").split(":")[0];
|
||||
@@ -69,8 +70,9 @@ public class UnmanagedTestCluster extends TestCluster {
|
||||
.build())
|
||||
.execute();
|
||||
|
||||
if (postResponse.code() != 202) {
|
||||
throw new Exception("Could not create bucket: " + postResponse + ", Reason: " + postResponse.body().string());
|
||||
String reason = postResponse.body().string();
|
||||
if (postResponse.code() != 202 && !(reason.contains("Bucket with given name already exists"))) {
|
||||
throw new Exception("Could not create bucket: " + postResponse + ", Reason: " + reason);
|
||||
}
|
||||
|
||||
Response getResponse = httpClient
|
||||
@@ -140,10 +142,13 @@ public class UnmanagedTestCluster extends TestCluster {
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
httpClient
|
||||
.newCall(new Request.Builder().header("Authorization", Credentials.basic(adminUsername, adminPassword))
|
||||
.url("http://" + seedHost + ":" + seedPort + "/pools/default/buckets/" + bucketname).delete().build())
|
||||
.execute();
|
||||
if (!bucketname.equals("my_bucket")) {
|
||||
httpClient
|
||||
.newCall(new Request.Builder().header("Authorization", Credentials.basic(adminUsername, adminPassword))
|
||||
.url("http://" + seedHost + ":" + seedPort + "/pools/default/buckets/" + bucketname).delete().build())
|
||||
.execute();
|
||||
}
|
||||
System.out.println("elapsed: " + (System.currentTimeMillis() - startTime));
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user