From 48f397c7361c77af176f4e4af1a472402773f50c Mon Sep 17 00:00:00 2001 From: mikereiche Date: Fri, 1 Oct 2021 11:45:00 -0700 Subject: [PATCH] Reinstate the getDefaultConsistency() method in the Configuration. Closes #1243. --- .../AbstractCouchbaseConfiguration.java | 12 +- .../couchbase/core/CouchbaseOperations.java | 6 + .../couchbase/core/CouchbaseTemplate.java | 17 ++- .../core/ReactiveCouchbaseOperations.java | 6 + .../core/ReactiveCouchbaseTemplate.java | 18 ++- .../ReactiveFindByQueryOperationSupport.java | 6 +- ...ReactiveRemoveByQueryOperationSupport.java | 3 +- .../couchbase/core/query/OptionsBuilder.java | 13 +- .../couchbase/domain/AirportRepository.java | 1 - .../AirportRepositoryScanConsistencyTest.java | 31 ++++ .../data/couchbase/domain/Config.java | 9 +- ...chbaseRepositoryQueryIntegrationTests.java | 139 ++++++++++++++++-- 12 files changed, 230 insertions(+), 31 deletions(-) create mode 100644 src/test/java/org/springframework/data/couchbase/domain/AirportRepositoryScanConsistencyTest.java diff --git a/src/main/java/org/springframework/data/couchbase/config/AbstractCouchbaseConfiguration.java b/src/main/java/org/springframework/data/couchbase/config/AbstractCouchbaseConfiguration.java index c15bbfb7e..2c9ff9718 100644 --- a/src/main/java/org/springframework/data/couchbase/config/AbstractCouchbaseConfiguration.java +++ b/src/main/java/org/springframework/data/couchbase/config/AbstractCouchbaseConfiguration.java @@ -57,6 +57,7 @@ import com.couchbase.client.java.env.ClusterEnvironment; import com.couchbase.client.java.json.JacksonTransformers; import com.couchbase.client.java.json.JsonValueModule; +import com.couchbase.client.java.query.QueryScanConsistency; import com.fasterxml.jackson.databind.ObjectMapper; /** @@ -156,7 +157,8 @@ protected void configureEnvironment(final ClusterEnvironment.Builder builder) { @Bean(name = BeanNames.COUCHBASE_TEMPLATE) public CouchbaseTemplate couchbaseTemplate(CouchbaseClientFactory couchbaseClientFactory, MappingCouchbaseConverter mappingCouchbaseConverter, TranslationService couchbaseTranslationService) { - return new CouchbaseTemplate(couchbaseClientFactory, mappingCouchbaseConverter, couchbaseTranslationService); + return new CouchbaseTemplate(couchbaseClientFactory, mappingCouchbaseConverter, couchbaseTranslationService, + getDefaultConsistency()); } public CouchbaseTemplate couchbaseTemplate(CouchbaseClientFactory couchbaseClientFactory, @@ -167,8 +169,8 @@ public CouchbaseTemplate couchbaseTemplate(CouchbaseClientFactory couchbaseClien @Bean(name = BeanNames.REACTIVE_COUCHBASE_TEMPLATE) public ReactiveCouchbaseTemplate reactiveCouchbaseTemplate(CouchbaseClientFactory couchbaseClientFactory, MappingCouchbaseConverter mappingCouchbaseConverter, TranslationService couchbaseTranslationService) { - return new ReactiveCouchbaseTemplate(couchbaseClientFactory, mappingCouchbaseConverter, - couchbaseTranslationService); + return new ReactiveCouchbaseTemplate(couchbaseClientFactory, mappingCouchbaseConverter, couchbaseTranslationService, + getDefaultConsistency()); } public ReactiveCouchbaseTemplate reactiveCouchbaseTemplate(CouchbaseClientFactory couchbaseClientFactory, @@ -376,4 +378,8 @@ private boolean nonShadowedJacksonPresent() { } } + public QueryScanConsistency getDefaultConsistency() { + return null; + } + } diff --git a/src/main/java/org/springframework/data/couchbase/core/CouchbaseOperations.java b/src/main/java/org/springframework/data/couchbase/core/CouchbaseOperations.java index 3385278bd..33ce0791a 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseOperations.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseOperations.java @@ -19,6 +19,8 @@ import org.springframework.data.couchbase.CouchbaseClientFactory; import org.springframework.data.couchbase.core.convert.CouchbaseConverter; +import com.couchbase.client.java.query.QueryScanConsistency; + /** * Defines common operations on the Couchbase data source, most commonly implemented by {@link CouchbaseTemplate}. */ @@ -44,4 +46,8 @@ public interface CouchbaseOperations extends FluentCouchbaseOperations { */ CouchbaseClientFactory getCouchbaseClientFactory(); + /** + * Returns the default consistency to use for queries + */ + QueryScanConsistency getConsistency(); } diff --git a/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java b/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java index a3fa295e8..4bf781210 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java @@ -32,6 +32,7 @@ import org.springframework.lang.Nullable; import com.couchbase.client.java.Collection; +import com.couchbase.client.java.query.QueryScanConsistency; /** * Implements lower-level couchbase operations on top of the SDK with entity mapping capabilities. @@ -49,6 +50,7 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationContex private final MappingContext, CouchbasePersistentProperty> mappingContext; private final ReactiveCouchbaseTemplate reactiveCouchbaseTemplate; private @Nullable CouchbasePersistentEntityIndexCreator indexCreator; + private QueryScanConsistency scanConsistency; public CouchbaseTemplate(final CouchbaseClientFactory clientFactory, final CouchbaseConverter converter) { this(clientFactory, converter, new JacksonTranslationService()); @@ -56,11 +58,17 @@ public CouchbaseTemplate(final CouchbaseClientFactory clientFactory, final Couch public CouchbaseTemplate(final CouchbaseClientFactory clientFactory, final CouchbaseConverter converter, final TranslationService translationService) { + this(clientFactory, converter, translationService, null); + } + + public CouchbaseTemplate(final CouchbaseClientFactory clientFactory, final CouchbaseConverter converter, + final TranslationService translationService, QueryScanConsistency scanConsistency) { this.clientFactory = clientFactory; this.converter = converter; this.templateSupport = new CouchbaseTemplateSupport(this, converter, translationService); - this.reactiveCouchbaseTemplate = new ReactiveCouchbaseTemplate(clientFactory, converter, translationService); - + this.reactiveCouchbaseTemplate = new ReactiveCouchbaseTemplate(clientFactory, converter, translationService, + scanConsistency); + this.scanConsistency = scanConsistency; this.mappingContext = this.converter.getMappingContext(); if (mappingContext instanceof CouchbaseMappingContext) { CouchbaseMappingContext cmc = (CouchbaseMappingContext) mappingContext; @@ -147,6 +155,11 @@ public CouchbaseClientFactory getCouchbaseClientFactory() { return clientFactory; } + @Override + public QueryScanConsistency getConsistency() { + return scanConsistency; + } + /** * Provides access to a {@link Collection} on the configured {@link CouchbaseClientFactory}. * diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveCouchbaseOperations.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveCouchbaseOperations.java index f3b97d35a..81b8cfdef 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveCouchbaseOperations.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveCouchbaseOperations.java @@ -18,6 +18,8 @@ import org.springframework.data.couchbase.CouchbaseClientFactory; import org.springframework.data.couchbase.core.convert.CouchbaseConverter; +import com.couchbase.client.java.query.QueryScanConsistency; + /** * Defines common operations on the Couchbase data source, most commonly implemented by * {@link ReactiveCouchbaseTemplate}. @@ -47,4 +49,8 @@ public interface ReactiveCouchbaseOperations extends ReactiveFluentCouchbaseOper */ CouchbaseClientFactory getCouchbaseClientFactory(); + /** + * @return the default consistency to use for queries + */ + QueryScanConsistency getConsistency(); } diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplate.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplate.java index f62b26b20..260bbd445 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplate.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplate.java @@ -28,6 +28,7 @@ import org.springframework.data.couchbase.core.support.PseudoArgs; import com.couchbase.client.java.Collection; +import com.couchbase.client.java.query.QueryScanConsistency; /** * template class for Reactive Couchbase operations @@ -43,7 +44,8 @@ public class ReactiveCouchbaseTemplate implements ReactiveCouchbaseOperations, A private final CouchbaseConverter converter; private final PersistenceExceptionTranslator exceptionTranslator; private final ReactiveCouchbaseTemplateSupport templateSupport; - private ThreadLocal> threadLocalArgs = null; + private ThreadLocal> threadLocalArgs = new ThreadLocal<>(); + private QueryScanConsistency scanConsistency; public ReactiveCouchbaseTemplate(final CouchbaseClientFactory clientFactory, final CouchbaseConverter converter) { this(clientFactory, converter, new JacksonTranslationService()); @@ -51,10 +53,16 @@ public ReactiveCouchbaseTemplate(final CouchbaseClientFactory clientFactory, fin public ReactiveCouchbaseTemplate(final CouchbaseClientFactory clientFactory, final CouchbaseConverter converter, final TranslationService translationService) { + this(clientFactory, converter, translationService, null); + } + + public ReactiveCouchbaseTemplate(final CouchbaseClientFactory clientFactory, final CouchbaseConverter converter, + final TranslationService translationService, QueryScanConsistency scanConsistency) { this.clientFactory = clientFactory; this.converter = converter; this.exceptionTranslator = clientFactory.getExceptionTranslator(); this.templateSupport = new ReactiveCouchbaseTemplateSupport(this, converter, translationService); + this.scanConsistency = scanConsistency; } @Override @@ -182,4 +190,12 @@ public void setPseudoArgs(PseudoArgs threadLocalArgs) { this.threadLocalArgs.set(threadLocalArgs); } + /** + * {@inheritDoc} + */ + @Override + public QueryScanConsistency getConsistency() { + return scanConsistency; + } + } diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java index e87f3eaea..d5dd83ccf 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java @@ -206,9 +206,9 @@ public Flux all() { })); } - private QueryOptions buildOptions(QueryOptions options) { - QueryOptions opts = query.buildQueryOptions(options, scanConsistency); - return opts; + public QueryOptions buildOptions(QueryOptions options) { + QueryScanConsistency qsc = scanConsistency != null ? scanConsistency : template.getConsistency(); + return query.buildQueryOptions(options, qsc); } @Override diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java index efcd86583..d6ea991d6 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java @@ -90,7 +90,8 @@ public Flux all() { } private QueryOptions buildQueryOptions(QueryOptions options) { - return query.buildQueryOptions(options, scanConsistency); + QueryScanConsistency qsc = scanConsistency != null ? scanConsistency : template.getConsistency(); + return query.buildQueryOptions(options, qsc); } @Override diff --git a/src/main/java/org/springframework/data/couchbase/core/query/OptionsBuilder.java b/src/main/java/org/springframework/data/couchbase/core/query/OptionsBuilder.java index 36cd9d355..930737095 100644 --- a/src/main/java/org/springframework/data/couchbase/core/query/OptionsBuilder.java +++ b/src/main/java/org/springframework/data/couchbase/core/query/OptionsBuilder.java @@ -381,13 +381,14 @@ public static V annotationAttribute(Class annotatio for (AnnotatedElement el : elements) { A an = AnnotatedElementUtils.findMergedAnnotation(el, annotation); if (an != null) { - if (defaultValue != null && !defaultValue.equals(an)) { - try { - Method m = an.getClass().getMethod(attributeName); - return (V) m.invoke(an); - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); + try { + Method m = an.getClass().getMethod(attributeName); + V result = (V) m.invoke(an); + if (result != null && !result.equals(defaultValue)) { + return result; } + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); } } } diff --git a/src/test/java/org/springframework/data/couchbase/domain/AirportRepository.java b/src/test/java/org/springframework/data/couchbase/domain/AirportRepository.java index 7bdae87dc..327557bd2 100644 --- a/src/test/java/org/springframework/data/couchbase/domain/AirportRepository.java +++ b/src/test/java/org/springframework/data/couchbase/domain/AirportRepository.java @@ -60,7 +60,6 @@ // @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) public interface AirportRepository extends CouchbaseRepository, DynamicProxyable { - // override an annotate with REQUEST_PLUS @Override @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) List findAll(); diff --git a/src/test/java/org/springframework/data/couchbase/domain/AirportRepositoryScanConsistencyTest.java b/src/test/java/org/springframework/data/couchbase/domain/AirportRepositoryScanConsistencyTest.java new file mode 100644 index 000000000..a49dc732b --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/domain/AirportRepositoryScanConsistencyTest.java @@ -0,0 +1,31 @@ +/* + * 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. + * 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.repository.CouchbaseRepository; +import org.springframework.stereotype.Repository; + +/** + * Airport repository for testing
+ * + * @author Michael Reiche + */ +@Repository +public interface AirportRepositoryScanConsistencyTest extends CouchbaseRepository { + +} + diff --git a/src/test/java/org/springframework/data/couchbase/domain/Config.java b/src/test/java/org/springframework/data/couchbase/domain/Config.java index fbdf3d57e..bfedc1b9f 100644 --- a/src/test/java/org/springframework/data/couchbase/domain/Config.java +++ b/src/test/java/org/springframework/data/couchbase/domain/Config.java @@ -18,12 +18,9 @@ import java.lang.reflect.InvocationTargetException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.auditing.DateTimeProvider; -import org.springframework.data.convert.CustomConversions; import org.springframework.data.couchbase.CouchbaseClientFactory; import org.springframework.data.couchbase.SimpleCouchbaseClientFactory; import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; @@ -159,14 +156,16 @@ public void configureRepositoryOperationsMapping(RepositoryOperationsMapping bas // will be used instead of the result of this call (the client factory arg is different) public ReactiveCouchbaseTemplate myReactiveCouchbaseTemplate(CouchbaseClientFactory couchbaseClientFactory, MappingCouchbaseConverter mappingCouchbaseConverter) { - return new ReactiveCouchbaseTemplate(couchbaseClientFactory, mappingCouchbaseConverter); + return new ReactiveCouchbaseTemplate(couchbaseClientFactory, mappingCouchbaseConverter, + new JacksonTranslationService(), getDefaultConsistency()); } // do not use couchbaseTemplate for the name of this method, otherwise the value of that been // will be used instead of the result from this call (the client factory arg is different) public CouchbaseTemplate myCouchbaseTemplate(CouchbaseClientFactory couchbaseClientFactory, MappingCouchbaseConverter mappingCouchbaseConverter) { - return new CouchbaseTemplate(couchbaseClientFactory, mappingCouchbaseConverter); + return new CouchbaseTemplate(couchbaseClientFactory, mappingCouchbaseConverter, new JacksonTranslationService(), + getDefaultConsistency()); } // do not use couchbaseClientFactory for the name of this method, otherwise the value of that bean will diff --git a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java index 58b7169e9..c4d1f9f30 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java @@ -16,6 +16,8 @@ package org.springframework.data.couchbase.repository; +import static com.couchbase.client.java.query.QueryScanConsistency.NOT_BOUNDED; +import static com.couchbase.client.java.query.QueryScanConsistency.REQUEST_PLUS; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -25,6 +27,7 @@ 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 static org.springframework.data.couchbase.config.BeanNames.COUCHBASE_TEMPLATE; import junit.framework.AssertionFailedError; @@ -46,6 +49,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataIntegrityViolationException; @@ -63,6 +68,7 @@ import org.springframework.data.couchbase.domain.Airport; import org.springframework.data.couchbase.domain.AirportMini; import org.springframework.data.couchbase.domain.AirportRepository; +import org.springframework.data.couchbase.domain.AirportRepositoryScanConsistencyTest; import org.springframework.data.couchbase.domain.NaiveAuditorAware; import org.springframework.data.couchbase.domain.Person; import org.springframework.data.couchbase.domain.PersonRepository; @@ -267,6 +273,80 @@ void findBySimplePropertyReturnType() { } } + @Test + public void saveNotBoundedRequestPlus() { + ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigRequestPlus.class); + // the Config class has been modified, these need to be loaded again + CouchbaseTemplate couchbaseTemplateRP = (CouchbaseTemplate) ac.getBean(COUCHBASE_TEMPLATE); + AirportRepository airportRepositoryRP = (AirportRepository) ac.getBean("airportRepository"); + + // save() followed by query with NOT_BOUNDED will result in not finding the document + Airport vie = new Airport("airports::vie", "vie", "low9"); + Airport airport2 = null; + for (int i = 1; i <= 100; i++) { + // set version == 0 so save() will be an upsert, not a replace + Airport saved = airportRepositoryRP.save(vie.clearVersion()); + try { + airport2 = airportRepositoryRP.iata(saved.getIata()); + if (airport2 == null) { + break; + } + } catch (DataRetrievalFailureException drfe) { + airport2 = null; // + } finally { + // airportRepository.delete(vie); + // instead of delete, use removeResult to test QueryOptions.consistentWith() + RemoveResult removeResult = couchbaseTemplateRP.removeById().one(vie.getId()); + assertEquals(vie.getId(), removeResult.getId()); + assertTrue(removeResult.getCas() != 0); + assertTrue(removeResult.getMutationToken().isPresent()); + Airport airport3 = airportRepositoryRP.iata(vie.getIata()); + assertNull(airport3, "should have been removed"); + } + } + assertNotNull(airport2, "airport2 should have never been null"); + Airport saved = airportRepositoryRP.save(vie.clearVersion()); + List airports = couchbaseTemplateRP.findByQuery(Airport.class).withConsistency(NOT_BOUNDED).all(); + RemoveResult removeResult = couchbaseTemplateRP.removeById().one(saved.getId()); + assertFalse(!airports.isEmpty(), "airports should have been empty"); + } + + @Test + public void saveNotBoundedWithDefaultRepository() { + + ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class); + // the Config class has been modified, these need to be loaded again + CouchbaseTemplate couchbaseTemplateRP = (CouchbaseTemplate) ac.getBean(COUCHBASE_TEMPLATE); + AirportRepositoryScanConsistencyTest airportRepositoryRP = (AirportRepositoryScanConsistencyTest) ac.getBean("airportRepositoryScanConsistencyTest"); + + List sizeBeforeTest = airportRepositoryRP.findAll(); + assertEquals(0, sizeBeforeTest.size()); + + Airport vie = new Airport("airports::vie", "vie" , "low9"); + Airport saved = airportRepositoryRP.save(vie); + List allSaved = airportRepositoryRP.findAll(); + couchbaseTemplate.removeById(Airport.class).one(saved.getId()); + assertNotEquals( 1, allSaved.size(),"should not have found 1 airport"); + } + + @Test + public void saveRequestPlusWithDefaultRepository() { + + ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigRequestPlus.class); + // the Config class has been modified, these need to be loaded again + AirportRepositoryScanConsistencyTest airportRepositoryRP = (AirportRepositoryScanConsistencyTest) ac.getBean("airportRepositoryScanConsistencyTest"); + + List sizeBeforeTest = airportRepositoryRP.findAll(); + assertEquals(0, sizeBeforeTest.size()); + + Airport vie = new Airport("airports::vie", "vie" , "low9"); + Airport saved = airportRepositoryRP.save(vie); + List allSaved = airportRepositoryRP.findAll(); + couchbaseTemplate.removeById(Airport.class).one(saved.getId()); + assertEquals( 1, allSaved.size(),"should have found 1 airport"); + } + + @Test void findByTypeAlias() { Airport vie = null; @@ -386,9 +466,7 @@ public void saveNotBounded() { // set version == 0 so save() will be an upsert, not a replace Airport saved = airportRepository.save(vie.clearVersion()); try { - airport2 = airportRepository - .withOptions(QueryOptions.queryOptions().scanConsistency(QueryScanConsistency.NOT_BOUNDED)) - .iata(saved.getIata()); + airport2 = airportRepository.iata(saved.getIata()); if (airport2 == null) { break; } @@ -401,14 +479,16 @@ public void saveNotBounded() { assertEquals(vie.getId(), removeResult.getId()); assertTrue(removeResult.getCas() != 0); assertTrue(removeResult.getMutationToken().isPresent()); - Airport airport3 = airportRepository - .withOptions(QueryOptions.queryOptions().scanConsistency(QueryScanConsistency.REQUEST_PLUS) - .consistentWith(MutationState.from(removeResult.getMutationToken().get()))) - .iata(vie.getIata()); + Airport airport3 = airportRepository.iata(vie.getIata()); assertNull(airport3, "should have been removed"); } } assertNull(airport2, "airport2 should have likely been null at least once"); + Airport saved = airportRepository.save(vie.clearVersion()); + couchbaseTemplate.findByQuery(Airport.class).withConsistency(REQUEST_PLUS).all(); + airport2 = airportRepository.iata(vie.getIata()); + RemoveResult removeResult = couchbaseTemplate.removeById().one(saved.getId()); + assertNotNull(airport2, "airport2 should have been found"); } @Test @@ -474,7 +554,7 @@ void count() { airportRepository.saveAll( Arrays.stream(iatas).map((iata) -> new Airport("airports::" + iata, iata, iata.toLowerCase(Locale.ROOT))) .collect(Collectors.toSet())); - couchbaseTemplate.findByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all(); + couchbaseTemplate.findByQuery(Airport.class).withConsistency(REQUEST_PLUS).all(); Long count = airportRepository.countFancyExpression(asList("JFK"), asList("jfk"), false); assertEquals(1, count); @@ -677,7 +757,7 @@ void deleteAllById() { void couchbaseRepositoryQuery() throws Exception { User user = new User("1", "Dave", "Wilson"); userRepository.save(user); - couchbaseTemplate.findByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS) + couchbaseTemplate.findByQuery(User.class).withConsistency(REQUEST_PLUS) .matching(QueryCriteria.where("firstname").is("Dave").and("`1`").is("`1`")).all(); String input = "findByFirstname"; Method method = UserRepository.class.getMethod(input, String.class); @@ -809,4 +889,45 @@ public ValidatingCouchbaseEventListener validationEventListener() { return new ValidatingCouchbaseEventListener(validator()); } } + + @Configuration + @EnableCouchbaseRepositories("org.springframework.data.couchbase") + @EnableCouchbaseAuditing(auditorAwareRef = "auditorAwareRef", dateTimeProviderRef = "dateTimeProviderRef") + static class ConfigRequestPlus 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(); + } + + @Bean(name = "auditorAwareRef") + public NaiveAuditorAware testAuditorAware() { + return new NaiveAuditorAware(); + } + + @Bean(name = "dateTimeProviderRef") + public DateTimeProvider testDateTimeProvider() { + return new AuditingDateTimeProvider(); + } + + @Override + public QueryScanConsistency getDefaultConsistency() { + return REQUEST_PLUS; + } + } }