Skip to content

Commit 4b527eb

Browse files
committed
Bump couchbase sdk to 3_4_3.
Requires some refactoring around @Stability.Internal APIs. Also fixed a test to get it to pass. Closes #1661,#1662.
1 parent 020693e commit 4b527eb

File tree

7 files changed

+80
-51
lines changed

7 files changed

+80
-51
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
</parent>
1919

2020
<properties>
21-
<couchbase>3.4.1</couchbase>
22-
<couchbase.osgi>3.4.1</couchbase.osgi>
21+
<couchbase>3.4.3</couchbase>
22+
<couchbase.osgi>3.4.3</couchbase.osgi>
2323
<springdata.commons>3.1.0-SNAPSHOT</springdata.commons>
2424
<java-module-name>spring.data.couchbase</java-module-name>
2525
<hibernate.validator>7.0.1.Final</hibernate.validator>

src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.springframework.data.couchbase.core;
1717

18+
import com.couchbase.client.core.api.query.CoreQueryContext;
19+
import com.couchbase.client.core.io.CollectionIdentifier;
1820
import reactor.core.publisher.Flux;
1921

2022
import java.util.Optional;
@@ -28,7 +30,6 @@
2830
import org.springframework.data.couchbase.core.support.TemplateUtils;
2931
import org.springframework.util.Assert;
3032

31-
import com.couchbase.client.core.deps.com.fasterxml.jackson.databind.node.ObjectNode;
3233
import com.couchbase.client.java.ReactiveScope;
3334
import com.couchbase.client.java.json.JsonObject;
3435
import com.couchbase.client.java.query.QueryOptions;
@@ -100,11 +101,10 @@ public Flux<RemoveResult> all() {
100101
} else {
101102
TransactionQueryOptions opts = OptionsBuilder
102103
.buildTransactionQueryOptions(buildQueryOptions(pArgs.getOptions()));
103-
ObjectNode convertedOptions = com.couchbase.client.java.transactions.internal.OptionsUtil
104-
.createTransactionOptions(pArgs.getScope() == null ? null : rs, statement, opts);
104+
CoreQueryContext queryContext = CollectionIdentifier.DEFAULT_SCOPE.equals(rs.name()) ? null : CoreQueryContext.of(rs.bucketName(), rs.name());
105105
return transactionContext.get().getCore()
106-
.queryBlocking(statement, template.getBucketName(), pArgs.getScope(), convertedOptions, false)
107-
.flatMapIterable(result -> result.rows).map(row -> {
106+
.queryBlocking(statement, queryContext, opts.builder().build(), false)
107+
.flatMapIterable(result -> result.collectRows()).map(row -> {
108108
JsonObject json = JsonObject.fromJson(row.data());
109109
return new RemoveResult(json.getString(TemplateUtils.SELECT_ID), json.getLong(TemplateUtils.SELECT_CAS),
110110
Optional.empty());

src/main/java/org/springframework/data/couchbase/core/query/N1QLQuery.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ public QueryOptions getOptions() {
4141
return options;
4242
}
4343

44+
// for logging only
4445
public JsonObject n1ql() {
4546
JsonObject query = JsonObject.create().put("statement", expression.toString());
46-
options.build().injectParams(query);
47+
query.put("options", OptionsBuilder.getQueryOpts(options.build()));
4748
return query;
4849
}
4950

src/main/java/org/springframework/data/couchbase/core/query/OptionsBuilder.java

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.couchbase.core.query;
1717

18+
import static com.couchbase.client.core.util.Validators.notNull;
1819
import static org.springframework.data.couchbase.core.query.Meta.MetaKey.RETRY_STRATEGY;
1920
import static org.springframework.data.couchbase.core.query.Meta.MetaKey.SCAN_CONSISTENCY;
2021
import static org.springframework.data.couchbase.core.query.Meta.MetaKey.TIMEOUT;
@@ -24,9 +25,13 @@
2425
import java.lang.reflect.InvocationTargetException;
2526
import java.lang.reflect.Method;
2627
import java.time.Duration;
28+
import java.util.HashMap;
2729
import java.util.Map;
2830
import java.util.Optional;
2931

32+
import com.couchbase.client.core.api.query.CoreQueryScanConsistency;
33+
import com.couchbase.client.core.classic.query.ClassicCoreQueryOps;
34+
import com.couchbase.client.core.error.InvalidArgumentException;
3035
import org.slf4j.Logger;
3136
import org.slf4j.LoggerFactory;
3237
import org.springframework.core.annotation.AnnotatedElementUtils;
@@ -67,21 +72,21 @@ public class OptionsBuilder {
6772
static QueryOptions buildQueryOptions(Query query, QueryOptions options, QueryScanConsistency scanConsistency) {
6873
options = options != null ? options : QueryOptions.queryOptions();
6974
if (query.getParameters() != null) {
70-
if (query.getParameters() instanceof JsonArray) {
75+
if (query.getParameters() instanceof JsonArray && !((JsonArray) query.getParameters()).isEmpty()) {
7176
options.parameters((JsonArray) query.getParameters());
72-
} else {
77+
} else if( query.getParameters() instanceof JsonObject && !((JsonObject)query.getParameters()).isEmpty()){
7378
options.parameters((JsonObject) query.getParameters());
7479
}
7580
}
7681

7782
Meta meta = query.getMeta() != null ? query.getMeta() : new Meta();
7883
QueryOptions.Built optsBuilt = options.build();
79-
JsonObject optsJson = getQueryOpts(optsBuilt);
84+
8085
QueryScanConsistency metaQueryScanConsistency = meta.get(SCAN_CONSISTENCY) != null
8186
? ((ScanConsistency) meta.get(SCAN_CONSISTENCY)).query()
8287
: null;
8388
QueryScanConsistency qsc = fromFirst(QueryScanConsistency.NOT_BOUNDED, query.getScanConsistency(),
84-
getScanConsistency(optsJson), scanConsistency, metaQueryScanConsistency);
89+
scanConsistency(optsBuilt), scanConsistency, metaQueryScanConsistency);
8590
Duration timeout = fromFirst(Duration.ofSeconds(0), getTimeout(optsBuilt), meta.get(TIMEOUT));
8691
RetryStrategy retryStrategy = fromFirst(null, getRetryStrategy(optsBuilt), meta.get(RETRY_STRATEGY));
8792

@@ -100,6 +105,21 @@ static QueryOptions buildQueryOptions(Query query, QueryOptions options, QuerySc
100105
return options;
101106
}
102107

108+
private static QueryScanConsistency scanConsistency(QueryOptions.Built optsBuilt){
109+
CoreQueryScanConsistency scanConsistency = optsBuilt.scanConsistency();
110+
if (scanConsistency == null){
111+
return null;
112+
}
113+
switch (scanConsistency) {
114+
case NOT_BOUNDED:
115+
return QueryScanConsistency.NOT_BOUNDED;
116+
case REQUEST_PLUS:
117+
return QueryScanConsistency.REQUEST_PLUS;
118+
default:
119+
throw new InvalidArgumentException("Unknown scan consistency type " + scanConsistency, null, null);
120+
}
121+
}
122+
103123
public static TransactionQueryOptions buildTransactionQueryOptions(QueryOptions options) {
104124
QueryOptions.Built built = options.build();
105125
TransactionQueryOptions txOptions = TransactionQueryOptions.queryOptions();
@@ -110,8 +130,21 @@ public static TransactionQueryOptions buildTransactionQueryOptions(QueryOptions
110130
throw new IllegalArgumentException("QueryOptions.flexIndex is not supported in a transaction");
111131
}
112132

133+
Object value = optsJson.get("args");
134+
if(value instanceof JsonObject){
135+
txOptions.parameters((JsonObject)value);
136+
}else if(value instanceof JsonArray) {
137+
txOptions.parameters((JsonArray) value);
138+
} else if(value != null) {
139+
throw InvalidArgumentException.fromMessage(
140+
"non-null args property was neither JsonObject(namedParameters) nor JsonArray(positionalParameters) "
141+
+ value);
142+
}
143+
113144
for (Map.Entry<String, Object> entry : optsJson.toMap().entrySet()) {
114-
txOptions.raw(entry.getKey(), entry.getValue());
145+
if(!entry.getKey().equals("args")) {
146+
txOptions.raw(entry.getKey(), entry.getValue());
147+
}
115148
}
116149

117150
if (LOG.isDebugEnabled()) {
@@ -370,10 +403,8 @@ static String toString(MutateInOptions o) {
370403
return s.toString();
371404
}
372405

373-
private static JsonObject getQueryOpts(QueryOptions.Built optsBuilt) {
374-
JsonObject jo = JsonObject.create();
375-
optsBuilt.injectParams(jo);
376-
return jo;
406+
public static JsonObject getQueryOpts(QueryOptions.Built optsBuilt) {
407+
return JsonObject.fromJson(ClassicCoreQueryOps.convertOptions(optsBuilt).toString().getBytes());
377408
}
378409

379410
/**
@@ -396,18 +427,6 @@ public static <T> T fromFirst(T deflt, Object... choice) {
396427
return chosen;
397428
}
398429

399-
private static QueryScanConsistency getScanConsistency(JsonObject opts) {
400-
String str = opts.getString("scan_consistency");
401-
if ("at_plus".equals(str)) {
402-
return null;
403-
}
404-
return str == null ? null : QueryScanConsistency.valueOf(str.toUpperCase());
405-
}
406-
407-
private static JsonObject getScanVectors(JsonObject opts) {
408-
return opts.getObject("scan_vectors");
409-
}
410-
411430
private static Duration getTimeout(QueryOptions.Built optsBuilt) {
412431
Optional<Duration> timeout = optsBuilt.timeout();
413432
return timeout.isPresent() ? timeout.get() : null;

src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
import com.couchbase.client.java.query.QueryScanConsistency;
5656

5757
/**
58-
* KV tests Theses tests rely on a cb server running.
58+
* KV test - these tests rely on a cb server running.
5959
*
6060
* @author Michael Nitschinger
6161
* @author Michael Reiche
@@ -81,11 +81,11 @@ public void beforeEach() {
8181
@Test
8282
void findByIdWithLock() {
8383
try {
84-
User user = new User(UUID.randomUUID().toString(), "user1", "user1");
84+
User user = new User("1", "user1", "user1");
8585

8686
couchbaseTemplate.upsertById(User.class).one(user);
8787

88-
User foundUser = couchbaseTemplate.findById(User.class).withLock(Duration.ofSeconds(2)).one(user.getId());
88+
User foundUser = couchbaseTemplate.findById(User.class).withLock(Duration.ofSeconds(5)).one(user.getId());
8989
user.setVersion(foundUser.getVersion());// version will have changed
9090
assertEquals(user, foundUser);
9191

@@ -94,8 +94,15 @@ void findByIdWithLock() {
9494
);
9595
assertTrue(exception.retryReasons().contains(RetryReason.KV_LOCKED), "should have been locked");
9696
} finally {
97-
sleepSecs(2);
98-
couchbaseTemplate.removeByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all();
97+
for(int i=0; i< 10; i++) {
98+
sleepSecs(2);
99+
try {
100+
couchbaseTemplate.removeByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all();
101+
break;
102+
} catch (Exception e) {
103+
e.printStackTrace(); // gives IndexFailureException if the lock is still active
104+
}
105+
}
99106
}
100107

101108
}

src/test/java/org/springframework/data/couchbase/repository/query/N1qlQueryCreatorTests.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,16 @@
2525
import java.util.List;
2626
import java.util.Locale;
2727

28+
import com.couchbase.client.core.deps.com.fasterxml.jackson.databind.node.ArrayNode;
29+
import com.couchbase.client.java.query.QueryOptions;
2830
import org.junit.jupiter.api.BeforeEach;
2931
import org.junit.jupiter.api.Test;
3032
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
3133
import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
3234
import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext;
3335
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity;
3436
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
37+
import org.springframework.data.couchbase.core.query.OptionsBuilder;
3538
import org.springframework.data.couchbase.core.query.Query;
3639
import org.springframework.data.couchbase.domain.Person;
3740
import org.springframework.data.couchbase.domain.PersonRepository;
@@ -119,18 +122,17 @@ void queryParametersArray() throws Exception {
119122
QueryMethod queryMethod = new QueryMethod(method, new DefaultRepositoryMetadata(UserRepository.class),
120123
new SpelAwareProxyProjectionFactory());
121124
Query expected = (new Query()).addCriteria(where(i("firstname")).in("Oliver", "Charles"));
125+
JsonArray parameters = JsonArray.create().add(JsonArray.create().add("Oliver").add("Charles"));
126+
QueryOptions expectedQOptions = QueryOptions.queryOptions().parameters(parameters);
122127
N1qlQueryCreator creator = new N1qlQueryCreator(tree,
123128
getAccessor(getParameters(method), new Object[] { new Object[] { "Oliver", "Charles" } }), queryMethod,
124129
converter, bucketName);
125130
Query query = creator.createQuery();
126131

127-
// Query expected = (new Query()).addCriteria(where("firstname").in("Oliver", "Charles"));
128132
assertEquals(" WHERE `firstname` in $1", query.export(new int[1]));
129-
JsonObject expectedOptions = JsonObject.create();
130-
expected.buildQueryOptions(null, null).build().injectParams(expectedOptions);
131-
JsonObject actualOptions = JsonObject.create();
132-
expected.buildQueryOptions(null, null).build().injectParams(actualOptions);
133-
assertEquals(expectedOptions.removeKey("client_context_id"), actualOptions.removeKey("client_context_id"));
133+
ArrayNode expectedOptions = expected.buildQueryOptions(expectedQOptions, null).build().positionalParameters();
134+
ArrayNode actualOptions = query.buildQueryOptions(null, null).build().positionalParameters();
135+
assertEquals(expectedOptions.toString(), actualOptions.toString());
134136
}
135137

136138
@Test
@@ -148,12 +150,12 @@ void queryParametersJsonArray() throws Exception {
148150
Query query = creator.createQuery();
149151

150152
Query expected = (new Query()).addCriteria(where(i("firstname")).in("Oliver", "Charles"));
153+
JsonArray parameters = JsonArray.create().add(JsonArray.create().add("Oliver").add("Charles"));
154+
QueryOptions expectedQOptions = QueryOptions.queryOptions().parameters(parameters);
151155
assertEquals(" WHERE `firstname` in $1", query.export(new int[1]));
152-
JsonObject expectedOptions = JsonObject.create();
153-
expected.buildQueryOptions(null, null).build().injectParams(expectedOptions);
154-
JsonObject actualOptions = JsonObject.create();
155-
expected.buildQueryOptions(null, null).build().injectParams(actualOptions);
156-
assertEquals(expectedOptions.removeKey("client_context_id"), actualOptions.removeKey("client_context_id"));
156+
ArrayNode expectedOptions = expected.buildQueryOptions(expectedQOptions, null).build().positionalParameters();
157+
ArrayNode actualOptions = query.buildQueryOptions(null, null).build().positionalParameters();
158+
assertEquals(expectedOptions.toString(), actualOptions.toString());
157159
}
158160

159161
@Test
@@ -171,13 +173,13 @@ void queryParametersList() throws Exception {
171173
Query query = creator.createQuery();
172174

173175
Query expected = (new Query()).addCriteria(where(i("firstname")).in("Oliver", "Charles"));
176+
JsonArray parameters = JsonArray.create().add(JsonArray.create().add("Oliver").add("Charles"));
177+
QueryOptions expectedQOptions = QueryOptions.queryOptions().parameters(parameters);
174178

175179
assertEquals(" WHERE `firstname` in $1", query.export(new int[1]));
176-
JsonObject expectedOptions = JsonObject.create();
177-
expected.buildQueryOptions(null, null).build().injectParams(expectedOptions);
178-
JsonObject actualOptions = JsonObject.create();
179-
expected.buildQueryOptions(null, null).build().injectParams(actualOptions);
180-
assertEquals(expectedOptions.removeKey("client_context_id"), actualOptions.removeKey("client_context_id"));
180+
ArrayNode expectedOptions = expected.buildQueryOptions(expectedQOptions, null).build().positionalParameters();
181+
ArrayNode actualOptions = query.buildQueryOptions(null, null).build().positionalParameters();
182+
assertEquals(expectedOptions.toString(), actualOptions.toString());
181183
}
182184

183185
@Test

src/test/java/org/springframework/data/couchbase/util/JavaIntegrationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ public static CompletableFuture<Void> createPrimaryIndex(Cluster cluster, String
285285
options.timeout(Duration.ofSeconds(300));
286286
options.ignoreIfExists(true);
287287
final CreatePrimaryQueryIndexOptions.Built builtOpts = options.build();
288-
final String indexName = builtOpts.indexName().orElse(null);
288+
final String indexName = builtOpts.indexName();
289289

290290
String keyspace = "default:`" + bucketName + "`.`" + scopeName + "`.`" + collectionName + "`";
291291
String statement = "CREATE PRIMARY INDEX ";

0 commit comments

Comments
 (0)