diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionOptions.java
index f0cb71f8ab..5aa36164b5 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionOptions.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/CollectionOptions.java
@@ -18,6 +18,7 @@
import java.util.Optional;
import org.springframework.data.mongodb.core.query.Collation;
+import org.springframework.data.mongodb.core.validation.ValidationOptions;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -27,6 +28,7 @@
* @author Thomas Risberg
* @author Christoph Strobl
* @author Mark Paluch
+ * @author Andreas Zink
*/
public class CollectionOptions {
@@ -34,6 +36,7 @@ public class CollectionOptions {
private @Nullable Long size;
private @Nullable Boolean capped;
private @Nullable Collation collation;
+ private @Nullable ValidationOptions validation;
/**
* Constructs a new CollectionOptions
instance.
@@ -46,16 +49,17 @@ public class CollectionOptions {
*/
@Deprecated
public CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped) {
- this(size, maxDocuments, capped, null);
+ this(size, maxDocuments, capped, null, null);
}
private CollectionOptions(@Nullable Long size, @Nullable Long maxDocuments, @Nullable Boolean capped,
- @Nullable Collation collation) {
+ @Nullable Collation collation, @Nullable ValidationOptions validation) {
this.maxDocuments = maxDocuments;
this.size = size;
this.capped = capped;
this.collation = collation;
+ this.validation = validation;
}
/**
@@ -69,7 +73,7 @@ public static CollectionOptions just(Collation collation) {
Assert.notNull(collation, "Collation must not be null!");
- return new CollectionOptions(null, null, null, collation);
+ return new CollectionOptions(null, null, null, collation, null);
}
/**
@@ -79,7 +83,7 @@ public static CollectionOptions just(Collation collation) {
* @since 2.0
*/
public static CollectionOptions empty() {
- return new CollectionOptions(null, null, null, null);
+ return new CollectionOptions(null, null, null, null, null);
}
/**
@@ -90,7 +94,7 @@ public static CollectionOptions empty() {
* @since 2.0
*/
public CollectionOptions capped() {
- return new CollectionOptions(size, maxDocuments, true, collation);
+ return new CollectionOptions(size, maxDocuments, true, collation, validation);
}
/**
@@ -101,7 +105,7 @@ public CollectionOptions capped() {
* @since 2.0
*/
public CollectionOptions maxDocuments(long maxDocuments) {
- return new CollectionOptions(size, maxDocuments, capped, collation);
+ return new CollectionOptions(size, maxDocuments, capped, collation, validation);
}
/**
@@ -112,7 +116,7 @@ public CollectionOptions maxDocuments(long maxDocuments) {
* @since 2.0
*/
public CollectionOptions size(long size) {
- return new CollectionOptions(size, maxDocuments, capped, collation);
+ return new CollectionOptions(size, maxDocuments, capped, collation, validation);
}
/**
@@ -123,7 +127,18 @@ public CollectionOptions size(long size) {
* @since 2.0
*/
public CollectionOptions collation(@Nullable Collation collation) {
- return new CollectionOptions(size, maxDocuments, capped, collation);
+ return new CollectionOptions(size, maxDocuments, capped, collation, validation);
+ }
+
+ /**
+ * Create new {@link CollectionOptions} with already given settings and {@link ValidationOptions} set to given value.
+ *
+ * @param validation can be {@literal null}.
+ * @return new {@link CollectionOptions}.
+ * @since 2.1
+ */
+ public CollectionOptions validation(@Nullable ValidationOptions validation) {
+ return new CollectionOptions(size, maxDocuments, capped, collation, validation);
}
/**
@@ -163,4 +178,8 @@ public Optional getCapped() {
public Optional getCollation() {
return Optional.ofNullable(collation);
}
+
+ public Optional getValidation() {
+ return Optional.ofNullable(validation);
+ }
}
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 30cec4d918..e5d83c8702 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
@@ -149,6 +149,9 @@
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
import com.mongodb.client.model.UpdateOptions;
+import com.mongodb.client.model.ValidationAction;
+import com.mongodb.client.model.ValidationLevel;
+import com.mongodb.client.model.ValidationOptions;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.mongodb.util.JSONParseException;
@@ -173,6 +176,7 @@
* @author Laszlo Csontos
* @author Maninder Singh
* @author Borislav Rangelov
+ * @author Andreas Zink
*/
@SuppressWarnings("deprecation")
public class MongoTemplate implements MongoOperations, ApplicationContextAware, IndexOperationsProvider {
@@ -2160,6 +2164,21 @@ public MongoCollection doInDB(MongoDatabase db) throws MongoException,
co.collation(IndexConverters.fromDocument(collectionOptions.get("collation", Document.class)));
}
+ if (collectionOptions.containsKey("validator")) {
+ ValidationOptions validationOptions = new ValidationOptions();
+ validationOptions.validator(collectionOptions.get("validator", Document.class));
+
+ if (collectionOptions.containsKey("validationLevel")) {
+ validationOptions
+ .validationLevel(ValidationLevel.fromString(collectionOptions.get("validationLevel", String.class)));
+ }
+ if (collectionOptions.containsKey("validationAction")) {
+ validationOptions
+ .validationAction(ValidationAction.fromString(collectionOptions.get("validationAction", String.class)));
+ }
+ co.validationOptions(validationOptions);
+ }
+
db.createCollection(collectionName, co);
MongoCollection coll = db.getCollection(collectionName, Document.class);
@@ -2281,6 +2300,11 @@ protected Document convertToDocument(@Nullable CollectionOptions collectionOptio
collectionOptions.getSize().ifPresent(val -> document.put("size", val));
collectionOptions.getMaxDocuments().ifPresent(val -> document.put("max", val));
collectionOptions.getCollation().ifPresent(val -> document.append("collation", val.toDocument()));
+ collectionOptions.getValidation().ifPresent(val -> {
+ document.append("validator", val.getValidator().toDocument());
+ val.getValidationLevel().ifPresent(level -> document.append("validationLevel", level.getValue()));
+ val.getValidationAction().ifPresent(action -> document.append("validationAction", action.getValue()));
+ });
}
return document;
}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/CriteriaValidator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/CriteriaValidator.java
new file mode 100644
index 0000000000..c6cc303859
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/CriteriaValidator.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017 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
+ *
+ * http://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.mongodb.core.validation;
+
+import lombok.EqualsAndHashCode;
+
+import org.bson.Document;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.CriteriaDefinition;
+import org.springframework.lang.NonNull;
+import org.springframework.util.Assert;
+
+/**
+ * Utility to build a MongoDB {@code validator} based on a {@link CriteriaDefinition}.
+ *
+ * @author Andreas Zink
+ * @since 2.1
+ * @see Criteria
+ */
+@EqualsAndHashCode
+public class CriteriaValidator implements ValidatorDefinition {
+
+ private final Document document;
+
+ private CriteriaValidator(Document document) {
+ Assert.notNull(document, "Document must not be null!");
+ this.document = document;
+ }
+
+ /**
+ * Builds a {@code validator} object, which is basically setup of query operators, based on a
+ * {@link CriteriaDefinition} instance.
+ *
+ * @param criteria the criteria to build the {@code validator} from
+ * @return
+ */
+ public static CriteriaValidator fromCriteria(@NonNull CriteriaDefinition criteria) {
+ Assert.notNull(criteria, "Criteria must not be null!");
+ return new CriteriaValidator(criteria.getCriteriaObject());
+ }
+
+ @Override
+ public Document toDocument() {
+ return this.document;
+ }
+
+ @Override
+ public String toString() {
+ return document.toString();
+ }
+
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationAction.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationAction.java
new file mode 100644
index 0000000000..199e00a7d6
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationAction.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 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
+ *
+ * http://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.mongodb.core.validation;
+
+import lombok.Getter;
+
+/**
+ * Determines whether to error on invalid documents or just warn about the violations but allow invalid documents to be
+ * inserted.
+ *
+ * @author Andreas Zink
+ * @since 2.1
+ * @see MongoDB Collection Options
+ */
+public enum ValidationAction {
+
+ /**
+ * Documents must pass validation before the write occurs. Otherwise, the write operation fails. (MongoDB default)
+ */
+ ERROR("error"),
+
+ /**
+ * Documents do not have to pass validation. If the document fails validation, the write operation logs the validation
+ * failure.
+ */
+ WARN("warn");
+
+ @Getter private String value;
+
+ private ValidationAction(String value) {
+ this.value = value;
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationLevel.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationLevel.java
new file mode 100644
index 0000000000..187c63ca15
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationLevel.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017 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
+ *
+ * http://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.mongodb.core.validation;
+
+import lombok.Getter;
+
+/**
+ * Determines how strictly MongoDB applies the validation rules to existing documents during an update.
+ *
+ * @author Andreas Zink
+ * @since 2.1
+ * @see MongoDB Collection Options
+ */
+public enum ValidationLevel {
+
+ /**
+ * No validation for inserts or updates.
+ */
+ OFF("off"),
+
+ /**
+ * Apply validation rules to all inserts and all updates. (MongoDB default)
+ */
+ STRICT("strict"),
+
+ /**
+ * Apply validation rules to inserts and to updates on existing valid documents. Do not apply rules to updates on
+ * existing invalid documents.
+ */
+ MODERATE("moderate");
+
+ @Getter private String value;
+
+ private ValidationLevel(String value) {
+ this.value = value;
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationOptions.java
new file mode 100644
index 0000000000..ebb9c0baa8
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidationOptions.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2017 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
+ *
+ * http://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.mongodb.core.validation;
+
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.util.Optional;
+
+import org.springframework.data.mongodb.core.CollectionOptions;
+import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
+import org.springframework.util.Assert;
+
+/**
+ * Wraps the collection validation options.
+ *
+ * @author Andreas Zink
+ * @since 2.1
+ * @see {@link CollectionOptions}
+ * @see MongoDB Document Validation
+ * @see MongoDB Collection Options
+ */
+@EqualsAndHashCode
+@ToString
+public class ValidationOptions {
+ private ValidatorDefinition validator;
+ private ValidationLevel validationLevel;
+ private ValidationAction validationAction;
+
+ private ValidationOptions(ValidatorDefinition validator) {
+ Assert.notNull(validator, "ValidatorDefinition must not be null!");
+ this.validator = validator;
+ }
+
+ public static ValidationOptions validator(@NonNull ValidatorDefinition validator) {
+ return new ValidationOptions(validator);
+ }
+
+ public ValidationOptions validationLevel(@Nullable ValidationLevel validationLevel) {
+ this.validationLevel = validationLevel;
+ return this;
+ }
+
+ public ValidationOptions validationAction(@Nullable ValidationAction validationAction) {
+ this.validationAction = validationAction;
+ return this;
+ }
+
+ public ValidatorDefinition getValidator() {
+ return validator;
+ }
+
+ public Optional getValidationLevel() {
+ return Optional.ofNullable(validationLevel);
+ }
+
+ public Optional getValidationAction() {
+ return Optional.ofNullable(validationAction);
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidatorDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidatorDefinition.java
new file mode 100644
index 0000000000..50bcbb579a
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/validation/ValidatorDefinition.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017 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
+ *
+ * http://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.mongodb.core.validation;
+
+import org.bson.Document;
+import org.springframework.lang.NonNull;
+
+/**
+ * Provides a {@code validator} object to be used for collection validation.
+ *
+ * @author Andreas Zink
+ * @since 2.1
+ * @see MongoDB Collection Options
+ */
+public interface ValidatorDefinition {
+
+ /**
+ * @return a MongoDB {@code validator} document
+ */
+ public @NonNull Document toDocument();
+
+}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java
new file mode 100644
index 0000000000..79f90724ed
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2017 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
+ *
+ * http://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.mongodb.core;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+
+import org.bson.Document;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.validation.CriteriaValidator;
+import org.springframework.data.mongodb.core.validation.ValidationAction;
+import org.springframework.data.mongodb.core.validation.ValidationLevel;
+import org.springframework.data.mongodb.core.validation.ValidationOptions;
+import org.springframework.data.mongodb.test.util.MongoVersionRule;
+import org.springframework.data.util.Version;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import com.mongodb.MongoClient;
+
+/**
+ * @author Andreas Zink
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+public class MongoTemplateValidationTests {
+
+ public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_2_0 = MongoVersionRule.atLeast(Version.parse("3.2.0"));
+ public static final String COLLECTION_NAME = "validation-1";
+
+ @Configuration
+ static class Config extends AbstractMongoConfiguration {
+
+ @Override
+ public MongoClient mongoClient() {
+ return new MongoClient();
+ }
+
+ @Override
+ protected String getDatabaseName() {
+ return "validation-tests";
+ }
+ }
+
+ @Autowired MongoTemplate template;
+
+ @Before
+ public void setUp() {
+ template.dropCollection(COLLECTION_NAME);
+ }
+
+ @Test // DATAMONGO-1322
+ public void testCollectionWithSimpleCriteriaBasedValidation() {
+ Criteria criteria = Criteria.where("nonNullString").ne(null).type(2).and("rangedInteger").ne(null).type(16).gte(0)
+ .lte(122);
+ ValidationOptions validationOptions = ValidationOptions.validator(CriteriaValidator.fromCriteria(criteria));
+ template.createCollection(COLLECTION_NAME, CollectionOptions.empty().validation(validationOptions));
+
+ Document validator = getValidatorInfo(COLLECTION_NAME);
+ assertThat(validator.get("nonNullString")).isEqualTo(new Document("$ne", null).append("$type", 2));
+ assertThat(validator.get("rangedInteger"))
+ .isEqualTo(new Document("$ne", null).append("$type", 16).append("$gte", 0).append("$lte", 122));
+
+ template.save(new SimpleBean("hello", 101), COLLECTION_NAME);
+ try {
+ template.save(new SimpleBean(null, 101), COLLECTION_NAME);
+ Assert.fail("The collection validation was setup to check for non-null string");
+ } catch (Exception e) {
+ // ignore
+ }
+ try {
+ template.save(new SimpleBean("hello", -1), COLLECTION_NAME);
+ Assert.fail("The collection validation was setup to check for non-negative int");
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ @Test // DATAMONGO-1322
+ public void testCollectionValidationActionError() {
+ Criteria criteria = Criteria.where("name").type(2);
+ ValidationOptions validationOptions = ValidationOptions.validator(CriteriaValidator.fromCriteria(criteria))
+ .validationAction(ValidationAction.ERROR);
+ template.createCollection(COLLECTION_NAME, CollectionOptions.empty().validation(validationOptions));
+
+ String validationAction = getValidationActionInfo(COLLECTION_NAME);
+ assertThat(ValidationAction.ERROR.getValue()).isEqualTo(validationAction);
+ }
+
+ @Test // DATAMONGO-1322
+ public void testCollectionValidationActionWarn() {
+ Criteria criteria = Criteria.where("name").type(2);
+ ValidationOptions validationOptions = ValidationOptions.validator(CriteriaValidator.fromCriteria(criteria))
+ .validationAction(ValidationAction.WARN);
+ template.createCollection(COLLECTION_NAME, CollectionOptions.empty().validation(validationOptions));
+
+ String validationAction = getValidationActionInfo(COLLECTION_NAME);
+ assertThat(ValidationAction.WARN.getValue()).isEqualTo(validationAction);
+ }
+
+ @Test // DATAMONGO-1322
+ public void testCollectionValidationLevelOff() {
+ Criteria criteria = Criteria.where("name").type(2);
+ ValidationOptions validationOptions = ValidationOptions.validator(CriteriaValidator.fromCriteria(criteria))
+ .validationLevel(ValidationLevel.OFF);
+ template.createCollection(COLLECTION_NAME, CollectionOptions.empty().validation(validationOptions));
+
+ String validationAction = getValidationLevelInfo(COLLECTION_NAME);
+ assertThat(ValidationLevel.OFF.getValue()).isEqualTo(validationAction);
+ }
+
+ @Test // DATAMONGO-1322
+ public void testCollectionValidationLevelModerate() {
+ Criteria criteria = Criteria.where("name").type(2);
+ ValidationOptions validationOptions = ValidationOptions.validator(CriteriaValidator.fromCriteria(criteria))
+ .validationLevel(ValidationLevel.MODERATE);
+ template.createCollection(COLLECTION_NAME, CollectionOptions.empty().validation(validationOptions));
+
+ String validationAction = getValidationLevelInfo(COLLECTION_NAME);
+ assertThat(ValidationLevel.MODERATE.getValue()).isEqualTo(validationAction);
+ }
+
+ @Test // DATAMONGO-1322
+ public void testCollectionValidationLevelStrict() {
+ Criteria criteria = Criteria.where("name").type(2);
+ ValidationOptions validationOptions = ValidationOptions.validator(CriteriaValidator.fromCriteria(criteria))
+ .validationLevel(ValidationLevel.STRICT);
+ template.createCollection(COLLECTION_NAME, CollectionOptions.empty().validation(validationOptions));
+
+ String validationAction = getValidationLevelInfo(COLLECTION_NAME);
+ assertThat(ValidationLevel.STRICT.getValue()).isEqualTo(validationAction);
+ }
+
+ private Document getCollectionOptions(String collectionName) {
+ return getCollectionInfo(collectionName).get("options", Document.class);
+ }
+
+ private Document getValidatorInfo(String collectionName) {
+ return getCollectionOptions(collectionName).get("validator", Document.class);
+ }
+
+ private String getValidationActionInfo(String collectionName) {
+ return getCollectionOptions(collectionName).get("validationAction", String.class);
+ }
+
+ private String getValidationLevelInfo(String collectionName) {
+ return getCollectionOptions(collectionName).get("validationLevel", String.class);
+ }
+
+ private Document getCollectionInfo(String collectionName) {
+ return template.execute(db -> {
+ Document result = db.runCommand(
+ new Document().append("listCollections", 1).append("filter", new Document("name", collectionName)));
+ return (Document) result.get("cursor", Document.class).get("firstBatch", List.class).get(0);
+ });
+ }
+
+ @Data
+ @AllArgsConstructor
+ @NoArgsConstructor
+ static class SimpleBean {
+ @NotNull private String nonNullString;
+ @NotNull @Min(0) @Max(122) private Integer rangedInteger;
+ }
+
+}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorTest.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorTest.java
new file mode 100644
index 0000000000..1279680435
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/validation/CriteriaValidatorTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 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
+ *
+ * http://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.mongodb.core.validation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.bson.Document;
+import org.junit.Test;
+import org.springframework.data.mongodb.core.query.Criteria;
+
+/**
+ * @author Andreas Zink
+ */
+public class CriteriaValidatorTest {
+
+ @Test // DATAMONGO-1322
+ public void testSimpleCriteria() {
+ Criteria criteria = Criteria.where("nonNullString").ne(null).type(2).and("rangedInteger").type(16).gte(0).lte(122);
+ Document validator = CriteriaValidator.fromCriteria(criteria).toDocument();
+
+ assertThat(validator.get("nonNullString")).isEqualTo(new Document("$ne", null).append("$type", 2));
+ assertThat(validator.get("rangedInteger"))
+ .isEqualTo(new Document("$type", 16).append("$gte", 0).append("$lte", 122));
+ }
+
+ @Test(expected = IllegalArgumentException.class) // DATAMONGO-1322
+ public void testFailOnNull() {
+ CriteriaValidator.fromCriteria(null);
+ }
+}