From fbf9b3eb29ce6122eba07b96bfb3225d677e488d Mon Sep 17 00:00:00 2001 From: mikereiche Date: Wed, 3 Jun 2020 21:16:57 -0700 Subject: [PATCH] DATACOUCH-545 - return null if not found instead of throwing an exception --- ...activeFindByAnalyticsOperationSupport.java | 10 ++-- .../ReactiveFindByIdOperationSupport.java | 10 +++- .../ReactiveFindByQueryOperationSupport.java | 52 +++++++++---------- ...ouchbaseTemplateQueryIntegrationTests.java | 16 +++++- 4 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByAnalyticsOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByAnalyticsOperationSupport.java index 3aaf6e96..598048ba 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByAnalyticsOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByAnalyticsOperationSupport.java @@ -67,7 +67,7 @@ public class ReactiveFindByAnalyticsOperationSupport implements ReactiveFindByAn @Override public Mono one() { - return all().single(); + return all().singleOrEmpty(); } @Override @@ -79,8 +79,8 @@ public class ReactiveFindByAnalyticsOperationSupport implements ReactiveFindByAn public Flux all() { return Flux.defer(() -> { String statement = assembleEntityQuery(false); - return template.getCouchbaseClientFactory().getCluster().reactive().analyticsQuery(statement, buildAnalyticsOptions()) - .onErrorMap(throwable -> { + return template.getCouchbaseClientFactory().getCluster().reactive() + .analyticsQuery(statement, buildAnalyticsOptions()).onErrorMap(throwable -> { if (throwable instanceof RuntimeException) { return template.potentiallyConvertRuntimeException((RuntimeException) throwable); } else { @@ -100,8 +100,8 @@ public class ReactiveFindByAnalyticsOperationSupport implements ReactiveFindByAn public Mono count() { return Mono.defer(() -> { String statement = assembleEntityQuery(true); - return template.getCouchbaseClientFactory().getCluster().reactive().analyticsQuery(statement, buildAnalyticsOptions()) - .onErrorMap(throwable -> { + return template.getCouchbaseClientFactory().getCluster().reactive() + .analyticsQuery(statement, buildAnalyticsOptions()).onErrorMap(throwable -> { if (throwable instanceof RuntimeException) { return template.potentiallyConvertRuntimeException((RuntimeException) throwable); } else { diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByIdOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByIdOperationSupport.java index 88475248..a58ffbf1 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByIdOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByIdOperationSupport.java @@ -17,6 +17,7 @@ package org.springframework.data.couchbase.core; import static com.couchbase.client.java.kv.GetOptions.*; +import com.couchbase.client.core.error.DocumentNotFoundException; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -66,7 +67,14 @@ public class ReactiveFindByIdOperationSupport implements ReactiveFindByIdOperati } return template.getCollection(collection).reactive().get(docId, options); }).map(result -> template.support().decodeEntity(id, result.contentAs(String.class), result.cas(), domainType)) - .onErrorMap(throwable -> { + .onErrorResume(throwable -> { + if (throwable instanceof RuntimeException) { + if (throwable instanceof DocumentNotFoundException) { + return Mono.empty(); + } + } + return Mono.error(throwable); + }).onErrorMap(throwable -> { if (throwable instanceof RuntimeException) { return template.potentiallyConvertRuntimeException((RuntimeException) throwable); } else { 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 94b6ff98..09f8d81a 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java @@ -50,8 +50,8 @@ public class ReactiveFindByQueryOperationSupport implements ReactiveFindByQueryO private final Query query; private final QueryScanConsistency scanConsistency; - ReactiveFindByQuerySupport(final ReactiveCouchbaseTemplate template, final Class domainType, - final Query query, final QueryScanConsistency scanConsistency) { + ReactiveFindByQuerySupport(final ReactiveCouchbaseTemplate template, final Class domainType, final Query query, + final QueryScanConsistency scanConsistency) { this.template = template; this.domainType = domainType; this.query = query; @@ -70,7 +70,7 @@ public class ReactiveFindByQueryOperationSupport implements ReactiveFindByQueryO @Override public Mono one() { - return all().single(); + return all().singleOrEmpty(); } @Override @@ -82,20 +82,20 @@ public class ReactiveFindByQueryOperationSupport implements ReactiveFindByQueryO public Flux all() { return Flux.defer(() -> { String statement = assembleEntityQuery(false); - return template.getCouchbaseClientFactory().getCluster().reactive().query(statement, - query.buildQueryOptions(scanConsistency)).onErrorMap(throwable -> { - if (throwable instanceof RuntimeException) { - return template.potentiallyConvertRuntimeException((RuntimeException) throwable); - } else { - return throwable; - } - }).flatMapMany(ReactiveQueryResult::rowsAsObject).map(row -> { - String id = row.getString(TemplateUtils.SELECT_ID); - long cas = row.getLong(TemplateUtils.SELECT_CAS); - row.removeKey(TemplateUtils.SELECT_ID); - row.removeKey(TemplateUtils.SELECT_CAS); - return template.support().decodeEntity(id, row.toString(), cas, domainType); - }); + return template.getCouchbaseClientFactory().getCluster().reactive() + .query(statement, query.buildQueryOptions(scanConsistency)).onErrorMap(throwable -> { + if (throwable instanceof RuntimeException) { + return template.potentiallyConvertRuntimeException((RuntimeException) throwable); + } else { + return throwable; + } + }).flatMapMany(ReactiveQueryResult::rowsAsObject).map(row -> { + String id = row.getString(TemplateUtils.SELECT_ID); + long cas = row.getLong(TemplateUtils.SELECT_CAS); + row.removeKey(TemplateUtils.SELECT_ID); + row.removeKey(TemplateUtils.SELECT_CAS); + return template.support().decodeEntity(id, row.toString(), cas, domainType); + }); }); } @@ -103,15 +103,15 @@ public class ReactiveFindByQueryOperationSupport implements ReactiveFindByQueryO public Mono count() { return Mono.defer(() -> { String statement = assembleEntityQuery(true); - return template.getCouchbaseClientFactory().getCluster().reactive().query(statement, - query.buildQueryOptions(scanConsistency)).onErrorMap(throwable -> { - if (throwable instanceof RuntimeException) { - return template.potentiallyConvertRuntimeException((RuntimeException) throwable); - } else { - return throwable; - } - }).flatMapMany(ReactiveQueryResult::rowsAsObject).map( - row -> row.getLong(TemplateUtils.SELECT_COUNT)).next(); + return template.getCouchbaseClientFactory().getCluster().reactive() + .query(statement, query.buildQueryOptions(scanConsistency)).onErrorMap(throwable -> { + if (throwable instanceof RuntimeException) { + return template.potentiallyConvertRuntimeException((RuntimeException) throwable); + } else { + return throwable; + } + }).flatMapMany(ReactiveQueryResult::rowsAsObject).map(row -> row.getLong(TemplateUtils.SELECT_COUNT)) + .next(); }); } diff --git a/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateQueryIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateQueryIntegrationTests.java index 7bf82884..64be7d9d 100644 --- a/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateQueryIntegrationTests.java @@ -46,6 +46,7 @@ import org.springframework.data.couchbase.util.IgnoreWhen; import com.couchbase.client.core.error.IndexExistsException; import com.couchbase.client.java.query.QueryScanConsistency; +import reactor.core.publisher.Mono; /** * Query tests Theses tests rely on a cb server running @@ -58,6 +59,7 @@ class CouchbaseTemplateQueryIntegrationTests extends ClusterAwareIntegrationTest private static CouchbaseClientFactory couchbaseClientFactory; private CouchbaseTemplate couchbaseTemplate; + private ReactiveCouchbaseTemplate reactiveCouchbaseTemplate; @BeforeAll static void beforeAll() { @@ -79,6 +81,7 @@ class CouchbaseTemplateQueryIntegrationTests extends ClusterAwareIntegrationTest void beforeEach() { ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class); couchbaseTemplate = (CouchbaseTemplate) ac.getBean(COUCHBASE_TEMPLATE); + reactiveCouchbaseTemplate = (ReactiveCouchbaseTemplate) ac.getBean(REACTIVE_COUCHBASE_TEMPLATE); } @Test @@ -111,9 +114,17 @@ class CouchbaseTemplateQueryIntegrationTests extends ClusterAwareIntegrationTest assertEquals(auditUser, u.getLastModifiedBy()); assertEquals(auditMillis, u.getLastModifiedDate()); } + couchbaseTemplate.findById(User.class).one(user1.getId()); + reactiveCouchbaseTemplate.findById(User.class).one(user1.getId()).block(); } finally { couchbaseTemplate.removeByQuery(User.class).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"); + } @Test @@ -128,8 +139,9 @@ class CouchbaseTemplateQueryIntegrationTests extends ClusterAwareIntegrationTest couchbaseTemplate.removeByQuery(User.class).consistentWith(QueryScanConsistency.REQUEST_PLUS).all(); - assertThrows(DataRetrievalFailureException.class, () -> couchbaseTemplate.findById(User.class).one(user1.getId())); - assertThrows(DataRetrievalFailureException.class, () -> couchbaseTemplate.findById(User.class).one(user2.getId())); + assertNull(couchbaseTemplate.findById(User.class).one(user1.getId())); + assertNull(couchbaseTemplate.findById(User.class).one(user2.getId())); + } }