From 0f3c90bea9ab50c73cec975d5b291e9dc44fe696 Mon Sep 17 00:00:00 2001
From: Mark Paluch
Date: Tue, 9 Apr 2019 13:26:04 +0200
Subject: [PATCH] DATAMONGO-1849 - Polishing.
Fix generics usage in MappingMongoJsonSchemaCreator. Make fields final. Rename MappingMongoConverter.computeWriteTarget to getWriteTarget and expose it publicly for reuse in custom DefaultTypeMapper setups without the need to subclass MappingMongoConverter.
Remove Nullability functionality for required fields as nullability indicators should originate from PersistentProperty and PreferredConstructor. Update documentation.
Related ticket: DATACMNS-1513
Original pull request: #733.
---
.../core/MappingMongoJsonSchemaCreator.java | 57 ++++++------
.../mongodb/core/MongoJsonSchemaCreator.java | 39 ++++----
.../core/convert/DefaultMongoTypeMapper.java | 45 ++++++++--
.../core/convert/MappingMongoConverter.java | 12 +--
.../data/mongodb/core/mapping/FieldType.java | 7 +-
...appingMongoJsonSchemaCreatorUnitTests.java | 88 +++----------------
src/main/asciidoc/new-features.adoc | 2 +-
.../reference/mongo-custom-conversions.adoc | 2 +-
.../asciidoc/reference/mongo-json-schema.adoc | 78 ++++++++--------
9 files changed, 147 insertions(+), 183 deletions(-)
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreator.java
index 212d5edd3..815a68994 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreator.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreator.java
@@ -21,12 +21,11 @@ import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
-import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
-import org.springframework.data.mapping.SimplePropertyHandler;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.mapping.Field;
+import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty.ObjectJsonSchemaProperty;
import org.springframework.data.mongodb.core.schema.JsonSchemaObject;
@@ -35,7 +34,6 @@ import org.springframework.data.mongodb.core.schema.JsonSchemaProperty;
import org.springframework.data.mongodb.core.schema.MongoJsonSchema;
import org.springframework.data.mongodb.core.schema.MongoJsonSchema.MongoJsonSchemaBuilder;
import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject;
-import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
@@ -45,26 +43,28 @@ import org.springframework.util.ObjectUtils;
* {@link MongoJsonSchemaCreator} implementation using both {@link MongoConverter} and {@link MappingContext} to obtain
* domain type meta information which considers {@link org.springframework.data.mongodb.core.mapping.Field field names}
* and {@link org.springframework.data.mongodb.core.convert.MongoCustomConversions custom conversions}.
- *
+ *
* @author Christoph Strobl
+ * @author Mark Paluch
* @since 2.2
*/
class MappingMongoJsonSchemaCreator implements MongoJsonSchemaCreator {
- private MongoConverter converter;
- private MappingContext mappingContext;
+ private final MongoConverter converter;
+ private final MappingContext, MongoPersistentProperty> mappingContext;
/**
* Create a new instance of {@link MappingMongoJsonSchemaCreator}.
*
* @param converter must not be {@literal null}.
*/
+ @SuppressWarnings("unchecked")
MappingMongoJsonSchemaCreator(MongoConverter converter) {
Assert.notNull(converter, "Converter must not be null!");
this.converter = converter;
- this.mappingContext = converter.getMappingContext();
-
+ this.mappingContext = (MappingContext, MongoPersistentProperty>) converter
+ .getMappingContext();
}
/*
@@ -74,7 +74,7 @@ class MappingMongoJsonSchemaCreator implements MongoJsonSchemaCreator {
@Override
public MongoJsonSchema createSchemaFor(Class> type) {
- PersistentEntity, ?> entity = mappingContext.getPersistentEntity(type);
+ MongoPersistentEntity> entity = mappingContext.getRequiredPersistentEntity(type);
MongoJsonSchemaBuilder schemaBuilder = MongoJsonSchema.builder();
List schemaProperties = computePropertiesForEntity(Collections.emptyList(), entity);
@@ -84,35 +84,33 @@ class MappingMongoJsonSchemaCreator implements MongoJsonSchemaCreator {
}
- private List computePropertiesForEntity(List path,
- PersistentEntity, ?> entity) {
+ private List computePropertiesForEntity(List path,
+ MongoPersistentEntity> entity) {
List schemaProperties = new ArrayList<>();
- entity.doWithProperties((SimplePropertyHandler) nested -> {
- ArrayList currentPath = new ArrayList<>(path);
+ for (MongoPersistentProperty nested : entity) {
+
+ List currentPath = new ArrayList<>(path);
if (path.contains(nested)) { // cycle guard
schemaProperties.add(createSchemaProperty(computePropertyFieldName(CollectionUtils.lastElement(currentPath)),
Object.class, false));
- return;
+ break;
}
currentPath.add(nested);
- JsonSchemaProperty jsonSchemaProperty = computeSchemaForProperty(currentPath, entity);
- if (jsonSchemaProperty != null) {
- schemaProperties.add(jsonSchemaProperty);
- }
- });
+ schemaProperties.add(computeSchemaForProperty(currentPath));
+ }
return schemaProperties;
}
- private JsonSchemaProperty computeSchemaForProperty(List path, PersistentEntity, ?> parent) {
+ private JsonSchemaProperty computeSchemaForProperty(List path) {
- PersistentProperty property = CollectionUtils.lastElement(path);
+ MongoPersistentProperty property = CollectionUtils.lastElement(path);
- boolean required = isRequiredProperty(parent, property);
+ boolean required = isRequiredProperty(property);
Class> rawTargetType = computeTargetType(property); // target type before conversion
Class> targetType = converter.getTypeMapper().getWriteTargetTypeFor(rawTargetType); // conversion target type
@@ -133,12 +131,12 @@ class MappingMongoJsonSchemaCreator implements MongoJsonSchemaCreator {
return createSchemaProperty(fieldName, targetType, required);
}
- private JsonSchemaProperty createObjectSchemaPropertyForEntity(List path,
- PersistentProperty property, boolean required) {
+ private JsonSchemaProperty createObjectSchemaPropertyForEntity(List path,
+ MongoPersistentProperty property, boolean required) {
ObjectJsonSchemaProperty target = JsonSchemaProperty.object(property.getName());
List nestedProperties = computePropertiesForEntity(path,
- mappingContext.getPersistentEntity(property));
+ mappingContext.getRequiredPersistentEntity(property));
return createPotentiallyRequiredSchemaProperty(
target.properties(nestedProperties.toArray(new JsonSchemaProperty[0])), required);
@@ -147,6 +145,7 @@ class MappingMongoJsonSchemaCreator implements MongoJsonSchemaCreator {
private JsonSchemaProperty createEnumSchemaProperty(String fieldName, Class> targetType, boolean required) {
List
- *
+ *
* @author Christoph Strobl
* @since 2.2
*/
@@ -66,7 +67,7 @@ public interface MongoJsonSchemaCreator {
* @param mongoConverter must not be {@literal null}.
* @return new instance of {@link MongoJsonSchemaCreator}.
*/
- static MongoJsonSchemaCreator jsonSchemaCreator(MongoConverter mongoConverter) {
+ static MongoJsonSchemaCreator create(MongoConverter mongoConverter) {
Assert.notNull(mongoConverter, "MongoConverter must not be null!");
return new MappingMongoJsonSchemaCreator(mongoConverter);
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapper.java
index ee3b9aaa2..b16681561 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapper.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapper.java
@@ -15,14 +15,16 @@
*/
package org.springframework.data.mongodb.core.convert;
-import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.function.Function;
+import java.util.function.UnaryOperator;
import org.bson.Document;
import org.bson.conversions.Bson;
+
+import org.springframework.data.convert.CustomConversions;
import org.springframework.data.convert.DefaultTypeMapper;
import org.springframework.data.convert.SimpleTypeInformationMapper;
import org.springframework.data.convert.TypeAliasAccessor;
@@ -59,29 +61,58 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper implements M
private final TypeAliasAccessor accessor;
private final @Nullable String typeKey;
- private Function, Class>> writeTarget = it -> it;
+ private UnaryOperator> writeTarget = UnaryOperator.identity();
+ /**
+ * Create a new {@link MongoTypeMapper} with fully-qualified type hints using {@code _class}.
+ */
public DefaultMongoTypeMapper() {
this(DEFAULT_TYPE_KEY);
}
+ /**
+ * Create a new {@link MongoTypeMapper} with fully-qualified type hints using {@code typeKey}.
+ *
+ * @param typeKey name of the field to read and write type hints. Can be {@literal null} to disable type hints.
+ */
public DefaultMongoTypeMapper(@Nullable String typeKey) {
- this(typeKey, Arrays.asList(new SimpleTypeInformationMapper()));
+ this(typeKey, Collections.singletonList(new SimpleTypeInformationMapper()));
}
+ /**
+ * Create a new {@link MongoTypeMapper} with fully-qualified type hints using {@code typeKey}.
+ *
+ * @param typeKey name of the field to read and write type hints. Can be {@literal null} to disable type hints.
+ * @param mappingContext the mapping context.
+ */
public DefaultMongoTypeMapper(@Nullable String typeKey,
MappingContext extends PersistentEntity, ?>, ?> mappingContext) {
this(typeKey, new DocumentTypeAliasAccessor(typeKey), mappingContext,
- Arrays.asList(new SimpleTypeInformationMapper()));
+ Collections.singletonList(new SimpleTypeInformationMapper()));
}
+ /**
+ * Create a new {@link MongoTypeMapper} with fully-qualified type hints using {@code typeKey}. Uses
+ * {@link UnaryOperator} to apply {@link CustomConversions}.
+ *
+ * @param typeKey name of the field to read and write type hints. Can be {@literal null} to disable type hints.
+ * @param mappingContext the mapping context to look up types using type hints.
+ * @see MappingMongoConverter#getWriteTarget(Class)
+ */
public DefaultMongoTypeMapper(@Nullable String typeKey,
- MappingContext extends PersistentEntity, ?>, ?> mappingContext, Function, Class>> writeTarget) {
+ MappingContext extends PersistentEntity, ?>, ?> mappingContext, UnaryOperator> writeTarget) {
this(typeKey, new DocumentTypeAliasAccessor(typeKey), mappingContext,
- Arrays.asList(new SimpleTypeInformationMapper()));
+ Collections.singletonList(new SimpleTypeInformationMapper()));
this.writeTarget = writeTarget;
}
+ /**
+ * Create a new {@link MongoTypeMapper} with fully-qualified type hints using {@code typeKey}. Uses
+ * {@link TypeInformationMapper} to map type hints.
+ *
+ * @param typeKey name of the field to read and write type hints. Can be {@literal null} to disable type hints.
+ * @param mappers
+ */
public DefaultMongoTypeMapper(@Nullable String typeKey, List extends TypeInformationMapper> mappers) {
this(typeKey, new DocumentTypeAliasAccessor(typeKey), null, mappers);
}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java
index ea1dd87cd..0d0e7a685 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java
@@ -34,6 +34,7 @@ import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -122,7 +123,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
this.dbRefResolver = dbRefResolver;
this.mappingContext = mappingContext;
this.typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, mappingContext,
- this::computeWriteTarget);
+ this::getWriteTarget);
this.idMapper = new QueryMapper(this);
this.spELContext = new SpELContext(DocumentPropertyAccessor.INSTANCE);
@@ -672,7 +673,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
if (!property.isDbReference()) {
if (property.hasExplicitWriteTarget()) {
- return writeCollectionInternal(collection, new HijackedTypeInformation<>(property), new ArrayList<>());
+ return writeCollectionInternal(collection, new TypeInformationWrapper<>(property), new ArrayList<>());
}
return writeCollectionInternal(collection, property.getTypeInformation(), new BasicDBList());
}
@@ -1608,6 +1609,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @param ref
* @return
*/
+ @Nullable
Document readRef(DBRef ref) {
return dbRefResolver.fetch(ref);
}
@@ -1630,7 +1632,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @return
* @since 2.2
*/
- protected Class> computeWriteTarget(Class> source) {
+ public Class> getWriteTarget(Class> source) {
return conversions.getCustomWriteTarget(source).orElse(source);
}
@@ -1702,12 +1704,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
}
- private static class HijackedTypeInformation implements TypeInformation {
+ private static class TypeInformationWrapper implements TypeInformation {
private MongoPersistentProperty persistentProperty;
private TypeInformation> delegate;
- public HijackedTypeInformation(MongoPersistentProperty property) {
+ public TypeInformationWrapper(MongoPersistentProperty property) {
this.persistentProperty = property;
this.delegate = property.getTypeInformation();
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/FieldType.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/FieldType.java
index 544d497c2..f550e8a58 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/FieldType.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/FieldType.java
@@ -31,8 +31,9 @@ import org.bson.types.ObjectId;
*
* Bson types are identified by a {@code byte} {@link #getBsonType() value}. This enumeration typically returns the
* according bson type value except for {@link #IMPLICIT} which is a marker to derive the field type from a property.
- *
+ *
* @author Mark Paluch
+ * @author Christoph Strobl
* @since 2.2
* @see org.bson.BsonType
*/
@@ -67,7 +68,7 @@ public enum FieldType {
/**
* Returns the BSON type identifier. Can be {@code -1} if {@link FieldType} maps to a synthetic Bson type.
- *
+ *
* @return the BSON type identifier. Can be {@code -1} if {@link FieldType} maps to a synthetic Bson type.
*/
public int getBsonType() {
@@ -76,7 +77,7 @@ public enum FieldType {
/**
* Returns the Java class used to represent the type.
- *
+ *
* @return the Java class used to represent the type.
*/
public Class> getJavaClass() {
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreatorUnitTests.java
index 03b6fc27a..de77ee6b0 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreatorUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MappingMongoJsonSchemaCreatorUnitTests.java
@@ -15,15 +15,17 @@
*/
package org.springframework.data.mongodb.core;
+import static org.springframework.data.mongodb.test.util.Assertions.*;
+
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
-import org.assertj.core.api.Assertions;
import org.bson.Document;
import org.junit.Before;
import org.junit.Test;
+
import org.springframework.data.annotation.Transient;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
@@ -34,10 +36,12 @@ import org.springframework.data.mongodb.core.mapping.FieldType;
import org.springframework.data.mongodb.core.mapping.MongoId;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.schema.MongoJsonSchema;
-import org.springframework.lang.Nullable;
/**
+ * Unit tests for {@link MappingMongoJsonSchemaCreator}.
+ *
* @author Christoph Strobl
+ * @author Mark Paluch
*/
public class MappingMongoJsonSchemaCreatorUnitTests {
@@ -58,52 +62,25 @@ public class MappingMongoJsonSchemaCreatorUnitTests {
MongoJsonSchema schema = schemaCreator.createSchemaFor(VariousFieldTypes.class);
- Assertions.assertThat(schema.toDocument().get("$jsonSchema", Document.class))
- .isEqualTo(Document.parse(VARIOUS_FIELD_TYPES));
- }
-
- @Test // DATAMONGO-1849
- public void requiredCtorArgs() {
-
- MongoJsonSchema schema = schemaCreator.createSchemaFor(RequiredArgsCtor.class);
- Assertions.assertThat(schema.toDocument().get("$jsonSchema", Document.class))
- .isEqualTo(Document.parse(REQUIRED_ARGS_CTOR));
- }
-
- @Test // DATAMONGO-1849
- public void withNestedObject() {
-
- MongoJsonSchema schema = schemaCreator.createSchemaFor(WithNestedDomainType.class);
- Assertions.assertThat(schema.toDocument().get("$jsonSchema", Document.class))
- .isEqualTo(Document.parse(WITH_NESTED_DOMAIN_TYPE));
- }
-
- @Test // DATAMONGO-1849
- public void withNestedThatHasRequiredFieldsObject() {
-
- MongoJsonSchema schema = schemaCreator.createSchemaFor(WithNestedDomainTypeHavingRequiredCtor.class);
-
- Assertions.assertThat(schema.toDocument().get("$jsonSchema", Document.class))
- .isEqualTo(Document.parse(WITH_NESTED_DOMAIN_TYPE_HAVING_REQUIRED_CTOR));
+ assertThat(schema.toDocument().get("$jsonSchema", Document.class)).isEqualTo(Document.parse(VARIOUS_FIELD_TYPES));
}
@Test // DATAMONGO-1849
public void withRemappedIdType() {
MongoJsonSchema schema = schemaCreator.createSchemaFor(WithExplicitMongoIdTypeMapping.class);
- Assertions.assertThat(schema.toDocument().get("$jsonSchema", Document.class))
- .isEqualTo(Document.parse(WITH_EXPLICIT_MONGO_ID_TYPE_MAPPING));
+ assertThat(schema.toDocument().get("$jsonSchema", Document.class)).isEqualTo(WITH_EXPLICIT_MONGO_ID_TYPE_MAPPING);
}
@Test // DATAMONGO-1849
public void cyclic() {
MongoJsonSchema schema = schemaCreator.createSchemaFor(Cyclic.class);
- Assertions.assertThat(schema.toDocument().get("$jsonSchema", Document.class)).isEqualTo(Document.parse(CYCLIC));
+ assertThat(schema.toDocument().get("$jsonSchema", Document.class)).isEqualTo(CYCLIC);
}
@Test // DATAMONGO-1849
- public void convterRegisterd() {
+ public void converterRegistered() {
MappingMongoConverter converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext);
MongoCustomConversions mcc = new MongoCustomConversions(
@@ -114,8 +91,8 @@ public class MappingMongoJsonSchemaCreatorUnitTests {
schemaCreator = new MappingMongoJsonSchemaCreator(converter);
MongoJsonSchema schema = schemaCreator.createSchemaFor(WithNestedDomainType.class);
- Assertions.assertThat(schema.toDocument().get("$jsonSchema", Document.class)).isEqualTo(Document.parse(
- "{ 'type' : 'object', 'properties' : { '_id' : { 'type' : 'object' }, 'nested' : { 'type' : 'object' } } }"));
+ assertThat(schema.toDocument().get("$jsonSchema", Document.class)).isEqualTo(
+ "{ 'type' : 'object', 'properties' : { '_id' : { 'type' : 'object' }, 'nested' : { 'type' : 'object' } } }");
}
// --> TYPES AND JSON
@@ -171,32 +148,6 @@ public class MappingMongoJsonSchemaCreatorUnitTests {
JustSomeEnum enumProperty;
}
- // --> REQUIRED ARGS (CTOR)
-
- static final String REQUIRED_ARGS_CTOR = "" + //
- "{" + //
- " 'type' : 'object'," + //
- " 'required' : ['requiredCtorArg']," + //
- " 'properties' : {" + //
- " 'requiredCtorArg' : { 'type' : 'string' }," + //
- " 'nullableCtorArg' : { 'type' : 'string' }," + //
- " 'optionalArg' : { 'type' : 'string' }" + //
- " }" + //
- "}";
-
- static class RequiredArgsCtor {
-
- String requiredCtorArg;
- @Nullable String nullableCtorArg;
- String optionalArg;
-
- public RequiredArgsCtor(String requiredCtorArg, @Nullable String nullableCtorArg) {
-
- this.requiredCtorArg = requiredCtorArg;
- this.nullableCtorArg = nullableCtorArg;
- }
- }
-
// --> NESTED DOMAIN TYPE
static final String WITH_NESTED_DOMAIN_TYPE = "" + //
@@ -214,21 +165,6 @@ public class MappingMongoJsonSchemaCreatorUnitTests {
VariousFieldTypes nested;
}
- static final String WITH_NESTED_DOMAIN_TYPE_HAVING_REQUIRED_CTOR = "" + //
- "{" + //
- " 'type' : 'object'," + //
- " 'properties' : {" + //
- " '_id' : { 'type' : 'object' }," + //
- " 'nested' : " + REQUIRED_ARGS_CTOR + //
- " }" + //
- "}";
-
- static class WithNestedDomainTypeHavingRequiredCtor {
-
- String id;
- RequiredArgsCtor nested;
- }
-
// --> EXPLICIT MONGO_ID MAPPING
final String WITH_EXPLICIT_MONGO_ID_TYPE_MAPPING = "" + //
diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc
index bff1c7aa1..56d296206 100644
--- a/src/main/asciidoc/new-features.adoc
+++ b/src/main/asciidoc/new-features.adoc
@@ -13,7 +13,7 @@
* Changed behavior of `Reactive/MongoOperations#count` now limiting the range to count matches within by passing on _offset_ & _limit_ to the server.
* Kotlin extension methods accepting `KClass` are deprecated now in favor of `reified` methods.
* Support of array filters in `Update` operations.
-* <> from domain types.
+* <> from domain types.
[[new-features.2-1-0]]
== What's New in Spring Data MongoDB 2.1
diff --git a/src/main/asciidoc/reference/mongo-custom-conversions.adoc b/src/main/asciidoc/reference/mongo-custom-conversions.adoc
index 90d6be1aa..c823e6a81 100644
--- a/src/main/asciidoc/reference/mongo-custom-conversions.adoc
+++ b/src/main/asciidoc/reference/mongo-custom-conversions.adoc
@@ -2,7 +2,7 @@
== Custom Conversions - Overriding Default Mapping
The most trivial way of influencing the the mapping result is by specifying the desired native MongoDB target type via the
-`@Field` annotation. This allows to work with non mongoDB types like `BigDecimal` in the domain model while persisting
+`@Field` annotation. This allows to work with non MongoDB types like `BigDecimal` in the domain model while persisting
values in native `org.bson.types.Decimal128` format.
.Explicit target type mapping
diff --git a/src/main/asciidoc/reference/mongo-json-schema.adoc b/src/main/asciidoc/reference/mongo-json-schema.adoc
index e53d63b3e..2f1bcf840 100644
--- a/src/main/asciidoc/reference/mongo-json-schema.adoc
+++ b/src/main/asciidoc/reference/mongo-json-schema.adoc
@@ -87,15 +87,14 @@ template.createCollection(Person.class, CollectionOptions.empty().schema(schema)
====
[[mongo.jsonSchema.generated]]
-==== Generating the Schema
+==== Generating a Schema
-Setting up a schema can be a time consuming task and we encourage everyone who decides to do so, to really take the time
-it takes. It's important, schema changes can be hard. However there might be times when one does not want to balked
-with it, and that is where the `JsonSchemaCreator` comes into play.
+Setting up a schema can be a time consuming task and we encourage everyone who decides to do so, to really take the time it takes.
+It's important, schema changes can be hard.
+However, there might be times when one does not want to balked with it, and that is where `JsonSchemaCreator` comes into play.
-The `JsonSchemaCreator` and its default implementation generate the `MongoJsonSchema` out of the domain types metadata provided
-by the mapping infrastructure. This means that <> as well as potential <>
-are considered.
+`JsonSchemaCreator` and its default implementation generates a `MongoJsonSchema` out of domain types metadata provided by the mapping infrastructure.
+This means, that <> as well as potential <> are considered.
.Generate Json Schema from domain type
====
@@ -103,25 +102,24 @@ are considered.
----
public class Person {
- private final String firstname; <1>
- private final @Nullable String lastname; <2>
- private int age; <3>
- private Species species; <4>
- private Address address; <5>
- private @Field(fieldType=SCRIPT) String theForce; <6>
- private @Transient Boolean useTheForce; <7>
+ private final String firstname; <1>
+ private final int age; <2>
+ private Species species; <3>
+ private Address address; <4>
+ private @Field(fieldType=SCRIPT) String theForce; <5>
+ private @Transient Boolean useTheForce; <6>
- public Person(String firstname, @Nullable String lastname) { <1> <2>
+ public Person(String firstname, int age) { <1> <2>
this.firstname = firstname;
- this.lastname = lastname;
+ this.age = age;
}
// gettter / setter omitted
}
-MongoJsonSchema schema = schemaCreator.jsonSchemaCreator(mongoOperations.getConverter())
- .createSchemaFor(DomainType.class);
+MongoJsonSchema schema = MongoJsonSchemaCreator.create(mongoOperations.getConverter())
+ .createSchemaFor(Person.class);
template.createCollection(Person.class, CollectionOptions.empty().schema(schema));
----
@@ -130,38 +128,36 @@ template.createCollection(Person.class, CollectionOptions.empty().schema(schema)
----
{
'type' : 'object',
- 'required' : ['firstname', 'age'], <1> <3>
+ 'required' : ['age'], <2>
'properties' : {
- 'firstname' : { 'type' : 'string' }, <1>
- 'lastname' : { 'type' : 'string' }, <2>
- 'age' : { 'bsonType' : 'int' } <3>
- 'species' : { <4>
+ 'firstname' : { 'type' : 'string' }, <1>
+ 'age' : { 'bsonType' : 'int' } <2>
+ 'species' : { <3>
'type' : 'string',
'enum' : ['HUMAN', 'WOOKIE', 'UNKNOWN']
}
- 'address' : { <5>
+ 'address' : { <4>
'type' : 'object'
'properties' : {
'postCode' : { 'type': 'string' }
}
},
- 'theForce' : { 'type' : 'javascript'} <6>
+ 'theForce' : { 'type' : 'javascript'} <5>
}
}
----
-<1> Required property as **not** `@Nullable` and used in the constructor.
-<2> Optional property though used in the constructor it is still `@Nullable`.
-<3> Primitive types are considered required properties.
-<4> Enums are restricted to possible values.
-<5> Object type properties get are inspected themselfes.
-<6> `String` type property that is truned into `Code` by the mapping.
-<7> `@Transient` properties are left out when generating the schema.
+<1> Simple object properties are consideres regular properties.
+<2> Primitive types are considered required properties
+<3> Enums are restricted to possible values.
+<4> Object type properties are inspected and represented as nested documents.
+<5> `String` type property that is converted to `Code` by the converter.
+<6> `@Transient` properties are omitted when generating the schema.
====
NOTE: `_id` properties using types that can be converted into `ObjectId` like `String` are mapped to `{ type : 'object' }`
unless there is more specific information available via the `@MongoId` annotation.
-[cols="3,1,6", options="header"]
+[cols="2,2,6", options="header"]
.Sepcial Schema Generation rules
|===
| Java
@@ -169,33 +165,33 @@ unless there is more specific information available via the `@MongoId` annotatio
| Notes
| `Object`
-| type : object
+| `type : object`
| with `properties` if metadata available.
| `Collection`
-| type : array
+| `type : array`
| -
| `Map`
-| type : object
+| `type : object`
| -
| `Enum`
-| type : string
+| `type : string`
| with `enum` property holding the possible enumeration values.
| `array`
-| type : array
+| `type : array`
| simple type array unless it's a `byte[]`
| `byte[]`
-| bsonType : binData
+| `bsonType : binData`
| -
|===
[[mongo.jsonSchema.query]]
-==== Query a collection for matching Json Schema
+==== Query a collection for matching JSON Schema
You can use a schema to query any collection for documents that match a given structure defined by a JSON schema, as the following example shows:
@@ -210,7 +206,7 @@ template.find(query(matchingDocumentStructure(schema)), Person.class);
====
[[mongo.jsonSchema.types]]
-==== Json Schema Types
+==== JSON Schema Types
The following table shows the supported JSON schema types: