diff --git a/pom.xml b/pom.xml
index dfb64f9ba3..0bcd005366 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.10.0.BUILD-SNAPSHOT
+ 1.10.0.DATAMONGO-1480-SNAPSHOT
pom
Spring Data MongoDB
diff --git a/spring-data-mongodb-cross-store/pom.xml b/spring-data-mongodb-cross-store/pom.xml
index ae0a5d6c8f..a667639a06 100644
--- a/spring-data-mongodb-cross-store/pom.xml
+++ b/spring-data-mongodb-cross-store/pom.xml
@@ -6,7 +6,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.10.0.BUILD-SNAPSHOT
+ 1.10.0.DATAMONGO-1480-SNAPSHOT
../pom.xml
@@ -48,7 +48,7 @@
org.springframework.data
spring-data-mongodb
- 1.10.0.BUILD-SNAPSHOT
+ 1.10.0.DATAMONGO-1480-SNAPSHOT
diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml
index 2d02722262..50fff77434 100644
--- a/spring-data-mongodb-distribution/pom.xml
+++ b/spring-data-mongodb-distribution/pom.xml
@@ -13,7 +13,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.10.0.BUILD-SNAPSHOT
+ 1.10.0.DATAMONGO-1480-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb-log4j/pom.xml b/spring-data-mongodb-log4j/pom.xml
index ee5e3336db..bc1bc34ce7 100644
--- a/spring-data-mongodb-log4j/pom.xml
+++ b/spring-data-mongodb-log4j/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.10.0.BUILD-SNAPSHOT
+ 1.10.0.DATAMONGO-1480-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 8072d3f665..e8d7bf18dc 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -11,7 +11,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.10.0.BUILD-SNAPSHOT
+ 1.10.0.DATAMONGO-1480-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
index 11960330b4..e26cd4d413 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
@@ -93,6 +93,7 @@
import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions;
import org.springframework.data.mongodb.core.mapreduce.MapReduceResults;
import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Meta;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
@@ -139,6 +140,7 @@
* @author Christoph Strobl
* @author Doménique Tilleuil
* @author Niko Schmuck
+ * @author Mark Paluch
*/
@SuppressWarnings("deprecation")
public class MongoTemplate implements MongoOperations, ApplicationContextAware {
@@ -2249,7 +2251,7 @@ public DBObject doInCollection(DBCollection collection) throws MongoException, D
* @author Thomas Darimont
*/
- static interface DbObjectCallback {
+ interface DbObjectCallback {
T doWith(DBObject object);
}
@@ -2347,23 +2349,49 @@ public DBCursor prepare(DBCursor cursor) {
DBCursor cursorToUse = cursor.copy();
try {
+
if (query.getSkip() > 0) {
cursorToUse = cursorToUse.skip(query.getSkip());
}
+
if (query.getLimit() > 0) {
cursorToUse = cursorToUse.limit(query.getLimit());
}
+
if (query.getSortObject() != null) {
DBObject sortDbo = type != null ? getMappedSortObject(query, type) : query.getSortObject();
cursorToUse = cursorToUse.sort(sortDbo);
}
+
if (StringUtils.hasText(query.getHint())) {
cursorToUse = cursorToUse.hint(query.getHint());
}
+
if (query.getMeta().hasValues()) {
+
for (Entry entry : query.getMeta().values()) {
cursorToUse = cursorToUse.addSpecial(entry.getKey(), entry.getValue());
}
+
+ for (Meta.CursorOption option : query.getMeta().getFlags()) {
+
+ switch (option) {
+ case EXHAUST:
+ cursorToUse = cursorToUse.addOption(Bytes.QUERYOPTION_EXHAUST);
+ break;
+ case NO_TIMEOUT:
+ cursorToUse = cursorToUse.addOption(Bytes.QUERYOPTION_NOTIMEOUT);
+ break;
+ case PARTIAL:
+ cursorToUse = cursorToUse.addOption(Bytes.QUERYOPTION_PARTIAL);
+ break;
+ case SLAVE_OK:
+ cursorToUse = cursorToUse.addOption(Bytes.QUERYOPTION_SLAVEOK);
+ break;
+ default:
+ throw new IllegalArgumentException(String.format("%s is no supported flag.", option));
+ }
+ }
}
} catch (RuntimeException e) {
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Meta.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Meta.java
index 4b364bc596..0543966d3c 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Meta.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Meta.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 the original author or authors.
+ * Copyright 2014-2016 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.
@@ -17,8 +17,10 @@
import java.util.Collections;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.util.Assert;
@@ -30,6 +32,7 @@
*
* @author Christoph Strobl
* @author Oliver Gierke
+ * @author Mark Paluch
* @since 1.6
*/
public class Meta {
@@ -39,12 +42,13 @@ private enum MetaKey {
private String key;
- private MetaKey(String key) {
+ MetaKey(String key) {
this.key = key;
}
}
private final Map values = new LinkedHashMap(2);
+ private final Set flags = new LinkedHashSet();
/**
* @return {@literal null} if not set.
@@ -120,11 +124,32 @@ public boolean getSnapshot() {
return getValue(MetaKey.SNAPSHOT.key, false);
}
+ /**
+ * Add {@link CursorOption} influencing behavior of the {@link com.mongodb.DBCursor}.
+ *
+ * @param option must not be {@literal null}.
+ * @return
+ * @since 1.10
+ */
+ public boolean addFlag(CursorOption option) {
+
+ Assert.notNull(option, "CursorOption must not be null!");
+ return this.flags.add(option);
+ }
+
+ /**
+ * @return never {@literal null}.
+ * @since 1.10
+ */
+ public Set getFlags() {
+ return flags;
+ }
+
/**
* @return
*/
public boolean hasValues() {
- return !this.values.isEmpty();
+ return !this.values.isEmpty() || !this.flags.isEmpty();
}
/**
@@ -169,7 +194,10 @@ private T getValue(String key, T defaultValue) {
*/
@Override
public int hashCode() {
- return ObjectUtils.nullSafeHashCode(this.values);
+
+ int hash = ObjectUtils.nullSafeHashCode(this.values);
+ hash += ObjectUtils.nullSafeHashCode(this.flags);
+ return hash;
}
/*
@@ -188,6 +216,35 @@ public boolean equals(Object obj) {
}
Meta other = (Meta) obj;
- return ObjectUtils.nullSafeEquals(this.values, other.values);
+ if (!ObjectUtils.nullSafeEquals(this.values, other.values)) {
+ return false;
+ }
+ return ObjectUtils.nullSafeEquals(this.flags, other.flags);
+ }
+
+ /**
+ * {@link CursorOption} represents {@code OP_QUERY} wire protocol flags to change the behavior of queries.
+ *
+ * @author Christoph Strobl
+ * @since 1.10
+ */
+ public enum CursorOption {
+
+ /** Prevents the server from timing out idle cursors. */
+ NO_TIMEOUT,
+
+ /**
+ * Sets the cursor to return all data returned by the query at once rather than splitting the results into batches.
+ */
+ EXHAUST,
+
+ /** Allows querying of a replica slave. */
+ SLAVE_OK,
+
+ /**
+ * Sets the cursor to return partial data from a query against a sharded cluster in which some shards do not respond
+ * rather than throwing an error.
+ */
+ PARTIAL
}
}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java
index b8bb5957bd..cd2668baee 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2015 the original author or authors.
+ * Copyright 2010-2016 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.
@@ -41,6 +41,7 @@
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
+ * @author Mark Paluch
*/
public class Query {
@@ -336,6 +337,50 @@ public Query useSnapshot() {
return this;
}
+ /**
+ * @return
+ * @see org.springframework.data.mongodb.core.query.Meta.CursorOption#NO_TIMEOUT
+ * @since 1.10
+ */
+ public Query noCursorTimeout() {
+
+ meta.addFlag(Meta.CursorOption.NO_TIMEOUT);
+ return this;
+ }
+
+ /**
+ * @return
+ * @see org.springframework.data.mongodb.core.query.Meta.CursorOption#EXHAUST
+ * @since 1.10
+ */
+ public Query exhaust() {
+
+ meta.addFlag(Meta.CursorOption.EXHAUST);
+ return this;
+ }
+
+ /**
+ * @return
+ * @see org.springframework.data.mongodb.core.query.Meta.CursorOption#SLAVE_OK
+ * @since 1.10
+ */
+ public Query slaveOk() {
+
+ meta.addFlag(Meta.CursorOption.SLAVE_OK);
+ return this;
+ }
+
+ /**
+ * @return
+ * @see org.springframework.data.mongodb.core.query.Meta.CursorOption#PARTIAL
+ * @since 1.10
+ */
+ public Query partialResults() {
+
+ meta.addFlag(Meta.CursorOption.PARTIAL);
+ return this;
+ }
+
/**
* @return never {@literal null}.
* @since 1.6
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java
index 61890370bf..c953b7d3c9 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java
@@ -75,4 +75,12 @@
*/
boolean snapshot() default false;
+ /**
+ * Set {@link org.springframework.data.mongodb.core.query.Meta.CursorOption} to be used when executing query.
+ *
+ * @return never {@literal null}.
+ * @since 1.10
+ */
+ org.springframework.data.mongodb.core.query.Meta.CursorOption[] flags() default {};
+
}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java
index afbecf83d3..067928b095 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java
@@ -37,6 +37,7 @@
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
+import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
@@ -248,6 +249,13 @@ public org.springframework.data.mongodb.core.query.Meta getQueryMetaAttributes()
metaAttributes.setSnapshot(meta.snapshot());
}
+ if (!ObjectUtils.isEmpty(meta.flags())) {
+
+ for (org.springframework.data.mongodb.core.query.Meta.CursorOption option : meta.flags()) {
+ metaAttributes.addFlag(option);
+ }
+ }
+
return metaAttributes;
}
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java
index 333cfd7a72..21ca3f8c03 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2014 the original author or authors.
+ * Copyright 2011-2016 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.
@@ -32,6 +32,7 @@
import org.springframework.data.mongodb.core.query.Meta;
import org.springframework.data.mongodb.core.query.Query;
+import com.mongodb.Bytes;
import com.mongodb.DBCursor;
/**
@@ -39,6 +40,7 @@
*
* @author Oliver Gierke
* @author Christoph Strobl
+ * @author Mark Paluch
*/
@RunWith(MockitoJUnitRunner.class)
public class QueryCursorPreparerUnitTests {
@@ -61,7 +63,7 @@ public void appliesHintsCorrectly() {
Query query = query(where("foo").is("bar")).withHint("hint");
- pepare(query);
+ prepare(query);
verify(cursorToUse).hint("hint");
}
@@ -75,7 +77,7 @@ public void doesNotApplyMetaWhenEmpty() {
Query query = query(where("foo").is("bar"));
query.setMeta(new Meta());
- pepare(query);
+ prepare(query);
verify(cursor, never()).copy();
verify(cursorToUse, never()).addSpecial(any(String.class), anyObject());
@@ -89,7 +91,7 @@ public void appliesMaxScanCorrectly() {
Query query = query(where("foo").is("bar")).maxScan(100);
- pepare(query);
+ prepare(query);
verify(cursorToUse).addSpecial(eq("$maxScan"), eq(100L));
}
@@ -102,7 +104,7 @@ public void appliesMaxTimeCorrectly() {
Query query = query(where("foo").is("bar")).maxTime(1, TimeUnit.SECONDS);
- pepare(query);
+ prepare(query);
verify(cursorToUse).addSpecial(eq("$maxTimeMS"), eq(1000L));
}
@@ -115,7 +117,7 @@ public void appliesCommentCorrectly() {
Query query = query(where("foo").is("bar")).comment("spring data");
- pepare(query);
+ prepare(query);
verify(cursorToUse).addSpecial(eq("$comment"), eq("spring data"));
}
@@ -128,12 +130,25 @@ public void appliesSnapshotCorrectly() {
Query query = query(where("foo").is("bar")).useSnapshot();
- pepare(query);
+ prepare(query);
verify(cursorToUse).addSpecial(eq("$snapshot"), eq(true));
}
- private DBCursor pepare(Query query) {
+ /**
+ * @see DATAMONGO-1480
+ */
+ @Test
+ public void appliesNoCursorTimeoutCorrectly() {
+
+ Query query = query(where("foo").is("bar")).noCursorTimeout();
+
+ prepare(query);
+
+ verify(cursorToUse).addOption(Bytes.QUERYOPTION_NOTIMEOUT);
+ }
+
+ private DBCursor prepare(Query query) {
CursorPreparer preparer = new MongoTemplate(factory).new QueryCursorPreparer(query, null);
return preparer.prepare(cursor);
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractMongoQueryUnitTests.java
index 981428dfbf..7406e63341 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractMongoQueryUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractMongoQueryUnitTests.java
@@ -347,7 +347,7 @@ private interface Repo extends MongoRepository {
List findByFirstname(String firstname);
- @Meta(comment = "comment")
+ @Meta(comment = "comment", flags = {org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT})
Page findByFirstname(String firstnanme, Pageable pageable);
@Meta(comment = "comment")
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryMethodUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryMethodUnitTests.java
index efea28a23b..c45bc31eed 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryMethodUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryMethodUnitTests.java
@@ -152,7 +152,6 @@ public void createsMongoQueryMethodWithMaxExecutionTimeCorrectly() throws Except
assertThat(method.getQueryMetaAttributes().getMaxTimeMsec(), is(100L));
}
-
/**
* @see DATAMONGO-1403
*/
@@ -201,6 +200,19 @@ public void createsMongoQueryMethodWithSnapshotCorrectly() throws Exception {
assertThat(method.getQueryMetaAttributes().getSnapshot(), is(true));
}
+ /**
+ * @see DATAMONGO-1480
+ */
+ @Test
+ public void createsMongoQueryMethodWithNoCursorTimeoutCorrectly() throws Exception {
+
+ MongoQueryMethod method = queryMethod(PersonRepository.class, "metaWithNoCursorTimeout");
+
+ assertThat(method.hasQueryMetaAttributes(), is(true));
+ assertThat(method.getQueryMetaAttributes().getFlags(),
+ containsInAnyOrder(org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT));
+ }
+
/**
* @see DATAMONGO-1266
*/
@@ -250,6 +262,9 @@ interface PersonRepository extends Repository {
@Meta(snapshot = true)
List metaWithSnapshotUsage();
+ @Meta(flags = { org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT })
+ List metaWithNoCursorTimeout();
+
/**
* @see DATAMONGO-1266
*/